Merge "DeleteChangeMessage: use ID instead index of a change message"

This commit is contained in:
xchangcheng
2019-04-02 17:20:17 +00:00
committed by Gerrit Code Review
5 changed files with 52 additions and 32 deletions

View File

@@ -109,12 +109,11 @@ public class ChangeMessagesUtil {
* rather than an ID allowed us to delete the message from both NoteDb and ReviewDb. * rather than an ID allowed us to delete the message from both NoteDb and ReviewDb.
* *
* @param update change update. * @param update change update.
* @param targetMessageIdx the index of the target change message. * @param targetMessageId the id of the target change message.
* @param newMessage the new message which is going to replace the old. * @param newMessage the new message which is going to replace the old.
*/ */
// TODO(xchangcheng): Reconsider implementation now that there is only a single ID. public void replaceChangeMessage(ChangeUpdate update, String targetMessageId, String newMessage) {
public void replaceChangeMessage(ChangeUpdate update, int targetMessageIdx, String newMessage) { update.deleteChangeMessageByRewritingHistory(targetMessageId, newMessage);
update.deleteChangeMessageByRewritingHistory(targetMessageIdx, newMessage);
} }
/** /**

View File

@@ -368,9 +368,9 @@ public class ChangeUpdate extends AbstractChangeUpdate {
deleteCommentRewriterFactory.create(getChange().getId(), uuid, newMessage); deleteCommentRewriterFactory.create(getChange().getId(), uuid, newMessage);
} }
public void deleteChangeMessageByRewritingHistory(int targetMessageIdx, String newMessage) { public void deleteChangeMessageByRewritingHistory(String targetMessageId, String newMessage) {
deleteChangeMessageRewriter = deleteChangeMessageRewriter =
new DeleteChangeMessageRewriter(getChange().getId(), targetMessageIdx, newMessage); new DeleteChangeMessageRewriter(getChange().getId(), targetMessageId, newMessage);
} }
@VisibleForTesting @VisibleForTesting

View File

@@ -15,6 +15,7 @@
package com.google.gerrit.server.notedb; package com.google.gerrit.server.notedb;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.parseCommitMessageRange; import static com.google.gerrit.server.notedb.ChangeNoteUtil.parseCommitMessageRange;
import static org.eclipse.jgit.util.RawParseUtils.decode; import static org.eclipse.jgit.util.RawParseUtils.decode;
@@ -40,12 +41,12 @@ import org.eclipse.jgit.util.RawParseUtils;
public class DeleteChangeMessageRewriter implements NoteDbRewriter { public class DeleteChangeMessageRewriter implements NoteDbRewriter {
private final Change.Id changeId; private final Change.Id changeId;
private final int targetMessageIdx; private final String targetMessageId;
private final String newChangeMessage; private final String newChangeMessage;
DeleteChangeMessageRewriter(Change.Id changeId, int targetMessageIdx, String newChangeMessage) { DeleteChangeMessageRewriter(Change.Id changeId, String targetMessageId, String newChangeMessage) {
this.changeId = changeId; this.changeId = changeId;
this.targetMessageIdx = targetMessageIdx; this.targetMessageId = checkNotNull(targetMessageId);
this.newChangeMessage = newChangeMessage; this.newChangeMessage = newChangeMessage;
} }
@@ -67,21 +68,18 @@ public class DeleteChangeMessageRewriter implements NoteDbRewriter {
ObjectId newTipId = null; ObjectId newTipId = null;
RevCommit originalCommit; RevCommit originalCommit;
int idx = 0; boolean startRewrite = false;
while ((originalCommit = revWalk.next()) != null) { while ((originalCommit = revWalk.next()) != null) {
if (idx < targetMessageIdx) { boolean isTargetCommit = originalCommit.getId().getName().equals(targetMessageId);
if (!startRewrite && !isTargetCommit) {
newTipId = originalCommit; newTipId = originalCommit;
idx++;
continue; continue;
} }
startRewrite = true;
String newCommitMessage = String newCommitMessage =
(idx == targetMessageIdx) isTargetCommit ? createNewCommitMessage(originalCommit) : originalCommit.getFullMessage();
? createNewCommitMessage(originalCommit)
: originalCommit.getFullMessage();
newTipId = rewriteOneCommit(originalCommit, newTipId, newCommitMessage, inserter); newTipId = rewriteOneCommit(originalCommit, newTipId, newCommitMessage, inserter);
idx++;
} }
return newTipId; return newTipId;
} }

View File

@@ -91,7 +91,7 @@ public class DeleteChangeMessage
String newChangeMessage = String newChangeMessage =
createNewChangeMessage(user.asIdentifiedUser().getName(), input.reason); createNewChangeMessage(user.asIdentifiedUser().getName(), input.reason);
DeleteChangeMessageOp deleteChangeMessageOp = DeleteChangeMessageOp deleteChangeMessageOp =
new DeleteChangeMessageOp(resource.getChangeMessageIndex(), newChangeMessage); new DeleteChangeMessageOp(resource.getChangeMessageId(), newChangeMessage);
try (BatchUpdate batchUpdate = try (BatchUpdate batchUpdate =
updateFactory.create(resource.getChangeResource().getProject(), user, TimeUtil.nowTs())) { updateFactory.create(resource.getChangeResource().getProject(), user, TimeUtil.nowTs())) {
batchUpdate.addOp(resource.getChangeId(), deleteChangeMessageOp).execute(); batchUpdate.addOp(resource.getChangeId(), deleteChangeMessageOp).execute();
@@ -130,18 +130,18 @@ public class DeleteChangeMessage
} }
private class DeleteChangeMessageOp implements BatchUpdateOp { private class DeleteChangeMessageOp implements BatchUpdateOp {
private final int targetMessageIdx; private final String targetMessageId;
private final String newMessage; private final String newMessage;
DeleteChangeMessageOp(int targetMessageIdx, String newMessage) { DeleteChangeMessageOp(String targetMessageIdx, String newMessage) {
this.targetMessageIdx = targetMessageIdx; this.targetMessageId = targetMessageIdx;
this.newMessage = newMessage; this.newMessage = newMessage;
} }
@Override @Override
public boolean updateChange(ChangeContext ctx) { public boolean updateChange(ChangeContext ctx) {
PatchSet.Id psId = ctx.getChange().currentPatchSetId(); PatchSet.Id psId = ctx.getChange().currentPatchSetId();
changeMessagesUtil.replaceChangeMessage(ctx.getUpdate(psId), targetMessageIdx, newMessage); changeMessagesUtil.replaceChangeMessage(ctx.getUpdate(psId), targetMessageId, newMessage);
return true; return true;
} }
} }

View File

@@ -130,6 +130,20 @@ public class ChangeMessagesIT extends AbstractDaemonTest {
assertThat(messages1).containsExactlyElementsIn(messages2).inOrder(); assertThat(messages1).containsExactlyElementsIn(messages2).inOrder();
} }
@Test
public void listChangeMessagesSkippedEmpty() throws Exception {
// Change message 1: create a change.
PushOneCommit.Result result = createChange();
String changeId = result.getChangeId();
// Will be a new commit with empty change message on the meta branch.
addOneReviewWithEmptyChangeMessage(changeId);
// Change Message 2: post a review with message "message 1".
addOneReview(changeId, "message");
List<ChangeMessageInfo> messages = gApi.changes().id(changeId).messages();
assertThat(messages).hasSize(2);
}
@Test @Test
public void getOneChangeMessage() throws Exception { public void getOneChangeMessage() throws Exception {
int changeNum = createOneChangeWithMultipleChangeMessagesInHistory(); int changeNum = createOneChangeWithMultipleChangeMessagesInHistory();
@@ -217,22 +231,28 @@ public class ChangeMessagesIT extends AbstractDaemonTest {
// Commit 1: create a change. // Commit 1: create a change.
PushOneCommit.Result result = createChange(); PushOneCommit.Result result = createChange();
String changeId = result.getChangeId(); String changeId = result.getChangeId();
// Commit 2: post a review with message "message 1". // Commit 2: post an empty change message.
requestScopeOperations.setApiUser(admin.getId()); requestScopeOperations.setApiUser(admin.getId());
addOneReviewWithEmptyChangeMessage(changeId);
// Commit 3: post a review with message "message 1".
addOneReview(changeId, "message 1"); addOneReview(changeId, "message 1");
// Commit 3: amend a new patch set. // Commit 4: amend a new patch set.
requestScopeOperations.setApiUser(user.getId()); requestScopeOperations.setApiUser(user.getId());
amendChange(changeId); amendChange(changeId);
// Commit 4: post a review with message "message 2". // Commit 5: post a review with message "message 2".
addOneReview(changeId, "message 2"); addOneReview(changeId, "message 2");
// Commit 5: amend a new patch set. // Commit 6: amend a new patch set.
amendChange(changeId); amendChange(changeId);
// Commit 6: approve the change. // Commit 7: approve the change.
requestScopeOperations.setApiUser(admin.getId()); requestScopeOperations.setApiUser(admin.getId());
gApi.changes().id(changeId).current().review(ReviewInput.approve()); gApi.changes().id(changeId).current().review(ReviewInput.approve());
// commit 7: submit the change. // commit 8: submit the change.
gApi.changes().id(changeId).current().submit(); gApi.changes().id(changeId).current().submit();
// Verifies there is only 7 change messages although there are 8 commits.
List<ChangeMessageInfo> messages = gApi.changes().id(changeId).messages();
assertThat(messages).hasSize(7);
return result.getChange().getId().get(); return result.getChange().getId().get();
} }
@@ -249,6 +269,10 @@ public class ChangeMessagesIT extends AbstractDaemonTest {
gApi.changes().id(changeId).current().review(reviewInput); gApi.changes().id(changeId).current().review(reviewInput);
} }
private void addOneReviewWithEmptyChangeMessage(String changeId) throws Exception {
gApi.changes().id(changeId).current().review(new ReviewInput());
}
private void deleteOneChangeMessage( private void deleteOneChangeMessage(
int changeNum, int deletedMessageIndex, TestAccount deletedBy, String reason) int changeNum, int deletedMessageIndex, TestAccount deletedBy, String reason)
throws Exception { throws Exception {
@@ -273,8 +297,7 @@ public class ChangeMessagesIT extends AbstractDaemonTest {
assertThat(changes.stream().map(c -> c._number).collect(toSet())).contains(changeNum); assertThat(changes.stream().map(c -> c._number).collect(toSet())).contains(changeNum);
// Verifies states of commits. // Verifies states of commits.
assertMetaCommitsAfterDeletion( assertMetaCommitsAfterDeletion(commitsBefore, changeNum, id, deletedBy, reason);
commitsBefore, changeNum, deletedMessageIndex, deletedBy, reason);
} }
private void assertMessagesAfterDeletion( private void assertMessagesAfterDeletion(
@@ -313,7 +336,7 @@ public class ChangeMessagesIT extends AbstractDaemonTest {
private void assertMetaCommitsAfterDeletion( private void assertMetaCommitsAfterDeletion(
List<RevCommit> commitsBeforeDeletion, List<RevCommit> commitsBeforeDeletion,
int changeNum, int changeNum,
int deletedMessageIndex, String deletedMessageId,
TestAccount deletedBy, TestAccount deletedBy,
String deleteReason) String deleteReason)
throws Exception { throws Exception {
@@ -324,7 +347,7 @@ public class ChangeMessagesIT extends AbstractDaemonTest {
for (int i = 0; i < commitsBeforeDeletion.size(); i++) { for (int i = 0; i < commitsBeforeDeletion.size(); i++) {
RevCommit commitBefore = commitsBeforeDeletion.get(i); RevCommit commitBefore = commitsBeforeDeletion.get(i);
RevCommit commitAfter = commitsAfterDeletion.get(i); RevCommit commitAfter = commitsAfterDeletion.get(i);
if (i == deletedMessageIndex) { if (commitBefore.getId().getName().equals(deletedMessageId)) {
byte[] rawBefore = commitBefore.getRawBuffer(); byte[] rawBefore = commitBefore.getRawBuffer();
byte[] rawAfter = commitAfter.getRawBuffer(); byte[] rawAfter = commitAfter.getRawBuffer();
Charset encodingBefore = RawParseUtils.parseEncoding(rawBefore); Charset encodingBefore = RawParseUtils.parseEncoding(rawBefore);