Don't change manually altered reviewer state If users manually changes their reviewer-state, that state should not be altered by automatically triggered reviewer-additions. Change-Id: I0e6abc0bbde7b8e0b21ab79a5a81c1c71340f1d1
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewers/AddReviewers.java b/src/main/java/com/googlesource/gerrit/plugins/reviewers/AddReviewers.java index 90f5841..43db627 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/reviewers/AddReviewers.java +++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/AddReviewers.java
@@ -28,6 +28,7 @@ import com.google.inject.assistedinject.Assisted; import java.util.ArrayList; import java.util.Set; +import java.util.stream.Collectors; /** Adds reviewers to a change. */ class AddReviewers implements Runnable { @@ -72,14 +73,30 @@ try { // TODO(davido): Switch back to using changes API again, // when it supports batch mode for adding reviewers + Set<Account.Id> existingReviewers = + gApi.changes().id(changeInfo._number).reviewers().stream() + .map(r -> Account.id(r._accountId)) + .collect(Collectors.toSet()); + /* Don't add, or change state of, already existing reviewers. */ + Set<Account.Id> reviewersToAdd = + reviewers.stream() + .filter(r -> !existingReviewers.contains(r)) + .collect(Collectors.toSet()); + /* If account is already configured to be added as reviewer, don't attempt to add as cc. */ + Set<Account.Id> ccsToAdd = + ccs.stream() + .filter(c -> !existingReviewers.contains(c)) + .filter(r -> !reviewersToAdd.contains(r)) + .collect(Collectors.toSet()); + ReviewInput in = new ReviewInput(); in.reviewers = new ArrayList<>(reviewers.size() + ccs.size()); - for (Account.Id account : reviewers) { + for (Account.Id account : reviewersToAdd) { AddReviewerInput addReviewerInput = new AddReviewerInput(); addReviewerInput.reviewer = account.toString(); in.reviewers.add(addReviewerInput); } - for (Account.Id account : ccs) { + for (Account.Id account : ccsToAdd) { AddReviewerInput input = new AddReviewerInput(); input.state = ReviewerState.CC; input.reviewer = account.toString();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewers/Reviewers.java b/src/main/java/com/googlesource/gerrit/plugins/reviewers/Reviewers.java index 42548a7..348e856 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/reviewers/Reviewers.java +++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/Reviewers.java
@@ -156,10 +156,12 @@ List<ReviewerFilter> matching = findMatchingFilters(changeNumber, filters); Set<String> reviewers = getReviewersFrom(matching); Set<String> ccs = getCcsFrom(matching); - ccs.removeAll(reviewers); if (reviewers.isEmpty() && ccs.isEmpty()) { return; } + /* Remove all reviewer identifiers (account-ids, group-ids) from ccs that are present in reviewers. + * Further filtering of individual accounts is done in AddReviewers after the ids have been resolved into Accounts. */ + ccs.removeAll(reviewers); final AddReviewers addReviewers = addReviewersFactory.create( c,
diff --git a/src/test/java/com/googlesource/gerrit/plugins/reviewers/ReviewersIT.java b/src/test/java/com/googlesource/gerrit/plugins/reviewers/ReviewersIT.java index 1cb511e..02f4902 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/reviewers/ReviewersIT.java +++ b/src/test/java/com/googlesource/gerrit/plugins/reviewers/ReviewersIT.java
@@ -26,6 +26,7 @@ import com.google.gerrit.acceptance.TestPlugin; import com.google.gerrit.entities.Account; import com.google.gerrit.entities.BranchNameKey; +import com.google.gerrit.extensions.api.changes.AddReviewerInput; import com.google.gerrit.extensions.api.changes.ReviewInput; import com.google.gerrit.extensions.client.ChangeStatus; import com.google.gerrit.extensions.client.ReviewerState; @@ -125,6 +126,43 @@ assertThat(reviewersFor(changeId)).containsExactlyElementsIn(ImmutableSet.of(user.id())); } + @Test + public void dontChangeExistingStateOfReviewer() throws Exception { + Set<Account.Id> userSet = ImmutableSet.of(user.id()); + TestAccount user2 = accountCreator.user2(); + Set<Account.Id> user2Set = ImmutableSet.of(user2.id()); + + createFilters(filter("*").reviewer(user2).cc(user)); + String changeId = createChange("refs/for/master").getChangeId(); + assertThat(ccsFor(changeId)).containsExactlyElementsIn(userSet); + assertThat(reviewersFor(changeId)).containsExactlyElementsIn(user2Set); + + addReviewer(changeId, user, ReviewerState.REVIEWER); + addReviewer(changeId, user2, ReviewerState.CC); + assertThat(reviewersFor(changeId)).containsExactlyElementsIn(userSet); + assertThat(ccsFor(changeId)).containsExactlyElementsIn(user2Set); + + amendChange(changeId); + assertThat(reviewersFor(changeId)).containsExactlyElementsIn(userSet); + assertThat(ccsFor(changeId)).containsExactlyElementsIn(user2Set); + } + + @Test + public void addAsReviewerIfConfiguredAsReviewerAndCc() throws Exception { + createFilters(filter("*").cc(user), filter("branch:master").reviewer(user)); + String changeId = createChange("refs/for/master").getChangeId(); + assertThat(reviewersFor(changeId)).containsExactlyElementsIn(ImmutableSet.of(user.id())); + assertThat(gApi.changes().id(changeId).get().reviewers.get(CC)).isNull(); + } + + private void addReviewer(String changeId, TestAccount user, ReviewerState state) + throws Exception { + AddReviewerInput input = new AddReviewerInput(); + input.reviewer = user.id().toString(); + input.state = state; + gApi.changes().id(changeId).addReviewer(input); + } + private Set<Account.Id> ccsFor(String changeId) throws Exception { return reviewersFor(changeId, CC); }