Reuse ReviewerAdder from ReplaceOp
Change-Id: I1034505eb7615dbba599424bd79066bcbf9b7737
This commit is contained in:
		@@ -14,7 +14,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package com.google.gerrit.server.git.receive;
 | 
					package com.google.gerrit.server.git.receive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static com.google.common.collect.ImmutableList.toImmutableList;
 | 
				
			||||||
import static com.google.gerrit.common.FooterConstants.CHANGE_ID;
 | 
					import static com.google.gerrit.common.FooterConstants.CHANGE_ID;
 | 
				
			||||||
 | 
					import static com.google.gerrit.server.change.ReviewerAdder.newAddReviewerInputFromCommitIdentity;
 | 
				
			||||||
import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromFooters;
 | 
					import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromFooters;
 | 
				
			||||||
import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromReviewers;
 | 
					import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromReviewers;
 | 
				
			||||||
import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
 | 
					import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
 | 
				
			||||||
@@ -23,12 +25,17 @@ import static org.eclipse.jgit.lib.Constants.R_HEADS;
 | 
				
			|||||||
import com.google.common.base.Strings;
 | 
					import com.google.common.base.Strings;
 | 
				
			||||||
import com.google.common.collect.ImmutableList;
 | 
					import com.google.common.collect.ImmutableList;
 | 
				
			||||||
import com.google.common.collect.ImmutableListMultimap;
 | 
					import com.google.common.collect.ImmutableListMultimap;
 | 
				
			||||||
 | 
					import com.google.common.collect.Streams;
 | 
				
			||||||
import com.google.common.flogger.FluentLogger;
 | 
					import com.google.common.flogger.FluentLogger;
 | 
				
			||||||
import com.google.gerrit.common.Nullable;
 | 
					import com.google.gerrit.common.Nullable;
 | 
				
			||||||
import com.google.gerrit.common.data.LabelType;
 | 
					import com.google.gerrit.common.data.LabelType;
 | 
				
			||||||
 | 
					import com.google.gerrit.extensions.api.changes.AddReviewerResult;
 | 
				
			||||||
import com.google.gerrit.extensions.api.changes.NotifyHandling;
 | 
					import com.google.gerrit.extensions.api.changes.NotifyHandling;
 | 
				
			||||||
import com.google.gerrit.extensions.client.ChangeKind;
 | 
					import com.google.gerrit.extensions.client.ChangeKind;
 | 
				
			||||||
 | 
					import com.google.gerrit.extensions.client.ReviewerState;
 | 
				
			||||||
 | 
					import com.google.gerrit.extensions.restapi.BadRequestException;
 | 
				
			||||||
import com.google.gerrit.extensions.restapi.RestApiException;
 | 
					import com.google.gerrit.extensions.restapi.RestApiException;
 | 
				
			||||||
 | 
					import com.google.gerrit.reviewdb.client.Account;
 | 
				
			||||||
import com.google.gerrit.reviewdb.client.Branch;
 | 
					import com.google.gerrit.reviewdb.client.Branch;
 | 
				
			||||||
import com.google.gerrit.reviewdb.client.Change;
 | 
					import com.google.gerrit.reviewdb.client.Change;
 | 
				
			||||||
import com.google.gerrit.reviewdb.client.ChangeMessage;
 | 
					import com.google.gerrit.reviewdb.client.ChangeMessage;
 | 
				
			||||||
@@ -45,6 +52,10 @@ import com.google.gerrit.server.PublishCommentUtil;
 | 
				
			|||||||
import com.google.gerrit.server.account.AccountResolver;
 | 
					import com.google.gerrit.server.account.AccountResolver;
 | 
				
			||||||
import com.google.gerrit.server.change.ChangeKindCache;
 | 
					import com.google.gerrit.server.change.ChangeKindCache;
 | 
				
			||||||
import com.google.gerrit.server.change.EmailReviewComments;
 | 
					import com.google.gerrit.server.change.EmailReviewComments;
 | 
				
			||||||
 | 
					import com.google.gerrit.server.change.ReviewerAdder;
 | 
				
			||||||
 | 
					import com.google.gerrit.server.change.ReviewerAdder.InternalAddReviewerInput;
 | 
				
			||||||
 | 
					import com.google.gerrit.server.change.ReviewerAdder.ReviewerAddition;
 | 
				
			||||||
 | 
					import com.google.gerrit.server.change.ReviewerAdder.ReviewerAdditionList;
 | 
				
			||||||
import com.google.gerrit.server.config.SendEmailExecutor;
 | 
					import com.google.gerrit.server.config.SendEmailExecutor;
 | 
				
			||||||
import com.google.gerrit.server.extensions.events.CommentAdded;
 | 
					import com.google.gerrit.server.extensions.events.CommentAdded;
 | 
				
			||||||
import com.google.gerrit.server.extensions.events.RevisionCreated;
 | 
					import com.google.gerrit.server.extensions.events.RevisionCreated;
 | 
				
			||||||
@@ -75,6 +86,7 @@ import java.util.Optional;
 | 
				
			|||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
import java.util.concurrent.ExecutorService;
 | 
					import java.util.concurrent.ExecutorService;
 | 
				
			||||||
import java.util.concurrent.Future;
 | 
					import java.util.concurrent.Future;
 | 
				
			||||||
 | 
					import org.eclipse.jgit.errors.ConfigInvalidException;
 | 
				
			||||||
import org.eclipse.jgit.lib.ObjectId;
 | 
					import org.eclipse.jgit.lib.ObjectId;
 | 
				
			||||||
import org.eclipse.jgit.revwalk.RevCommit;
 | 
					import org.eclipse.jgit.revwalk.RevCommit;
 | 
				
			||||||
import org.eclipse.jgit.revwalk.RevWalk;
 | 
					import org.eclipse.jgit.revwalk.RevWalk;
 | 
				
			||||||
@@ -117,6 +129,7 @@ public class ReplaceOp implements BatchUpdateOp {
 | 
				
			|||||||
  private final PatchSetUtil psUtil;
 | 
					  private final PatchSetUtil psUtil;
 | 
				
			||||||
  private final ReplacePatchSetSender.Factory replacePatchSetFactory;
 | 
					  private final ReplacePatchSetSender.Factory replacePatchSetFactory;
 | 
				
			||||||
  private final ProjectCache projectCache;
 | 
					  private final ProjectCache projectCache;
 | 
				
			||||||
 | 
					  private final ReviewerAdder reviewerAdder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private final ProjectState projectState;
 | 
					  private final ProjectState projectState;
 | 
				
			||||||
  private final Branch.NameKey dest;
 | 
					  private final Branch.NameKey dest;
 | 
				
			||||||
@@ -142,6 +155,7 @@ public class ReplaceOp implements BatchUpdateOp {
 | 
				
			|||||||
  private String rejectMessage;
 | 
					  private String rejectMessage;
 | 
				
			||||||
  private MergedByPushOp mergedByPushOp;
 | 
					  private MergedByPushOp mergedByPushOp;
 | 
				
			||||||
  private RequestScopePropagator requestScopePropagator;
 | 
					  private RequestScopePropagator requestScopePropagator;
 | 
				
			||||||
 | 
					  private ReviewerAdditionList reviewerAdditions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Inject
 | 
					  @Inject
 | 
				
			||||||
  ReplaceOp(
 | 
					  ReplaceOp(
 | 
				
			||||||
@@ -161,6 +175,7 @@ public class ReplaceOp implements BatchUpdateOp {
 | 
				
			|||||||
      ReplacePatchSetSender.Factory replacePatchSetFactory,
 | 
					      ReplacePatchSetSender.Factory replacePatchSetFactory,
 | 
				
			||||||
      ProjectCache projectCache,
 | 
					      ProjectCache projectCache,
 | 
				
			||||||
      @SendEmailExecutor ExecutorService sendEmailExecutor,
 | 
					      @SendEmailExecutor ExecutorService sendEmailExecutor,
 | 
				
			||||||
 | 
					      ReviewerAdder reviewerAdder,
 | 
				
			||||||
      @Assisted ProjectState projectState,
 | 
					      @Assisted ProjectState projectState,
 | 
				
			||||||
      @Assisted Branch.NameKey dest,
 | 
					      @Assisted Branch.NameKey dest,
 | 
				
			||||||
      @Assisted boolean checkMergedInto,
 | 
					      @Assisted boolean checkMergedInto,
 | 
				
			||||||
@@ -188,6 +203,7 @@ public class ReplaceOp implements BatchUpdateOp {
 | 
				
			|||||||
    this.replacePatchSetFactory = replacePatchSetFactory;
 | 
					    this.replacePatchSetFactory = replacePatchSetFactory;
 | 
				
			||||||
    this.projectCache = projectCache;
 | 
					    this.projectCache = projectCache;
 | 
				
			||||||
    this.sendEmailExecutor = sendEmailExecutor;
 | 
					    this.sendEmailExecutor = sendEmailExecutor;
 | 
				
			||||||
 | 
					    this.reviewerAdder = reviewerAdder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.projectState = projectState;
 | 
					    this.projectState = projectState;
 | 
				
			||||||
    this.dest = dest;
 | 
					    this.dest = dest;
 | 
				
			||||||
@@ -228,7 +244,8 @@ public class ReplaceOp implements BatchUpdateOp {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @Override
 | 
					  @Override
 | 
				
			||||||
  public boolean updateChange(ChangeContext ctx)
 | 
					  public boolean updateChange(ChangeContext ctx)
 | 
				
			||||||
      throws RestApiException, OrmException, IOException, PermissionBackendException {
 | 
					      throws RestApiException, OrmException, IOException, PermissionBackendException,
 | 
				
			||||||
 | 
					          ConfigInvalidException {
 | 
				
			||||||
    notes = ctx.getNotes();
 | 
					    notes = ctx.getNotes();
 | 
				
			||||||
    Change change = notes.getChange();
 | 
					    Change change = notes.getChange();
 | 
				
			||||||
    if (change == null || change.getStatus().isClosed()) {
 | 
					    if (change == null || change.getStatus().isClosed()) {
 | 
				
			||||||
@@ -294,7 +311,8 @@ public class ReplaceOp implements BatchUpdateOp {
 | 
				
			|||||||
            psDescription);
 | 
					            psDescription);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    update.setPsDescription(psDescription);
 | 
					    update.setPsDescription(psDescription);
 | 
				
			||||||
    recipients.add(getRecipientsFromFooters(accountResolver, commit.getFooterLines()));
 | 
					    MailRecipients fromFooters = getRecipientsFromFooters(accountResolver, commit.getFooterLines());
 | 
				
			||||||
 | 
					    recipients.add(fromFooters);
 | 
				
			||||||
    recipients.remove(ctx.getAccountId());
 | 
					    recipients.remove(ctx.getAccountId());
 | 
				
			||||||
    ChangeData cd = changeDataFactory.create(ctx.getDb(), ctx.getNotes());
 | 
					    ChangeData cd = changeDataFactory.create(ctx.getDb(), ctx.getNotes());
 | 
				
			||||||
    MailRecipients oldRecipients = getRecipientsFromReviewers(cd.reviewers());
 | 
					    MailRecipients oldRecipients = getRecipientsFromReviewers(cd.reviewers());
 | 
				
			||||||
@@ -313,15 +331,21 @@ public class ReplaceOp implements BatchUpdateOp {
 | 
				
			|||||||
        ctx.getRevWalk(),
 | 
					        ctx.getRevWalk(),
 | 
				
			||||||
        ctx.getRepoView().getConfig(),
 | 
					        ctx.getRepoView().getConfig(),
 | 
				
			||||||
        newApprovals);
 | 
					        newApprovals);
 | 
				
			||||||
    approvalsUtil.addReviewers(
 | 
					
 | 
				
			||||||
        ctx.getDb(),
 | 
					    reviewerAdditions =
 | 
				
			||||||
        update,
 | 
					        reviewerAdder.prepare(
 | 
				
			||||||
        projectState.getLabelTypes(),
 | 
					            ctx.getNotes(),
 | 
				
			||||||
        change,
 | 
					            ctx.getUser(),
 | 
				
			||||||
        newPatchSet,
 | 
					            getReviewerInputs(recipients, ctx.getChange(), info),
 | 
				
			||||||
        info,
 | 
					            true);
 | 
				
			||||||
        recipients.getReviewers(),
 | 
					    Optional<ReviewerAddition> reviewerError = reviewerAdditions.getFailures().stream().findFirst();
 | 
				
			||||||
        oldRecipients.getAll());
 | 
					    if (reviewerError.isPresent()) {
 | 
				
			||||||
 | 
					      // TODO(dborowitz): How best to report this? Erroring out would match existing
 | 
				
			||||||
 | 
					      // ReceiveCommits behavior, but it may be worth rethinking.
 | 
				
			||||||
 | 
					      AddReviewerResult result = reviewerError.get().result;
 | 
				
			||||||
 | 
					      throw new BadRequestException("Failed to add reviewer " + result.input + ": " + result.error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    reviewerAdditions.updateChange(ctx, newPatchSet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check if approvals are changing in with this update. If so, add current user to reviewers.
 | 
					    // Check if approvals are changing in with this update. If so, add current user to reviewers.
 | 
				
			||||||
    // Note that this is done separately as addReviewers is filtering out the change owner as
 | 
					    // Note that this is done separately as addReviewers is filtering out the change owner as
 | 
				
			||||||
@@ -344,6 +368,44 @@ public class ReplaceOp implements BatchUpdateOp {
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private static ImmutableList<InternalAddReviewerInput> getReviewerInputs(
 | 
				
			||||||
 | 
					      MailRecipients recipients, Change change, PatchSetInfo psInfo) {
 | 
				
			||||||
 | 
					    // Disable individual emails when adding reviewers, as all reviewers will receive the single
 | 
				
			||||||
 | 
					    // bulk new change email.
 | 
				
			||||||
 | 
					    return Streams.concat(
 | 
				
			||||||
 | 
					            recipients
 | 
				
			||||||
 | 
					                .getReviewers()
 | 
				
			||||||
 | 
					                .stream()
 | 
				
			||||||
 | 
					                .distinct()
 | 
				
			||||||
 | 
					                .map(id -> newAddReviewerInput(id, ReviewerState.REVIEWER)),
 | 
				
			||||||
 | 
					            recipients
 | 
				
			||||||
 | 
					                .getCcOnly()
 | 
				
			||||||
 | 
					                .stream()
 | 
				
			||||||
 | 
					                .distinct()
 | 
				
			||||||
 | 
					                .map(id -> newAddReviewerInput(id, ReviewerState.CC)),
 | 
				
			||||||
 | 
					            Streams.stream(
 | 
				
			||||||
 | 
					                newAddReviewerInputFromCommitIdentity(
 | 
				
			||||||
 | 
					                    change, psInfo.getAuthor().getAccount(), NotifyHandling.NONE)),
 | 
				
			||||||
 | 
					            Streams.stream(
 | 
				
			||||||
 | 
					                newAddReviewerInputFromCommitIdentity(
 | 
				
			||||||
 | 
					                    change, psInfo.getCommitter().getAccount(), NotifyHandling.NONE)))
 | 
				
			||||||
 | 
					        .collect(toImmutableList());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private static InternalAddReviewerInput newAddReviewerInput(
 | 
				
			||||||
 | 
					      Account.Id accountId, ReviewerState state) {
 | 
				
			||||||
 | 
					    // Disable individual emails when adding reviewers, as all reviewers will receive the single
 | 
				
			||||||
 | 
					    // bulk new patch set email.
 | 
				
			||||||
 | 
					    InternalAddReviewerInput input =
 | 
				
			||||||
 | 
					        ReviewerAdder.newAddReviewerInput(accountId, state, NotifyHandling.NONE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Ignore failures for reasons like the reviewer being inactive or being unable to see the
 | 
				
			||||||
 | 
					    // change. See discussion in ChangeInserter.
 | 
				
			||||||
 | 
					    input.otherFailureBehavior = ReviewerAdder.FailureBehavior.IGNORE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return input;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private ChangeMessage createChangeMessage(ChangeContext ctx, String reviewMessage)
 | 
					  private ChangeMessage createChangeMessage(ChangeContext ctx, String reviewMessage)
 | 
				
			||||||
      throws OrmException, IOException {
 | 
					      throws OrmException, IOException {
 | 
				
			||||||
    String approvalMessage =
 | 
					    String approvalMessage =
 | 
				
			||||||
@@ -455,6 +517,7 @@ public class ReplaceOp implements BatchUpdateOp {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @Override
 | 
					  @Override
 | 
				
			||||||
  public void postUpdate(Context ctx) throws Exception {
 | 
					  public void postUpdate(Context ctx) throws Exception {
 | 
				
			||||||
 | 
					    reviewerAdditions.postUpdate(ctx);
 | 
				
			||||||
    if (changeKind != ChangeKind.TRIVIAL_REBASE) {
 | 
					    if (changeKind != ChangeKind.TRIVIAL_REBASE) {
 | 
				
			||||||
      // TODO(dborowitz): Merge email templates so we only have to send one.
 | 
					      // TODO(dborowitz): Merge email templates so we only have to send one.
 | 
				
			||||||
      Runnable e = new ReplaceEmailTask(ctx);
 | 
					      Runnable e = new ReplaceEmailTask(ctx);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2259,6 +2259,7 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
 | 
				
			|||||||
      String name = "reviewers for " + (i + 1);
 | 
					      String name = "reviewers for " + (i + 1);
 | 
				
			||||||
      if (expectedReviewer != null) {
 | 
					      if (expectedReviewer != null) {
 | 
				
			||||||
        assertThat(cd.reviewers().all()).named(name).containsExactly(expectedReviewer.getId());
 | 
					        assertThat(cd.reviewers().all()).named(name).containsExactly(expectedReviewer.getId());
 | 
				
			||||||
 | 
					        // Remove reviewer from PS1 so we can test adding this same reviewer on PS2 below.
 | 
				
			||||||
        gApi.changes().id(cd.getId().get()).reviewer(expectedReviewer.getId().toString()).remove();
 | 
					        gApi.changes().id(cd.getId().get()).reviewer(expectedReviewer.getId().toString()).remove();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      assertThat(byCommit(c).reviewers().all()).named(name).isEmpty();
 | 
					      assertThat(byCommit(c).reviewers().all()).named(name).isEmpty();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user