Support /COMMIT_MSG for change edit REST endpoints

The change edit REST endpoints to get and set file contents failed with
"409 Conflict: Invalid path: /COMMIT_MSG" if the magic file
"/COMMIT_MSG" is used to update the commit message.

This is what is currently used by PolyGerrit if you have a change edit,
open the diff via for the commit message and then try to edit and save
the file content.

Updating the commit message of change edits from the change screen
works, because that is using a dedicated REST endpoint to update the
commit message.

This fix makes the change edit REST endpoints aware of the magic file
"/COMMIT_MSG" by making them forward the request to the dedicated REST
endpoints to get/set the commit message. Alternatively PolyGerrit could
be changed to directly use these REST endpoints when the commit message
is edited.

Bug: Issue 11706
Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: I5c2ef8dbabe72e04ed61606e7b923d877efa3a23
This commit is contained in:
Edwin Kempin
2020-03-10 14:07:10 +01:00
committed by Thomas Draebing
parent 022280fcaa
commit e22bfc3afa
2 changed files with 40 additions and 6 deletions

View File

@@ -14,7 +14,10 @@
package com.google.gerrit.server.restapi.change;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.base.Strings;
import com.google.common.io.ByteStreams;
import com.google.gerrit.extensions.common.DiffWebLinkInfo;
import com.google.gerrit.extensions.common.EditInfo;
import com.google.gerrit.extensions.common.Input;
@@ -36,6 +39,7 @@ import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.WebLinks;
@@ -120,7 +124,7 @@ public class ChangeEdits implements ChildCollection<ChangeResource, ChangeEditRe
@Override
public Response<?> apply(ChangeResource resource, IdString id, Put.Input input)
throws AuthException, ResourceConflictException, IOException, OrmException,
PermissionBackendException {
PermissionBackendException, BadRequestException {
putEdit.apply(resource, id.get(), input.content);
return Response.none();
}
@@ -277,23 +281,34 @@ public class ChangeEdits implements ChildCollection<ChangeResource, ChangeEditRe
private final ChangeEditModifier editModifier;
private final GitRepositoryManager repositoryManager;
private final EditMessage editMessage;
@Inject
Put(ChangeEditModifier editModifier, GitRepositoryManager repositoryManager) {
Put(
ChangeEditModifier editModifier,
GitRepositoryManager repositoryManager,
EditMessage editMessage) {
this.editModifier = editModifier;
this.repositoryManager = repositoryManager;
this.editMessage = editMessage;
}
@Override
public Response<?> apply(ChangeEditResource rsrc, Input input)
throws AuthException, ResourceConflictException, IOException, OrmException,
PermissionBackendException {
PermissionBackendException, BadRequestException {
return apply(rsrc.getChangeResource(), rsrc.getPath(), input.content);
}
public Response<?> apply(ChangeResource rsrc, String path, RawInput newContent)
throws ResourceConflictException, AuthException, IOException, OrmException,
PermissionBackendException {
PermissionBackendException, BadRequestException {
if (Patch.COMMIT_MSG.equals(path)) {
EditMessage.Input editCommitMessageInput = new EditMessage.Input();
editCommitMessageInput.message =
new String(ByteStreams.toByteArray(newContent.getInputStream()), UTF_8);
return Response.ok(editMessage.apply(rsrc, editCommitMessageInput));
}
if (Strings.isNullOrEmpty(path) || path.charAt(0) == '/') {
throw new ResourceConflictException("Invalid path: " + path);
}
@@ -347,6 +362,7 @@ public class ChangeEdits implements ChildCollection<ChangeResource, ChangeEditRe
public static class Get implements RestReadView<ChangeEditResource> {
private final FileContentUtil fileContentUtil;
private final ProjectCache projectCache;
private final GetMessage getMessage;
@Option(
name = "--base",
@@ -355,14 +371,20 @@ public class ChangeEdits implements ChildCollection<ChangeResource, ChangeEditRe
private boolean base;
@Inject
Get(FileContentUtil fileContentUtil, ProjectCache projectCache) {
Get(FileContentUtil fileContentUtil, ProjectCache projectCache, GetMessage getMessage) {
this.fileContentUtil = fileContentUtil;
this.projectCache = projectCache;
this.getMessage = getMessage;
}
@Override
public Response<BinaryResult> apply(ChangeEditResource rsrc) throws IOException {
public Response<BinaryResult> apply(ChangeEditResource rsrc)
throws AuthException, IOException, OrmException {
try {
if (Patch.COMMIT_MSG.equals(rsrc.getPath())) {
return Response.ok(getMessage.apply(rsrc.getChangeResource()));
}
ChangeEdit edit = rsrc.getChangeEdit();
return Response.ok(
fileContentUtil.getContent(

View File

@@ -53,6 +53,7 @@ import com.google.gerrit.extensions.common.FileInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -320,6 +321,17 @@ public class ChangeEditIT extends AbstractDaemonTest {
ensureSameBytes(getFileContentOfEdit(changeId, FILE_NAME), CONTENT_NEW);
}
@Test
public void updateCommitMessageByEditingMagicCommitMsgFile() throws Exception {
createEmptyEditFor(changeId);
gApi.changes()
.id(changeId)
.edit()
.modifyFile(Patch.COMMIT_MSG, RawInputUtil.create("Foo Bar".getBytes(UTF_8)));
assertThat(getEdit(changeId)).isPresent();
ensureSameBytes(getFileContentOfEdit(changeId, Patch.COMMIT_MSG), "Foo Bar\n".getBytes(UTF_8));
}
@Test
@TestProjectInput(createEmptyCommit = false)
public void updateRootCommitMessage() throws Exception {