blob: 3aa5e9c3f8a9cb89903f60995b1e75ffba5b9076 [file] [log] [blame]
// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.notedb;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.entities.LabelId.CODE_REVIEW;
import static com.google.gerrit.entities.LabelId.VERIFIED;
import static com.google.gerrit.server.notedb.ReviewerStateInternal.CC;
import static com.google.gerrit.server.notedb.ReviewerStateInternal.REMOVED;
import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.ReviewerStatusUpdate;
import com.google.gerrit.server.notedb.CommitRewriter.BackfillResult;
import com.google.gerrit.server.notedb.CommitRewriter.RunOptions;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import java.sql.Timestamp;
import java.util.List;
import java.util.stream.IntStream;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;
/** Tests for {@link CommitRewriter} */
public class CommitRewriterTest extends AbstractChangeNotesTest {
private @Inject CommitRewriter rewriter;
@Inject private ChangeNoteUtil changeNoteUtil;
@Before
public void setUp() throws Exception {}
@Test
public void validHistoryNoOp() throws Exception {
String tag = "jenkins";
Change c = newChange();
ChangeUpdate update = newUpdate(c, changeOwner);
update.setChangeMessage("verification from jenkins");
update.setTag(tag);
update.commit();
ChangeUpdate updateWithSubject = newUpdate(c, changeOwner);
updateWithSubject.setSubjectForCommit("Update with subject");
updateWithSubject.commit();
ChangeNotes notesBeforeRewrite = newNotes(c);
Ref metaRefBefore = repo.exactRef(RefNames.changeMetaRef(c.getId()));
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult backfillResult = rewriter.backfillProject(project, repo, options);
ChangeNotes notesAfterRewrite = newNotes(c);
Ref metaRefAfter = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(notesBeforeRewrite.getMetaId()).isEqualTo(notesAfterRewrite.getMetaId());
assertThat(metaRefBefore.getObjectId()).isEqualTo(metaRefAfter.getObjectId());
assertThat(backfillResult.fixedRefDiff).isEmpty();
}
@Test
public void failedVerification() throws Exception {
String tag = "jenkins";
Change c = newChange();
ChangeUpdate update = newUpdate(c, changeOwner);
update.setChangeMessage("Unknown commit " + changeOwner.getName());
update.setTag(tag);
update.commit();
ChangeUpdate updateWithSubject = newUpdate(c, changeOwner);
updateWithSubject.setSubjectForCommit("Update with subject");
updateWithSubject.commit();
ChangeNotes notesBeforeRewrite = newNotes(c);
Ref metaRefBefore = repo.exactRef(RefNames.changeMetaRef(c.getId()));
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult backfillResult = rewriter.backfillProject(project, repo, options);
assertThat(backfillResult.fixedRefDiff).isEmpty();
assertThat(backfillResult.refsStillInvalidAfterFix)
.containsExactly(RefNames.changeMetaRef(c.getId()));
ChangeNotes notesAfterRewrite = newNotes(c);
Ref metaRefAfter = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(notesBeforeRewrite.getMetaId()).isEqualTo(notesAfterRewrite.getMetaId());
assertThat(metaRefBefore.getObjectId()).isEqualTo(metaRefAfter.getObjectId());
}
@Test
public void fixAuthorIdent() throws Exception {
Change c = newChange();
Timestamp when = TimeUtil.nowTs();
PersonIdent invalidAuthorIdent =
new PersonIdent(
changeOwner.getName(),
changeNoteUtil.getAccountIdAsEmailAddress(changeOwner.getAccountId()),
when,
serverIdent.getTimeZone());
RevCommit invalidUpdateCommit =
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(c, /*changeMessage=*/ null),
invalidAuthorIdent);
ChangeUpdate validUpdate = newUpdate(c, changeOwner);
validUpdate.setChangeMessage("verification from jenkins");
validUpdate.setTag("jenkins");
validUpdate.commit();
Ref metaRefBeforeRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
ImmutableList<RevCommit> commitsBeforeRewrite = logMetaRef(repo, metaRefBeforeRewrite);
ChangeNotes notesBeforeRewrite = newNotes(c);
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult result = rewriter.backfillProject(project, repo, options);
assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
ChangeNotes notesAfterRewrite = newNotes(c);
assertThat(notesAfterRewrite.getChange().getOwner())
.isEqualTo(notesBeforeRewrite.getChange().getOwner());
Ref metaRefAfterRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(metaRefAfterRewrite.getObjectId()).isNotEqualTo(metaRefBeforeRewrite.getObjectId());
ImmutableList<RevCommit> commitsAfterRewrite = logMetaRef(repo, metaRefAfterRewrite);
int invalidCommitIndex = commitsBeforeRewrite.indexOf(invalidUpdateCommit);
assertValidCommits(
commitsBeforeRewrite, commitsAfterRewrite, ImmutableList.of(invalidCommitIndex));
RevCommit fixedUpdateCommit = commitsAfterRewrite.get(invalidCommitIndex);
PersonIdent originalAuthorIdent = invalidUpdateCommit.getAuthorIdent();
PersonIdent fixedAuthorIdent = fixedUpdateCommit.getAuthorIdent();
assertThat(originalAuthorIdent).isNotEqualTo(fixedAuthorIdent);
assertThat(fixedUpdateCommit.getAuthorIdent().getName())
.isEqualTo("Gerrit User " + changeOwner.getAccountId());
assertThat(originalAuthorIdent.getEmailAddress()).isEqualTo(fixedAuthorIdent.getEmailAddress());
assertThat(originalAuthorIdent.getWhen()).isEqualTo(fixedAuthorIdent.getWhen());
assertThat(originalAuthorIdent.getTimeZone()).isEqualTo(fixedAuthorIdent.getTimeZone());
assertThat(invalidUpdateCommit.getFullMessage()).isEqualTo(fixedUpdateCommit.getFullMessage());
assertThat(invalidUpdateCommit.getCommitterIdent())
.isEqualTo(fixedUpdateCommit.getCommitterIdent());
assertThat(fixedUpdateCommit.getFullMessage()).doesNotContain(changeOwner.getName());
List<String> commitHistoryDiff = result.fixedRefDiff.get(RefNames.changeMetaRef(c.getId()));
assertThat(commitHistoryDiff).hasSize(1);
assertThat(commitHistoryDiff.get(0)).contains("-author Change Owner <1@gerrit>");
assertThat(commitHistoryDiff.get(0)).contains("+author Gerrit User 1 <1@gerrit>");
}
@Test
public void fixRealUserFooterIdent() throws Exception {
Change c = newChange();
String realUserIdentToFix = getAccountIdentToFix(otherUser.getAccount());
RevCommit invalidUpdateCommit =
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(c, "Comment on behalf of user", "Real-user: " + realUserIdentToFix),
getAuthorIdent(changeOwner.getAccount()));
IdentifiedUser impersonatedChangeOwner =
this.userFactory.runAs(
null, changeOwner.getAccountId(), requireNonNull(otherUser).getRealUser());
ChangeUpdate impersonatedChangeMessageUpdate = newUpdate(c, impersonatedChangeOwner);
impersonatedChangeMessageUpdate.setChangeMessage("Other comment on behalf of");
impersonatedChangeMessageUpdate.commit();
Ref metaRefBeforeRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
ImmutableList<RevCommit> commitsBeforeRewrite = logMetaRef(repo, metaRefBeforeRewrite);
int invalidCommitIndex = commitsBeforeRewrite.indexOf(invalidUpdateCommit);
ChangeNotes notesBeforeRewrite = newNotes(c);
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult result = rewriter.backfillProject(project, repo, options);
assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
ChangeNotes notesAfterRewrite = newNotes(c);
assertThat(changeMessages(notesBeforeRewrite))
.containsExactly("Comment on behalf of user", "Other comment on behalf of");
assertThat(notesBeforeRewrite.getChangeMessages().get(0).getAuthor())
.isEqualTo(changeOwner.getAccountId());
assertThat(notesBeforeRewrite.getChangeMessages().get(0).getRealAuthor())
.isEqualTo(otherUser.getAccountId());
assertThat(changeMessages(notesAfterRewrite))
.containsExactly("Comment on behalf of user", "Other comment on behalf of");
assertThat(notesBeforeRewrite.getChangeMessages().get(0).getAuthor())
.isEqualTo(changeOwner.getAccountId());
assertThat(notesBeforeRewrite.getChangeMessages().get(0).getRealAuthor())
.isEqualTo(otherUser.getAccountId());
Ref metaRefAfterRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(metaRefAfterRewrite.getObjectId()).isNotEqualTo(metaRefBeforeRewrite.getObjectId());
ImmutableList<RevCommit> commitsAfterRewrite = logMetaRef(repo, metaRefAfterRewrite);
assertValidCommits(
commitsBeforeRewrite, commitsAfterRewrite, ImmutableList.of(invalidCommitIndex));
List<String> commitHistoryDiff = result.fixedRefDiff.get(RefNames.changeMetaRef(c.getId()));
assertThat(commitHistoryDiff).hasSize(1);
assertThat(commitHistoryDiff.get(0))
.isEqualTo(
"@@ -9 +9 @@\n"
+ "-Real-user: Other Account <2@gerrit>\n"
+ "+Real-user: Gerrit User 2 <2@gerrit>\n");
}
@Test
public void fixReviewerFooterIdent() throws Exception {
Change c = newChange();
String reviewerIdentToFix = getAccountIdentToFix(otherUser.getAccount());
ImmutableList<RevCommit> commitsToFix =
new ImmutableList.Builder<RevCommit>()
.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c, /*changeMessage=*/ null, "Reviewer: " + reviewerIdentToFix),
getAuthorIdent(changeOwner.getAccount())))
.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(c, /*changeMessage=*/ null, "CC: " + reviewerIdentToFix),
getAuthorIdent(otherUser.getAccount())))
.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(c, "Removed cc", "Removed: " + reviewerIdentToFix),
getAuthorIdent(changeOwner.getAccount())))
.build();
Ref metaRefBeforeRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
ImmutableList<RevCommit> commitsBeforeRewrite = logMetaRef(repo, metaRefBeforeRewrite);
ImmutableList<Integer> invalidCommits =
commitsToFix.stream()
.map(commit -> commitsBeforeRewrite.indexOf(commit))
.collect(toImmutableList());
ChangeNotes notesBeforeRewrite = newNotes(c);
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult result = rewriter.backfillProject(project, repo, options);
assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
Timestamp updateTimestamp = new Timestamp(serverIdent.getWhen().getTime());
ImmutableList<ReviewerStatusUpdate> expectedReviewerUpdates =
ImmutableList.of(
ReviewerStatusUpdate.create(
updateTimestamp, changeOwner.getAccountId(), otherUserId, REVIEWER),
ReviewerStatusUpdate.create(updateTimestamp, otherUserId, otherUserId, CC),
ReviewerStatusUpdate.create(
updateTimestamp, changeOwner.getAccountId(), otherUserId, REMOVED));
ChangeNotes notesAfterRewrite = newNotes(c);
assertThat(notesBeforeRewrite.getReviewerUpdates()).isEqualTo(expectedReviewerUpdates);
assertThat(notesAfterRewrite.getReviewerUpdates()).isEqualTo(expectedReviewerUpdates);
Ref metaRefAfterRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(metaRefAfterRewrite.getObjectId()).isNotEqualTo(metaRefBeforeRewrite.getObjectId());
ImmutableList<RevCommit> commitsAfterRewrite = logMetaRef(repo, metaRefAfterRewrite);
assertValidCommits(commitsBeforeRewrite, commitsAfterRewrite, invalidCommits);
List<String> commitHistoryDiff = result.fixedRefDiff.get(RefNames.changeMetaRef(c.getId()));
assertThat(commitHistoryDiff).hasSize(3);
assertThat(commitHistoryDiff.get(0))
.isEqualTo(
"@@ -7 +7 @@\n"
+ "-Reviewer: Other Account <2@gerrit>\n"
+ "+Reviewer: Gerrit User 2 <2@gerrit>\n");
assertThat(commitHistoryDiff.get(1))
.isEqualTo(
"@@ -7 +7 @@\n"
+ "-CC: Other Account <2@gerrit>\n"
+ "+CC: Gerrit User 2 <2@gerrit>\n");
assertThat(commitHistoryDiff.get(2))
.isEqualTo(
"@@ -9 +9 @@\n"
+ "-Removed: Other Account <2@gerrit>\n"
+ "+Removed: Gerrit User 2 <2@gerrit>\n");
}
@Test
public void fixReviewerMessage() throws Exception {
Change c = newChange();
ImmutableList.Builder<RevCommit> commitsToFix = new ImmutableList.Builder<>();
ChangeUpdate addReviewerUpdate = newUpdate(c, changeOwner);
addReviewerUpdate.putReviewer(otherUserId, REVIEWER);
addReviewerUpdate.commit();
commitsToFix.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c,
"Removed reviewer " + otherUser.getAccount().fullName(),
"Removed: " + getValidIdentAsString(otherUser.getAccount())),
getAuthorIdent(changeOwner.getAccount())));
ChangeUpdate addCcUpdate = newUpdate(c, changeOwner);
addCcUpdate.putReviewer(otherUserId, CC);
addCcUpdate.commit();
commitsToFix.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c,
"Removed cc " + otherUser.getAccount().fullName(),
"Removed: " + getValidIdentAsString(otherUser.getAccount())),
getAuthorIdent(changeOwner.getAccount())));
Ref metaRefBeforeRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
ImmutableList<RevCommit> commitsBeforeRewrite = logMetaRef(repo, metaRefBeforeRewrite);
ImmutableList<Integer> invalidCommits =
commitsToFix.build().stream()
.map(commit -> commitsBeforeRewrite.indexOf(commit))
.collect(toImmutableList());
ChangeNotes notesBeforeRewrite = newNotes(c);
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult result = rewriter.backfillProject(project, repo, options);
assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
Timestamp updateTimestamp = new Timestamp(serverIdent.getWhen().getTime());
ImmutableList<ReviewerStatusUpdate> expectedReviewerUpdates =
ImmutableList.of(
ReviewerStatusUpdate.create(
new Timestamp(addReviewerUpdate.when.getTime()),
changeOwner.getAccountId(),
otherUserId,
REVIEWER),
ReviewerStatusUpdate.create(
updateTimestamp, changeOwner.getAccountId(), otherUserId, REMOVED),
ReviewerStatusUpdate.create(
new Timestamp(addCcUpdate.when.getTime()),
changeOwner.getAccountId(),
otherUserId,
CC),
ReviewerStatusUpdate.create(
updateTimestamp, changeOwner.getAccountId(), otherUserId, REMOVED));
ChangeNotes notesAfterRewrite = newNotes(c);
assertThat(notesBeforeRewrite.getReviewerUpdates()).isEqualTo(expectedReviewerUpdates);
assertThat(changeMessages(notesBeforeRewrite))
.containsExactly("Removed reviewer Other Account", "Removed cc Other Account");
assertThat(notesAfterRewrite.getReviewerUpdates()).isEqualTo(expectedReviewerUpdates);
assertThat(changeMessages(notesAfterRewrite)).containsExactly("Removed reviewer", "Removed cc");
Ref metaRefAfterRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(metaRefAfterRewrite.getObjectId()).isNotEqualTo(metaRefBeforeRewrite.getObjectId());
ImmutableList<RevCommit> commitsAfterRewrite = logMetaRef(repo, metaRefAfterRewrite);
assertValidCommits(commitsBeforeRewrite, commitsAfterRewrite, invalidCommits);
List<String> commitHistoryDiff = result.fixedRefDiff.get(RefNames.changeMetaRef(c.getId()));
assertThat(commitHistoryDiff).hasSize(2);
assertThat(commitHistoryDiff.get(0))
.isEqualTo("@@ -6 +6 @@\n" + "-Removed reviewer Other Account\n" + "+Removed reviewer\n");
assertThat(commitHistoryDiff.get(1))
.isEqualTo("@@ -6 +6 @@\n" + "-Removed cc Other Account\n" + "+Removed cc\n");
}
@Test
public void fixLabelFooterIdent() throws Exception {
Change c = newChange();
String approverIdentToFix = getAccountIdentToFix(otherUser.getAccount());
String changeOwnerIdentToFix = getAccountIdentToFix(changeOwner.getAccount());
ChangeUpdate approvalUpdateByOtherUser = newUpdate(c, otherUser);
approvalUpdateByOtherUser.putApproval(VERIFIED, (short) -1);
approvalUpdateByOtherUser.commit();
ImmutableList<RevCommit> commitsToFix =
new ImmutableList.Builder<RevCommit>()
.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c,
/*changeMessage=*/ null,
"Label: -Verified " + approverIdentToFix,
"Label: Custom-Label-1=-1 " + approverIdentToFix,
"Label: Verified=+1",
"Label: Custom-Label-1=+1",
"Label: Custom-Label-2=+2 " + approverIdentToFix,
"Label: Custom-Label-3=0 " + approverIdentToFix),
getAuthorIdent(changeOwner.getAccount())))
.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c,
/*changeMessage=*/ null,
"Label: -Verified " + changeOwnerIdentToFix,
"Label: Custom-Label-1=+1"),
getAuthorIdent(otherUser.getAccount())))
.build();
Ref metaRefBeforeRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
ImmutableList<RevCommit> commitsBeforeRewrite = logMetaRef(repo, metaRefBeforeRewrite);
ImmutableList<Integer> invalidCommits =
commitsToFix.stream()
.map(commit -> commitsBeforeRewrite.indexOf(commit))
.collect(toImmutableList());
ChangeNotes notesBeforeRewrite = newNotes(c);
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult result = rewriter.backfillProject(project, repo, options);
assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
Timestamp updateTimestamp = new Timestamp(serverIdent.getWhen().getTime());
ImmutableList<PatchSetApproval> expectedApprovals =
ImmutableList.of(
PatchSetApproval.builder()
.key(
PatchSetApproval.key(
c.currentPatchSetId(),
changeOwner.getAccountId(),
LabelId.create(VERIFIED)))
.value(0)
.granted(updateTimestamp)
.build(),
PatchSetApproval.builder()
.key(
PatchSetApproval.key(
c.currentPatchSetId(),
changeOwner.getAccountId(),
LabelId.create("Custom-Label-1")))
.value(+1)
.granted(updateTimestamp)
.build(),
PatchSetApproval.builder()
.key(
PatchSetApproval.key(
c.currentPatchSetId(), otherUserId, LabelId.create(VERIFIED)))
.value(0)
.granted(updateTimestamp)
.build(),
PatchSetApproval.builder()
.key(
PatchSetApproval.key(
c.currentPatchSetId(), otherUserId, LabelId.create("Custom-Label-1")))
.value(+1)
.granted(updateTimestamp)
.build(),
PatchSetApproval.builder()
.key(
PatchSetApproval.key(
c.currentPatchSetId(), otherUserId, LabelId.create("Custom-Label-2")))
.value(+2)
.granted(updateTimestamp)
.build(),
PatchSetApproval.builder()
.key(
PatchSetApproval.key(
c.currentPatchSetId(), otherUserId, LabelId.create("Custom-Label-3")))
.value(0)
.granted(updateTimestamp)
.build());
ChangeNotes notesAfterRewrite = newNotes(c);
assertThat(notesBeforeRewrite.getApprovals().get(c.currentPatchSetId()))
.containsExactlyElementsIn(expectedApprovals);
assertThat(notesAfterRewrite.getApprovals().get(c.currentPatchSetId()))
.containsExactlyElementsIn(expectedApprovals);
Ref metaRefAfterRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(metaRefAfterRewrite.getObjectId()).isNotEqualTo(metaRefBeforeRewrite.getObjectId());
ImmutableList<RevCommit> commitsAfterRewrite = logMetaRef(repo, metaRefAfterRewrite);
assertValidCommits(commitsBeforeRewrite, commitsAfterRewrite, invalidCommits);
List<String> commitHistoryDiff = result.fixedRefDiff.get(RefNames.changeMetaRef(c.getId()));
assertThat(commitHistoryDiff).hasSize(2);
assertThat(commitHistoryDiff.get(0))
.isEqualTo(
"@@ -7,2 +7,2 @@\n"
+ "-Label: -Verified Other Account <2@gerrit>\n"
+ "-Label: Custom-Label-1=-1 Other Account <2@gerrit>\n"
+ "+Label: -Verified Gerrit User 2 <2@gerrit>\n"
+ "+Label: Custom-Label-1=-1 Gerrit User 2 <2@gerrit>\n"
+ "@@ -11,2 +11,2 @@\n"
+ "-Label: Custom-Label-2=+2 Other Account <2@gerrit>\n"
+ "-Label: Custom-Label-3=0 Other Account <2@gerrit>\n"
+ "+Label: Custom-Label-2=+2 Gerrit User 2 <2@gerrit>\n"
+ "+Label: Custom-Label-3=0 Gerrit User 2 <2@gerrit>\n");
assertThat(commitHistoryDiff.get(1))
.isEqualTo(
"@@ -7 +7 @@\n"
+ "-Label: -Verified Change Owner <1@gerrit>\n"
+ "+Label: -Verified Gerrit User 1 <1@gerrit>\n");
}
@Test
public void fixRemoveVoteChangeMessage() throws Exception {
Change c = newChange();
String approverIdentToFix = getAccountIdentToFix(otherUser.getAccount());
ChangeUpdate approvalUpdateByOtherUser = newUpdate(c, otherUser);
approvalUpdateByOtherUser.putApproval(CODE_REVIEW, (short) +2);
approvalUpdateByOtherUser.putApproval("Custom-Label", (short) -1);
approvalUpdateByOtherUser.putApprovalFor(changeOwner.getAccountId(), VERIFIED, (short) -1);
approvalUpdateByOtherUser.commit();
ImmutableList<RevCommit> commitsToFix =
new ImmutableList.Builder<RevCommit>()
.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c,
/*changeMessage=*/ "Removed Code-Review+2 by " + otherUser.getNameEmail(),
"Label: -Code-Review " + approverIdentToFix),
getAuthorIdent(changeOwner.getAccount())))
.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c,
/*changeMessage=*/ "Removed Custom-Label-1 by " + otherUser.getNameEmail(),
"Label: -Custom-Label " + getValidIdentAsString(otherUser.getAccount())),
getAuthorIdent(changeOwner.getAccount())))
.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c,
/*changeMessage=*/ "Removed Verified+2 by " + changeOwner.getNameEmail(),
"Label: -Verified"),
getAuthorIdent(changeOwner.getAccount())))
.build();
Ref metaRefBeforeRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
ImmutableList<RevCommit> commitsBeforeRewrite = logMetaRef(repo, metaRefBeforeRewrite);
ImmutableList<Integer> invalidCommits =
commitsToFix.stream()
.map(commit -> commitsBeforeRewrite.indexOf(commit))
.collect(toImmutableList());
ChangeNotes notesBeforeRewrite = newNotes(c);
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult result = rewriter.backfillProject(project, repo, options);
assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
Timestamp updateTimestamp = new Timestamp(serverIdent.getWhen().getTime());
ImmutableList<PatchSetApproval> expectedApprovals =
ImmutableList.of(
PatchSetApproval.builder()
.key(
PatchSetApproval.key(
c.currentPatchSetId(),
changeOwner.getAccountId(),
LabelId.create(VERIFIED)))
.value(0)
.granted(updateTimestamp)
.build(),
PatchSetApproval.builder()
.key(
PatchSetApproval.key(
c.currentPatchSetId(), otherUserId, LabelId.create("Custom-Label")))
.value(0)
.granted(updateTimestamp)
.build(),
PatchSetApproval.builder()
.key(
PatchSetApproval.key(
c.currentPatchSetId(), otherUserId, LabelId.create(CODE_REVIEW)))
.value(0)
.granted(updateTimestamp)
.build());
ChangeNotes notesAfterRewrite = newNotes(c);
assertThat(changeMessages(notesBeforeRewrite))
.containsExactly(
"Removed Code-Review+2 by Other Account <other@account.com>",
"Removed Custom-Label-1 by Other Account <other@account.com>",
"Removed Verified+2 by Change Owner <change@owner.com>");
assertThat(notesBeforeRewrite.getApprovals().get(c.currentPatchSetId()))
.containsExactlyElementsIn(expectedApprovals);
assertThat(changeMessages(notesAfterRewrite))
.containsExactly(
"Removed Code-Review+2 by <GERRIT_ACCOUNT_2>",
"Removed Custom-Label-1 by <GERRIT_ACCOUNT_2>",
"Removed Verified+2 by <GERRIT_ACCOUNT_1>");
assertThat(notesAfterRewrite.getApprovals().get(c.currentPatchSetId()))
.containsExactlyElementsIn(expectedApprovals);
Ref metaRefAfterRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(metaRefAfterRewrite.getObjectId()).isNotEqualTo(metaRefBeforeRewrite.getObjectId());
ImmutableList<RevCommit> commitsAfterRewrite = logMetaRef(repo, metaRefAfterRewrite);
assertValidCommits(commitsBeforeRewrite, commitsAfterRewrite, invalidCommits);
List<String> commitHistoryDiff = result.fixedRefDiff.get(RefNames.changeMetaRef(c.getId()));
assertThat(commitHistoryDiff).hasSize(3);
assertThat(commitHistoryDiff.get(0))
.isEqualTo(
"@@ -6 +6 @@\n"
+ "-Removed Code-Review+2 by Other Account <other@account.com>\n"
+ "+Removed Code-Review+2 by <GERRIT_ACCOUNT_2>\n"
+ "@@ -9 +9 @@\n"
+ "-Label: -Code-Review Other Account <2@gerrit>\n"
+ "+Label: -Code-Review Gerrit User 2 <2@gerrit>\n");
assertThat(commitHistoryDiff.get(1))
.isEqualTo(
"@@ -6 +6 @@\n"
+ "-Removed Custom-Label-1 by Other Account <other@account.com>\n"
+ "+Removed Custom-Label-1 by <GERRIT_ACCOUNT_2>\n");
assertThat(commitHistoryDiff.get(2))
.isEqualTo(
"@@ -6 +6 @@\n"
+ "-Removed Verified+2 by Change Owner <change@owner.com>\n"
+ "+Removed Verified+2 by <GERRIT_ACCOUNT_1>\n");
}
@Test
public void fixAttentionFooterIdent() throws Exception {
// TODO(mariasavtchouk): add once backfilling is implemented for this case.
}
@Test
public void fixSubmitChangeMessage() throws Exception {
Change c = newChange();
ImmutableList.Builder<ObjectId> commitsToFix = new ImmutableList.Builder<>();
ChangeUpdate invalidMergedMessageUpdate = newUpdate(c, changeOwner);
invalidMergedMessageUpdate.setChangeMessage(
"Change has been successfully merged by " + changeOwner.getName());
invalidMergedMessageUpdate.setTag(ChangeMessagesUtil.TAG_MERGED);
commitsToFix.add(invalidMergedMessageUpdate.commit());
ChangeUpdate invalidCherryPickedMessageUpdate = newUpdate(c, changeOwner);
invalidCherryPickedMessageUpdate.setChangeMessage(
"Change has been successfully cherry-picked as e40dc1a50dc7f457a37579e2755374f3e1a5413b by "
+ changeOwner.getName());
invalidCherryPickedMessageUpdate.setTag(ChangeMessagesUtil.TAG_MERGED);
commitsToFix.add(invalidCherryPickedMessageUpdate.commit());
ChangeUpdate invalidRebasedMessageUpdate = newUpdate(c, changeOwner);
invalidRebasedMessageUpdate.setChangeMessage(
"Change has been successfully rebased and submitted as e40dc1a50dc7f457a37579e2755374f3e1a5413b by "
+ changeOwner.getName());
invalidRebasedMessageUpdate.setTag(ChangeMessagesUtil.TAG_MERGED);
commitsToFix.add(invalidRebasedMessageUpdate.commit());
ChangeUpdate validSubmitMessageUpdate = newUpdate(c, changeOwner);
validSubmitMessageUpdate.setChangeMessage(
"Change has been successfully rebased and submitted as e40dc1a50dc7f457a37579e2755374f3e1a5413b");
validSubmitMessageUpdate.commit();
Ref metaRefBeforeRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
ImmutableList<RevCommit> commitsBeforeRewrite = logMetaRef(repo, metaRefBeforeRewrite);
ImmutableList<Integer> invalidCommits =
commitsToFix.build().stream()
.map(commit -> commitsBeforeRewrite.indexOf(commit))
.collect(toImmutableList());
ChangeNotes notesBeforeRewrite = newNotes(c);
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult result = rewriter.backfillProject(project, repo, options);
assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
ChangeNotes notesAfterRewrite = newNotes(c);
assertThat(changeMessages(notesBeforeRewrite))
.containsExactly(
"Change has been successfully merged by Change Owner",
"Change has been successfully cherry-picked as e40dc1a50dc7f457a37579e2755374f3e1a5413b by Change Owner",
"Change has been successfully rebased and submitted as e40dc1a50dc7f457a37579e2755374f3e1a5413b by Change Owner",
"Change has been successfully rebased and submitted as e40dc1a50dc7f457a37579e2755374f3e1a5413b");
assertThat(changeMessages(notesAfterRewrite))
.containsExactly(
"Change has been successfully merged",
"Change has been successfully cherry-picked as e40dc1a50dc7f457a37579e2755374f3e1a5413b",
"Change has been successfully rebased and submitted as e40dc1a50dc7f457a37579e2755374f3e1a5413b",
"Change has been successfully rebased and submitted as e40dc1a50dc7f457a37579e2755374f3e1a5413b");
Ref metaRefAfterRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(metaRefAfterRewrite.getObjectId()).isNotEqualTo(metaRefBeforeRewrite.getObjectId());
ImmutableList<RevCommit> commitsAfterRewrite = logMetaRef(repo, metaRefAfterRewrite);
assertValidCommits(commitsBeforeRewrite, commitsAfterRewrite, invalidCommits);
List<String> commitHistoryDiff = result.fixedRefDiff.get(RefNames.changeMetaRef(c.getId()));
assertThat(commitHistoryDiff).hasSize(3);
assertThat(commitHistoryDiff.get(0))
.isEqualTo(
"@@ -6 +6 @@\n"
+ "-Change has been successfully merged by Change Owner\n"
+ "+Change has been successfully merged\n");
assertThat(commitHistoryDiff.get(1))
.isEqualTo(
"@@ -6 +6 @@\n"
+ "-Change has been successfully cherry-picked as e40dc1a50dc7f457a37579e2755374f3e1a5413b by Change Owner\n"
+ "+Change has been successfully cherry-picked as e40dc1a50dc7f457a37579e2755374f3e1a5413b\n");
assertThat(commitHistoryDiff.get(2))
.isEqualTo(
"@@ -6 +6 @@\n"
+ "-Change has been successfully rebased and submitted as e40dc1a50dc7f457a37579e2755374f3e1a5413b by Change Owner\n"
+ "+Change has been successfully rebased and submitted as e40dc1a50dc7f457a37579e2755374f3e1a5413b\n");
}
@Test
public void fixSubmittedWithFooterIdent() throws Exception {
// TODO(mariasavtchouk): add once backfilling is implemented for this case.
}
@Test
public void fixDeleteChangeMessageCommitMessage() throws Exception {
Change c = newChange();
ImmutableList.Builder<ObjectId> commitsToFix = new ImmutableList.Builder<>();
ChangeUpdate invalidDeleteChangeMessageUpdate = newUpdate(c, changeOwner);
invalidDeleteChangeMessageUpdate.setChangeMessage(
"Change message removed by: " + changeOwner.getName());
commitsToFix.add(invalidDeleteChangeMessageUpdate.commit());
ChangeUpdate invalidDeleteChangeMessageUpdateWithReason = newUpdate(c, changeOwner);
invalidDeleteChangeMessageUpdateWithReason.setChangeMessage(
String.format(
"Change message removed by: %s\nReason: %s",
changeOwner.getName(), "contains confidential information"));
commitsToFix.add(invalidDeleteChangeMessageUpdateWithReason.commit());
ChangeUpdate validDeleteChangeMessageUpdate = newUpdate(c, changeOwner);
validDeleteChangeMessageUpdate.setChangeMessage(
"Change message removed by: <GERRIT_ACCOUNT_1>");
validDeleteChangeMessageUpdate.commit();
ChangeUpdate validDeleteChangeMessageUpdateWithReason = newUpdate(c, changeOwner);
validDeleteChangeMessageUpdateWithReason.setChangeMessage(
"Change message removed by: <GERRIT_ACCOUNT_1>\nReason: abusive language");
validDeleteChangeMessageUpdateWithReason.commit();
Ref metaRefBeforeRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
ImmutableList<RevCommit> commitsBeforeRewrite = logMetaRef(repo, metaRefBeforeRewrite);
ImmutableList<Integer> invalidCommits =
commitsToFix.build().stream()
.map(commit -> commitsBeforeRewrite.indexOf(commit))
.collect(toImmutableList());
ChangeNotes notesBeforeRewrite = newNotes(c);
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult result = rewriter.backfillProject(project, repo, options);
assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
ChangeNotes notesAfterRewrite = newNotes(c);
assertThat(changeMessages(notesBeforeRewrite))
.containsExactly(
"Change message removed by: Change Owner",
"Change message removed by: Change Owner\n"
+ "Reason: contains confidential information",
"Change message removed by: <GERRIT_ACCOUNT_1>",
"Change message removed by: <GERRIT_ACCOUNT_1>\n" + "Reason: abusive language");
assertThat(changeMessages(notesAfterRewrite))
.containsExactly(
"Change message removed",
"Change message removed\n" + "Reason: contains confidential information",
"Change message removed by: <GERRIT_ACCOUNT_1>",
"Change message removed by: <GERRIT_ACCOUNT_1>\n" + "Reason: abusive language");
Ref metaRefAfterRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(metaRefAfterRewrite.getObjectId()).isNotEqualTo(metaRefBeforeRewrite.getObjectId());
ImmutableList<RevCommit> commitsAfterRewrite = logMetaRef(repo, metaRefAfterRewrite);
assertValidCommits(commitsBeforeRewrite, commitsAfterRewrite, invalidCommits);
List<String> commitHistoryDiff = result.fixedRefDiff.get(RefNames.changeMetaRef(c.getId()));
assertThat(commitHistoryDiff).hasSize(2);
assertThat(commitHistoryDiff.get(0))
.isEqualTo(
"@@ -6 +6 @@\n"
+ "-Change message removed by: Change Owner\n"
+ "+Change message removed\n");
assertThat(commitHistoryDiff.get(1))
.isEqualTo(
"@@ -6 +6 @@\n"
+ "-Change message removed by: Change Owner\n"
+ "+Change message removed\n");
}
@Test
public void fixCodeOwnersChangeMessage() throws Exception {
// TODO(mariasavtchouk): add once backfilling is implemented for this case.
}
@Test
public void fixAssigneeFooterIdent() throws Exception {
Change c = newChange();
String assigneeIdentToFix = getAccountIdentToFix(changeOwner.getAccount());
RevCommit invalidUpdateCommit =
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(c, "Assignee added", "Assignee: " + assigneeIdentToFix),
getAuthorIdent(changeOwner.getAccount()));
ChangeUpdate changeAssigneeUpdate = newUpdate(c, changeOwner);
changeAssigneeUpdate.setAssignee(otherUserId);
changeAssigneeUpdate.commit();
ChangeUpdate removeAssigneeUpdate = newUpdate(c, changeOwner);
removeAssigneeUpdate.removeAssignee();
removeAssigneeUpdate.commit();
Ref metaRefBeforeRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
ImmutableList<RevCommit> commitsBeforeRewrite = logMetaRef(repo, metaRefBeforeRewrite);
int invalidCommitIndex = commitsBeforeRewrite.indexOf(invalidUpdateCommit);
ChangeNotes notesBeforeRewrite = newNotes(c);
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult result = rewriter.backfillProject(project, repo, options);
assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
ChangeNotes notesAfterRewrite = newNotes(c);
assertThat(notesBeforeRewrite.getPastAssignees())
.containsExactly(changeOwner.getAccountId(), otherUser.getAccountId());
assertThat(notesBeforeRewrite.getChange().getAssignee()).isNull();
assertThat(notesAfterRewrite.getPastAssignees())
.containsExactly(changeOwner.getAccountId(), otherUser.getAccountId());
assertThat(notesAfterRewrite.getChange().getAssignee()).isNull();
Ref metaRefAfterRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(metaRefAfterRewrite.getObjectId()).isNotEqualTo(metaRefBeforeRewrite.getObjectId());
ImmutableList<RevCommit> commitsAfterRewrite = logMetaRef(repo, metaRefAfterRewrite);
assertValidCommits(
commitsBeforeRewrite, commitsAfterRewrite, ImmutableList.of(invalidCommitIndex));
RevCommit fixedUpdateCommit = commitsAfterRewrite.get(invalidCommitIndex);
assertThat(invalidUpdateCommit.getAuthorIdent()).isEqualTo(fixedUpdateCommit.getAuthorIdent());
assertThat(invalidUpdateCommit.getCommitterIdent())
.isEqualTo(fixedUpdateCommit.getCommitterIdent());
assertThat(invalidUpdateCommit.getFullMessage())
.isNotEqualTo(fixedUpdateCommit.getFullMessage());
assertThat(fixedUpdateCommit.getFullMessage()).doesNotContain(changeOwner.getName());
assertThat(invalidUpdateCommit.getFullMessage()).contains(assigneeIdentToFix);
String expectedFixedIdent = getValidIdentAsString(changeOwner.getAccount());
assertThat(fixedUpdateCommit.getFullMessage()).contains(expectedFixedIdent);
List<String> commitHistoryDiff = result.fixedRefDiff.get(RefNames.changeMetaRef(c.getId()));
assertThat(commitHistoryDiff).hasSize(1);
assertThat(commitHistoryDiff.get(0))
.isEqualTo(
"@@ -9 +9 @@\n"
+ "-Assignee: Change Owner <1@gerrit>\n"
+ "+Assignee: Gerrit User 1 <1@gerrit>\n");
}
@Test
public void fixAssigneeChangeMessage() throws Exception {
Change c = newChange();
ImmutableList<RevCommit> commitsToFix =
new ImmutableList.Builder<RevCommit>()
.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c,
"Assignee added: " + changeOwner.getNameEmail(),
"Assignee: " + getValidIdentAsString(changeOwner.getAccount())),
getAuthorIdent(changeOwner.getAccount())))
.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c,
String.format(
"Assignee changed from: %s to: %s",
changeOwner.getNameEmail(), otherUser.getNameEmail()),
"Assignee: " + getValidIdentAsString(otherUser.getAccount())),
getAuthorIdent(changeOwner.getAccount())))
.add(
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c, "Assignee deleted: " + otherUser.getNameEmail(), "Assignee:"),
getAuthorIdent(changeOwner.getAccount())))
.build();
Ref metaRefBeforeRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
ImmutableList<RevCommit> commitsBeforeRewrite = logMetaRef(repo, metaRefBeforeRewrite);
ImmutableList<Integer> invalidCommits =
commitsToFix.stream()
.map(commit -> commitsBeforeRewrite.indexOf(commit))
.collect(toImmutableList());
ChangeNotes notesBeforeRewrite = newNotes(c);
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult result = rewriter.backfillProject(project, repo, options);
assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
ChangeNotes notesAfterRewrite = newNotes(c);
assertThat(notesBeforeRewrite.getPastAssignees())
.containsExactly(changeOwner.getAccountId(), otherUser.getAccountId());
assertThat(notesBeforeRewrite.getChange().getAssignee()).isNull();
assertThat(changeMessages(notesBeforeRewrite))
.containsExactly(
"Assignee added: Change Owner <change@owner.com>",
"Assignee changed from: Change Owner <change@owner.com> to: Other Account <other@account.com>",
"Assignee deleted: Other Account <other@account.com>");
assertThat(notesAfterRewrite.getPastAssignees())
.containsExactly(changeOwner.getAccountId(), otherUser.getAccountId());
assertThat(notesAfterRewrite.getChange().getAssignee()).isNull();
assertThat(changeMessages(notesAfterRewrite))
.containsExactly(
"Assignee added: " + ChangeMessagesUtil.getAccountTemplate(changeOwner.getAccountId()),
String.format(
"Assignee changed from: %s to: %s",
ChangeMessagesUtil.getAccountTemplate(changeOwner.getAccountId()),
ChangeMessagesUtil.getAccountTemplate(otherUser.getAccountId())),
"Assignee deleted: " + ChangeMessagesUtil.getAccountTemplate(otherUser.getAccountId()));
Ref metaRefAfterRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(metaRefAfterRewrite.getObjectId()).isNotEqualTo(metaRefBeforeRewrite.getObjectId());
ImmutableList<RevCommit> commitsAfterRewrite = logMetaRef(repo, metaRefAfterRewrite);
assertValidCommits(commitsBeforeRewrite, commitsAfterRewrite, invalidCommits);
List<String> commitHistoryDiff = result.fixedRefDiff.get(RefNames.changeMetaRef(c.getId()));
assertThat(commitHistoryDiff).hasSize(3);
assertThat(commitHistoryDiff.get(0))
.isEqualTo(
"@@ -6 +6 @@\n"
+ "-Assignee added: Change Owner <change@owner.com>\n"
+ "+Assignee added: <GERRIT_ACCOUNT_1>\n");
assertThat(commitHistoryDiff.get(1))
.isEqualTo(
"@@ -6 +6 @@\n"
+ "-Assignee changed from: Change Owner <change@owner.com> to: Other Account <other@account.com>\n"
+ "+Assignee changed from: <GERRIT_ACCOUNT_1> to: <GERRIT_ACCOUNT_2>\n");
assertThat(commitHistoryDiff.get(2))
.isEqualTo(
"@@ -6 +6 @@\n"
+ "-Assignee deleted: Other Account <other@account.com>\n"
+ "+Assignee deleted: <GERRIT_ACCOUNT_2>\n");
}
@Test
public void singleRunFixesAll() throws Exception {
Change c = newChange();
Timestamp when = TimeUtil.nowTs();
String assigneeIdentToFix = getAccountIdentToFix(otherUser.getAccount());
PersonIdent authorIdentToFix =
new PersonIdent(
changeOwner.getName(),
changeNoteUtil.getAccountIdAsEmailAddress(changeOwner.getAccountId()),
when,
serverIdent.getTimeZone());
RevCommit invalidUpdateCommit =
writeUpdate(
RefNames.changeMetaRef(c.getId()),
getChangeUpdateBody(
c,
"Assignee added: Other Account <other@account.com>",
"Assignee: " + assigneeIdentToFix),
authorIdentToFix);
Ref metaRefBeforeRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
ImmutableList<RevCommit> commitsBeforeRewrite = logMetaRef(repo, metaRefBeforeRewrite);
int invalidCommitIndex = commitsBeforeRewrite.indexOf(invalidUpdateCommit);
ChangeNotes notesBeforeRewrite = newNotes(c);
RunOptions options = new RunOptions();
options.dryRun = false;
BackfillResult result = rewriter.backfillProject(project, repo, options);
assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
ChangeNotes notesAfterRewrite = newNotes(c);
assertThat(notesBeforeRewrite.getChange().getAssignee()).isEqualTo(otherUserId);
assertThat(notesAfterRewrite.getChange().getAssignee()).isEqualTo(otherUserId);
Ref metaRefAfterRewrite = repo.exactRef(RefNames.changeMetaRef(c.getId()));
assertThat(metaRefAfterRewrite.getObjectId()).isNotEqualTo(metaRefBeforeRewrite.getObjectId());
ImmutableList<RevCommit> commitsAfterRewrite = logMetaRef(repo, metaRefAfterRewrite);
assertValidCommits(
commitsBeforeRewrite, commitsAfterRewrite, ImmutableList.of(invalidCommitIndex));
RevCommit fixedUpdateCommit = commitsAfterRewrite.get(invalidCommitIndex);
assertThat(invalidUpdateCommit.getAuthorIdent())
.isNotEqualTo(fixedUpdateCommit.getAuthorIdent());
assertThat(invalidUpdateCommit.getFullMessage()).contains(otherUser.getName());
assertThat(fixedUpdateCommit.getFullMessage()).doesNotContain(changeOwner.getName());
assertThat(fixedUpdateCommit.getFullMessage()).doesNotContain(otherUser.getName());
List<String> commitHistoryDiff = result.fixedRefDiff.get(RefNames.changeMetaRef(c.getId()));
assertThat(commitHistoryDiff).hasSize(1);
assertThat(commitHistoryDiff.get(0)).contains("-author Change Owner <1@gerrit>");
assertThat(commitHistoryDiff.get(0)).contains("+author Gerrit User 1 <1@gerrit>");
assertThat(commitHistoryDiff.get(0))
.contains(
"@@ -6 +6 @@\n"
+ "-Assignee added: Other Account <other@account.com>\n"
+ "+Assignee added: <GERRIT_ACCOUNT_2>\n"
+ "@@ -9 +9 @@\n"
+ "-Assignee: Other Account <2@gerrit>\n"
+ "+Assignee: Gerrit User 2 <2@gerrit>");
}
private RevCommit writeUpdate(String metaRef, String body, PersonIdent author) throws Exception {
return tr.branch(metaRef).commit().message(body).author(author).committer(serverIdent).create();
}
private String getChangeUpdateBody(Change change, String changeMessage, String... footers) {
StringBuilder commitBody = new StringBuilder();
commitBody.append("Update patch set " + change.currentPatchSetId().get());
commitBody.append("\n\n");
if (changeMessage != null) {
commitBody.append(changeMessage);
commitBody.append("\n\n");
}
commitBody.append("Patch-set: " + change.currentPatchSetId().get());
commitBody.append("\n");
for (String footer : footers) {
commitBody.append(footer);
commitBody.append("\n");
}
return commitBody.toString();
}
private ImmutableList<RevCommit> logMetaRef(Repository repo, Ref metaRef) throws Exception {
try (RevWalk rw = new RevWalk(repo)) {
rw.sort(RevSort.TOPO);
rw.sort(RevSort.REVERSE);
if (metaRef == null) {
return ImmutableList.of();
}
rw.markStart(rw.parseCommit(metaRef.getObjectId()));
return ImmutableList.copyOf(rw);
}
}
private void assertValidCommits(
ImmutableList<RevCommit> commitsBeforeRewrite,
ImmutableList<RevCommit> commitsAfterRewrite,
ImmutableList<Integer> invalidCommits) {
ImmutableList<RevCommit> validCommitsBeforeRewrite =
IntStream.range(0, commitsBeforeRewrite.size())
.filter(i -> !invalidCommits.contains(i))
.mapToObj(commitsBeforeRewrite::get)
.collect(ImmutableList.toImmutableList());
ImmutableList<RevCommit> validCommitsAfterRewrite =
IntStream.range(0, commitsAfterRewrite.size())
.filter(i -> !invalidCommits.contains(i))
.mapToObj(commitsAfterRewrite::get)
.collect(ImmutableList.toImmutableList());
assertThat(validCommitsBeforeRewrite).hasSize(validCommitsAfterRewrite.size());
for (int i = 0; i < validCommitsAfterRewrite.size(); i++) {
RevCommit actual = validCommitsAfterRewrite.get(i);
RevCommit expected = validCommitsBeforeRewrite.get(i);
assertThat(actual.getAuthorIdent()).isEqualTo(expected.getAuthorIdent());
assertThat(actual.getCommitterIdent()).isEqualTo(expected.getCommitterIdent());
assertThat(actual.getFullMessage()).isEqualTo(expected.getFullMessage());
}
}
private String getAccountIdentToFix(Account account) {
return String.format("%s <%s>", account.getName(), account.id().get() + "@" + serverId);
}
private String getValidIdentAsString(Account account) {
return String.format(
"%s <%s>",
ChangeNoteUtil.getAccountIdAsUsername(account.id()), account.id().get() + "@" + serverId);
}
private ImmutableList<String> changeMessages(ChangeNotes changeNotes) {
return changeNotes.getChangeMessages().stream()
.map(ChangeMessage::getMessage)
.collect(toImmutableList());
}
private PersonIdent getAuthorIdent(Account account) {
Timestamp when = TimeUtil.nowTs();
return changeNoteUtil.newAccountIdIdent(account.id(), when, serverIdent);
}
}