// Copyright (C) 2008 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.git.receive;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableListMultimap.toImmutableListMultimap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.flogger.LazyArgs.lazy;
import static com.google.gerrit.entities.RefNames.REFS_CHANGES;
import static com.google.gerrit.entities.RefNames.isConfigRef;
import static com.google.gerrit.entities.RefNames.isRefsUsersSelf;
import static com.google.gerrit.git.ObjectIds.abbreviateName;
import static com.google.gerrit.server.change.HashtagsUtil.cleanupHashtag;
import static com.google.gerrit.server.git.MultiProgressMonitor.UNKNOWN;
import static com.google.gerrit.server.git.receive.ReceiveConstants.COMMAND_REJECTION_MESSAGE_FOOTER;
import static com.google.gerrit.server.git.receive.ReceiveConstants.ONLY_USERS_WITH_TOGGLE_WIP_STATE_PERM_CAN_MODIFY_WIP;
import static com.google.gerrit.server.git.receive.ReceiveConstants.PUSH_OPTION_SKIP_VALIDATION;
import static com.google.gerrit.server.git.receive.ReceiveConstants.SAME_CHANGE_ID_IN_MULTIPLE_CHANGES;
import static com.google.gerrit.server.git.validators.CommitValidators.NEW_PATCHSET_PATTERN;
import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromFooters;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static org.eclipse.jgit.lib.Constants.R_HEADS;
import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
import static org.eclipse.jgit.transport.ReceiveCommand.Result.OK;
import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_MISSING_OBJECT;
import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_OTHER_REASON;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Sets;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.UsedAt;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.LabelTypes;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetInfo;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.entities.SubmissionId;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.changes.HashtagsInput;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.NotifyInfo;
import com.google.gerrit.extensions.api.changes.RecipientType;
import com.google.gerrit.extensions.api.changes.SubmitInput;
import com.google.gerrit.extensions.api.projects.ProjectConfigEntryType;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.Extension;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.extensions.validators.CommentForValidation;
import com.google.gerrit.extensions.validators.CommentForValidation.CommentSource;
import com.google.gerrit.extensions.validators.CommentForValidation.CommentType;
import com.google.gerrit.extensions.validators.CommentValidationContext;
import com.google.gerrit.extensions.validators.CommentValidationFailure;
import com.google.gerrit.extensions.validators.CommentValidator;
import com.google.gerrit.metrics.Counter0;
import com.google.gerrit.metrics.Counter3;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Field;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.server.CancellationMetrics;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CreateGroupPermissionSyncer;
import com.google.gerrit.server.DeadlineChecker;
import com.google.gerrit.server.DraftCommentsReader;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.InvalidDeadlineException;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.PublishCommentUtil;
import com.google.gerrit.server.PublishCommentsOp;
import com.google.gerrit.server.RequestInfo;
import com.google.gerrit.server.RequestListener;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.approval.ApprovalsUtil;
import com.google.gerrit.server.cancellation.RequestCancelledException;
import com.google.gerrit.server.cancellation.RequestStateContext;
import com.google.gerrit.server.change.AttentionSetUnchangedOp;
import com.google.gerrit.server.change.ChangeInserter;
import com.google.gerrit.server.change.NotifyResolver;
import com.google.gerrit.server.change.SetHashtagsOp;
import com.google.gerrit.server.change.SetPrivateOp;
import com.google.gerrit.server.change.SetTopicOp;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.ProjectConfigEntry;
import com.google.gerrit.server.edit.ChangeEdit;
import com.google.gerrit.server.edit.ChangeEditUtil;
import com.google.gerrit.server.git.BanCommit;
import com.google.gerrit.server.git.ChangeReportFormatter;
import com.google.gerrit.server.git.GroupCollector;
import com.google.gerrit.server.git.MergedByPushOp;
import com.google.gerrit.server.git.MultiProgressMonitor;
import com.google.gerrit.server.git.MultiProgressMonitor.Task;
import com.google.gerrit.server.git.ReceivePackInitializer;
import com.google.gerrit.server.git.TagCache;
import com.google.gerrit.server.git.ValidationError;
import com.google.gerrit.server.git.validators.CommentCountValidator;
import com.google.gerrit.server.git.validators.CommentSizeValidator;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.gerrit.server.git.validators.RefOperationValidationException;
import com.google.gerrit.server.git.validators.RefOperationValidators;
import com.google.gerrit.server.git.validators.ValidationMessage;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.PerformanceLogContext;
import com.google.gerrit.server.logging.PerformanceLogger;
import com.google.gerrit.server.logging.RequestId;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.mail.MailUtil.MailRecipients;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.AutoMerger;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.PermissionDeniedException;
import com.google.gerrit.server.permissions.ProjectPermission;
import com.google.gerrit.server.permissions.RefPermission;
import com.google.gerrit.server.plugincontext.PluginSetContext;
import com.google.gerrit.server.project.CreateRefControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.restapi.change.ReplyAttentionSetUpdates;
import com.google.gerrit.server.submit.MergeOp;
import com.google.gerrit.server.submit.MergeOpRepoManager;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.PostUpdateContext;
import com.google.gerrit.server.update.RepoContext;
import com.google.gerrit.server.update.RepoOnlyOp;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gerrit.server.update.SubmissionExecutor;
import com.google.gerrit.server.update.SubmissionListener;
import com.google.gerrit.server.update.SuperprojectUpdateOnSubmission;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType;
import com.google.gerrit.server.util.LabelVote;
import com.google.gerrit.server.util.MagicBranch;
import com.google.gerrit.server.util.RequestScopePropagator;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.util.cli.CmdLineParser;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.util.Providers;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.FooterLine;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.filter.RevFilter;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.ReceivePack;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.Option;

/**
 * Receives change upload using the Git receive-pack protocol.
 *
 * <p>Conceptually, most use of Gerrit is a push of some commits to refs/for/BRANCH. However, the
 * receive-pack protocol that this is based on allows multiple ref updates to be processed at once.
 * So we have to be prepared to also handle normal pushes (refs/heads/BRANCH). It is hard to split
 * this class up further, because normal pushes can also result in updates to reviews, through the
 * autoclose mechanism.
 */
class ReceiveCommits {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final String CANNOT_DELETE_CHANGES = "Cannot delete from '" + REFS_CHANGES + "'";
  private static final String CANNOT_DELETE_CONFIG =
      "Cannot delete project configuration from '" + RefNames.REFS_CONFIG + "'";
  private static final String INTERNAL_SERVER_ERROR = "internal server error";

  public static final String DIRECT_PUSH_JUSTIFICATION_OPTION = "push-justification";

  interface Factory {
    ReceiveCommits create(
        ProjectState projectState,
        IdentifiedUser user,
        ReceivePack receivePack,
        Repository repository,
        AllRefsWatcher allRefsWatcher,
        MessageSender messageSender);
  }

  private class ReceivePackMessageSender implements MessageSender {
    @Override
    public void sendMessage(String what) {
      receivePack.sendMessage(what);
    }

    @Override
    public void sendError(String what) {
      receivePack.sendError(what);
    }

    @Override
    public void sendBytes(byte[] what) {
      sendBytes(what, 0, what.length);
    }

    @Override
    public void sendBytes(byte[] what, int off, int len) {
      try {
        receivePack.getMessageOutputStream().write(what, off, len);
      } catch (IOException e) {
        // Ignore write failures (matching JGit behavior).
      }
    }

    @Override
    public void flush() {
      try {
        receivePack.getMessageOutputStream().flush();
      } catch (IOException e) {
        // Ignore write failures (matching JGit behavior).
      }
    }
  }

  private static RestApiException asRestApiException(Exception e) {
    if (e instanceof RestApiException) {
      return (RestApiException) e;
    } else if ((e instanceof ExecutionException) && (e.getCause() instanceof RestApiException)) {
      return (RestApiException) e.getCause();
    }
    return RestApiException.wrap("Error inserting change/patchset", e);
  }

  @Singleton
  private static class Metrics {
    private final Counter0 psRevisionMissing;
    private final Counter3<String, String, String> pushCount;

    @Inject
    Metrics(MetricMaker metricMaker) {
      psRevisionMissing =
          metricMaker.newCounter(
              "receivecommits/ps_revision_missing",
              new Description("errors due to patch set revision missing"));
      pushCount =
          metricMaker.newCounter(
              "receivecommits/push_count",
              new Description("number of pushes"),
              Field.ofString("kind", (metadataBuilder, fieldValue) -> {})
                  .description("The push kind (direct vs. magic).")
                  .build(),
              Field.ofString(
                      "project",
                      (metadataBuilder, fieldValue) -> metadataBuilder.projectName(fieldValue))
                  .description("The name of the project for which the push is done.")
                  .build(),
              Field.ofString("type", (metadataBuilder, fieldValue) -> {})
                  .description(
                      "The type of the update (CREATE, UPDATE, CREATE/UPDATE,"
                          + " UPDATE_NONFASTFORWARD, DELETE).")
                  .build());
    }
  }

  // ReceiveCommits has a lot of fields, sorry. Here and in the constructor they are split up
  // somewhat, and kept sorted lexicographically within sections, except where later assignments
  // depend on previous ones.

  // Injected fields.
  private final AccountResolver accountResolver;
  private final AllProjectsName allProjectsName;
  private final BatchUpdate.Factory batchUpdateFactory;
  private final CancellationMetrics cancellationMetrics;
  private final ChangeEditUtil editUtil;
  private final ChangeIndexer indexer;
  private final ChangeInserter.Factory changeInserterFactory;
  private final ChangeNotes.Factory notesFactory;
  private final ChangeReportFormatter changeFormatter;
  private final ChangeUtil changeUtil;
  private final CmdLineParser.Factory optionParserFactory;
  private final DraftCommentsReader draftCommentsReader;
  private final PluginSetContext<CommentValidator> commentValidators;
  private final BranchCommitValidator.Factory commitValidatorFactory;
  private final Config config;
  private final CreateGroupPermissionSyncer createGroupPermissionSyncer;
  private final CreateRefControl createRefControl;
  private final DeadlineChecker.Factory deadlineCheckerFactory;
  private final DynamicMap<ProjectConfigEntry> pluginConfigEntries;
  private final DynamicSet<PluginPushOption> pluginPushOptions;
  private final PluginSetContext<ReceivePackInitializer> initializers;
  private final MergedByPushOp.Factory mergedByPushOpFactory;
  private final Metrics metrics;
  private final PatchSetInfoFactory patchSetInfoFactory;
  private final PatchSetUtil psUtil;
  private final DynamicSet<PerformanceLogger> performanceLoggers;
  private final PermissionBackend permissionBackend;
  private final ProjectCache projectCache;
  private final Provider<InternalChangeQuery> queryProvider;
  private final Provider<MergeOp> mergeOpProvider;
  private final Provider<MergeOpRepoManager> ormProvider;
  private final ReceiveConfig receiveConfig;
  private final RefOperationValidators.Factory refValidatorsFactory;
  private final ReplaceOp.Factory replaceOpFactory;
  private final PluginSetContext<RequestListener> requestListeners;
  private final PublishCommentsOp.Factory publishCommentsOp;
  private final RetryHelper retryHelper;
  private final RequestScopePropagator requestScopePropagator;
  private final Sequences seq;
  private final SetHashtagsOp.Factory hashtagsFactory;
  private final SetTopicOp.Factory setTopicFactory;
  private final ImmutableList<SubmissionListener> superprojectUpdateSubmissionListeners;
  private final TagCache tagCache;
  private final ProjectConfig.Factory projectConfigFactory;
  private final SetPrivateOp.Factory setPrivateOpFactory;
  private final ReplyAttentionSetUpdates replyAttentionSetUpdates;
  private final AutoMerger autoMerger;

  // Assisted injected fields.
  private final ProjectState projectState;
  private final IdentifiedUser user;
  private final ReceivePack receivePack;

  // Immutable fields derived from constructor arguments.
  private final boolean allowProjectOwnersToChangeParent;
  private final LabelTypes labelTypes;
  private final NoteMap rejectCommits;
  private final PermissionBackend.ForProject permissions;
  private final Project project;
  private final Repository repo;

  // Collections populated during processing.
  private final Queue<ValidationMessage> messages;
  /** Multimap of error text to refnames that produced that error. */
  private final ListMultimap<String, String> errors;

  private final ListMultimap<String, String> pushOptions;
  private final ReceivePackRefCache receivePackRefCache;
  private final Map<Change.Id, ReplaceRequest> replaceByChange;

  // Other settings populated during processing.
  private MagicBranchInput magicBranch;
  private boolean newChangeForAllNotInTarget;
  private boolean setChangeAsPrivate;
  private Optional<NoteDbPushOption> noteDbPushOption;
  private Optional<String> tracePushOption;

  private MessageSender messageSender;
  private ReceiveCommitsResult.Builder result;
  private ImmutableMap<String, String> loggingTags;
  private ImmutableList<String> transitionalPluginOptions;

  /** This object is for single use only. */
  private boolean used;

  @Inject
  ReceiveCommits(
      AccountResolver accountResolver,
      AllProjectsName allProjectsName,
      BatchUpdate.Factory batchUpdateFactory,
      CancellationMetrics cancellationMetrics,
      ProjectConfig.Factory projectConfigFactory,
      @GerritServerConfig Config config,
      ChangeEditUtil editUtil,
      ChangeIndexer indexer,
      ChangeInserter.Factory changeInserterFactory,
      ChangeNotes.Factory notesFactory,
      DynamicItem<ChangeReportFormatter> changeFormatterProvider,
      ChangeUtil changeUtil,
      CmdLineParser.Factory optionParserFactory,
      DraftCommentsReader draftCommentsReader,
      BranchCommitValidator.Factory commitValidatorFactory,
      CreateGroupPermissionSyncer createGroupPermissionSyncer,
      CreateRefControl createRefControl,
      DeadlineChecker.Factory deadlineCheckerFactory,
      DynamicMap<ProjectConfigEntry> pluginConfigEntries,
      DynamicSet<PluginPushOption> pluginPushOptions,
      PluginSetContext<ReceivePackInitializer> initializers,
      PluginSetContext<CommentValidator> commentValidators,
      MergedByPushOp.Factory mergedByPushOpFactory,
      Metrics metrics,
      PatchSetInfoFactory patchSetInfoFactory,
      PatchSetUtil psUtil,
      DynamicSet<PerformanceLogger> performanceLoggers,
      PermissionBackend permissionBackend,
      ProjectCache projectCache,
      Provider<InternalChangeQuery> queryProvider,
      Provider<MergeOp> mergeOpProvider,
      Provider<MergeOpRepoManager> ormProvider,
      PublishCommentsOp.Factory publishCommentsOp,
      ReceiveConfig receiveConfig,
      RefOperationValidators.Factory refValidatorsFactory,
      ReplaceOp.Factory replaceOpFactory,
      PluginSetContext<RequestListener> requestListeners,
      RetryHelper retryHelper,
      RequestScopePropagator requestScopePropagator,
      Sequences seq,
      SetHashtagsOp.Factory hashtagsFactory,
      SetTopicOp.Factory setTopicFactory,
      @SuperprojectUpdateOnSubmission
          ImmutableList<SubmissionListener> superprojectUpdateSubmissionListeners,
      TagCache tagCache,
      SetPrivateOp.Factory setPrivateOpFactory,
      ReplyAttentionSetUpdates replyAttentionSetUpdates,
      AutoMerger autoMerger,
      @Assisted ProjectState projectState,
      @Assisted IdentifiedUser user,
      @Assisted ReceivePack rp,
      @Assisted Repository repository,
      @Assisted AllRefsWatcher allRefsWatcher,
      @Nullable @Assisted MessageSender messageSender)
      throws IOException {
    // Injected fields.
    this.accountResolver = accountResolver;
    this.allProjectsName = allProjectsName;
    this.batchUpdateFactory = batchUpdateFactory;
    this.cancellationMetrics = cancellationMetrics;
    this.changeFormatter = changeFormatterProvider.get();
    this.changeUtil = changeUtil;
    this.changeInserterFactory = changeInserterFactory;
    this.draftCommentsReader = draftCommentsReader;
    this.commentValidators = commentValidators;
    this.commitValidatorFactory = commitValidatorFactory;
    this.config = config;
    this.createRefControl = createRefControl;
    this.createGroupPermissionSyncer = createGroupPermissionSyncer;
    this.deadlineCheckerFactory = deadlineCheckerFactory;
    this.editUtil = editUtil;
    this.hashtagsFactory = hashtagsFactory;
    this.setTopicFactory = setTopicFactory;
    this.indexer = indexer;
    this.initializers = initializers;
    this.mergeOpProvider = mergeOpProvider;
    this.mergedByPushOpFactory = mergedByPushOpFactory;
    this.notesFactory = notesFactory;
    this.optionParserFactory = optionParserFactory;
    this.ormProvider = ormProvider;
    this.metrics = metrics;
    this.patchSetInfoFactory = patchSetInfoFactory;
    this.permissionBackend = permissionBackend;
    this.pluginConfigEntries = pluginConfigEntries;
    this.pluginPushOptions = pluginPushOptions;
    this.projectCache = projectCache;
    this.psUtil = psUtil;
    this.performanceLoggers = performanceLoggers;
    this.publishCommentsOp = publishCommentsOp;
    this.queryProvider = queryProvider;
    this.receiveConfig = receiveConfig;
    this.refValidatorsFactory = refValidatorsFactory;
    this.replaceOpFactory = replaceOpFactory;
    this.requestListeners = requestListeners;
    this.retryHelper = retryHelper;
    this.requestScopePropagator = requestScopePropagator;
    this.seq = seq;
    this.superprojectUpdateSubmissionListeners = superprojectUpdateSubmissionListeners;
    this.tagCache = tagCache;
    this.projectConfigFactory = projectConfigFactory;
    this.setPrivateOpFactory = setPrivateOpFactory;
    this.replyAttentionSetUpdates = replyAttentionSetUpdates;
    this.autoMerger = autoMerger;

    // Assisted injected fields.
    this.projectState = projectState;
    this.user = user;
    this.receivePack = rp;
    // This repository instance in unwrapped, while the repository instance in
    // receivePack.getRepo() is wrapped in PermissionAwareRepository instance.
    this.repo = repository;

    // Immutable fields derived from constructor arguments.
    project = projectState.getProject();
    labelTypes = projectState.getLabelTypes();
    permissions = permissionBackend.user(user).project(project.getNameKey());
    rejectCommits = BanCommit.loadRejectCommitsMap(repo, rp.getRevWalk());

    // Collections populated during processing.
    errors = MultimapBuilder.linkedHashKeys().arrayListValues().build();
    messages = new ConcurrentLinkedQueue<>();
    pushOptions = LinkedListMultimap.create();
    replaceByChange = new LinkedHashMap<>();

    used = false;

    this.allowProjectOwnersToChangeParent =
        config.getBoolean("receive", "allowProjectOwnersToChangeParent", false);

    // Other settings populated during processing.
    newChangeForAllNotInTarget =
        projectState.is(BooleanProjectConfig.CREATE_NEW_CHANGE_FOR_ALL_NOT_IN_TARGET);

    // Handles for outputting back over the wire to the end user.
    this.messageSender = messageSender != null ? messageSender : new ReceivePackMessageSender();
    this.result = ReceiveCommitsResult.builder();
    this.loggingTags = ImmutableMap.of();

    // TODO(hiesel): Make this decision implicit once vetted
    boolean useRefCache = config.getBoolean("receive", "enableInMemoryRefCache", true);
    receivePackRefCache =
        useRefCache
            ? ReceivePackRefCache.withAdvertisedRefs(() -> allRefsWatcher.getAllRefs())
            : ReceivePackRefCache.noCache(receivePack.getRepository().getRefDatabase());
    this.transitionalPluginOptions =
        ImmutableList.copyOf(config.getStringList("plugins", null, "transitionalPushOptions"));
  }

  void init() {
    initializers.runEach(i -> i.init(projectState.getNameKey(), receivePack));
  }

  MessageSender getMessageSender() {
    return messageSender;
  }

  Project getProject() {
    return project;
  }

  private void addMessage(String message, ValidationMessage.Type type) {
    messages.add(new CommitValidationMessage(message, type));
  }

  private void addMessage(String message) {
    messages.add(new CommitValidationMessage(message, ValidationMessage.Type.OTHER));
  }

  private void addError(String error) {
    addMessage(error, ValidationMessage.Type.ERROR);
  }

  /**
   * Sends all messages which have been collected while processing the push to the client.
   *
   * <p><strong>Attention:</strong>{@link AsyncReceiveCommits} may call this method while {@link
   * #processCommands(Collection, MultiProgressMonitor)} is still running (if the execution of
   * processCommands takes too long and AsyncReceiveCommits gets a timeout). This means that local
   * variables that are accessed in this method must be thread-safe (otherwise we may hit a {@link
   * java.util.ConcurrentModificationException} if we read a variable here that at the same time is
   * updated by the background thread that still executes processCommands).
   */
  void sendMessages() {
    try (TraceContext traceContext =
        TraceContext.newTrace(
            loggingTags.containsKey(RequestId.Type.TRACE_ID.name()),
            loggingTags.get(RequestId.Type.TRACE_ID.name()),
            (tagName, traceId) -> {})) {
      loggingTags.forEach((tagName, tagValue) -> traceContext.addTag(tagName, tagValue));

      for (ValidationMessage m : messages) {
        String msg = m.getType().getPrefix() + m.getMessage();
        logger.atFine().log("Sending message: %s", msg);

        // Avoid calling sendError which will add its own error: prefix.
        messageSender.sendMessage(msg);
      }
    }
  }

  ReceiveCommitsResult processCommands(
      Collection<ReceiveCommand> commands, MultiProgressMonitor progress) throws StorageException {
    checkState(!used, "Tried to re-use a ReceiveCommits objects that is single-use only");
    long start = TimeUtil.nowNanos();
    parsePushOptions();
    String clientProvidedDeadlineValue =
        Iterables.getLast(pushOptions.get("deadline"), /* defaultValue= */ null);
    int commandCount = commands.size();
    try (TraceContext traceContext =
            TraceContext.newTrace(
                tracePushOption.isPresent(),
                tracePushOption.orElse(null),
                (tagName, traceId) -> addMessage(tagName + ": " + traceId));
        PerformanceLogContext performanceLogContext =
            new PerformanceLogContext(config, performanceLoggers);
        TraceTimer traceTimer =
            newTimer("processCommands", Metadata.builder().resourceCount(commandCount))) {
      RequestInfo requestInfo =
          RequestInfo.builder(RequestInfo.RequestType.GIT_RECEIVE, user, traceContext)
              .project(project.getNameKey())
              .build();
      requestListeners.runEach(l -> l.onRequest(requestInfo));
      traceContext.addTag(RequestId.Type.RECEIVE_ID, new RequestId(project.getNameKey().get()));

      // Log the push options here, rather than in parsePushOptions(), so that they are included
      // into the trace if tracing is enabled.
      logger.atFine().log("push options: %s", receivePack.getPushOptions());

      Task commandProgress = progress.beginSubTask("refs", UNKNOWN);
      commands =
          commands.stream().map(c -> wrapReceiveCommand(c, commandProgress)).collect(toList());

      try (RequestStateContext requestStateContext =
          RequestStateContext.open()
              .addRequestStateProvider(progress)
              .addRequestStateProvider(
                  deadlineCheckerFactory.create(start, requestInfo, clientProvidedDeadlineValue))) {
        processCommandsUnsafe(commands, progress);
        rejectRemaining(commands, INTERNAL_SERVER_ERROR);
      } catch (InvalidDeadlineException e) {
        rejectRemaining(commands, e.getMessage());
      } catch (RuntimeException e) {
        Optional<RequestCancelledException> requestCancelledException =
            RequestCancelledException.getFromCausalChain(e);
        if (!requestCancelledException.isPresent()) {
          Throwables.throwIfUnchecked(e);
        }
        cancellationMetrics.countCancelledRequest(
            requestInfo, requestCancelledException.get().getCancellationReason());
        StringBuilder msg =
            new StringBuilder(requestCancelledException.get().formatCancellationReason());
        if (requestCancelledException.get().getCancellationMessage().isPresent()) {
          msg.append(
              String.format(
                  " (%s)", requestCancelledException.get().getCancellationMessage().get()));
        }
        rejectRemaining(commands, msg.toString());
      }

      // This sends error messages before the 'done' string of the progress monitor is sent.
      // Currently, the test framework relies on this ordering to understand if pushes completed
      // successfully.
      sendErrorMessages();

      commandProgress.end();
      loggingTags = traceContext.getTags();
      logger.atFine().log("Processing commands done.");
    }
    progress.end();
    return result.build();
  }

  // Process as many commands as possible, but may leave some commands in state NOT_ATTEMPTED.
  private void processCommandsUnsafe(
      Collection<ReceiveCommand> commands, MultiProgressMonitor progress) {
    logger.atFine().log("Calling user: %s, commands: %d", user.getLoggableName(), commands.size());

    // If the list of groups is large, the log entry may get dropped, so separate out.
    logger.atFine().log("Groups: %s", lazy(() -> user.getEffectiveGroups().getKnownGroups()));

    if (!projectState.getProject().getState().permitsWrite()) {
      for (ReceiveCommand cmd : commands) {
        reject(cmd, "prohibited by Gerrit: project state does not permit write");
      }
      return;
    }

    List<ReceiveCommand> magicCommands = new ArrayList<>();
    List<ReceiveCommand> regularCommands = new ArrayList<>();

    for (ReceiveCommand cmd : commands) {
      if (MagicBranch.isMagicBranch(cmd.getRefName())) {
        magicCommands.add(cmd);
      } else {
        regularCommands.add(cmd);
      }
    }

    if (!magicCommands.isEmpty() && !regularCommands.isEmpty()) {
      rejectRemaining(commands, "cannot combine normal pushes and magic pushes");
      return;
    }

    try {
      if (!magicCommands.isEmpty()) {
        parseMagicBranch(Iterables.getLast(magicCommands));
        // Using the submit option submits the created change(s) immediately without checking labels
        // nor submit rules. Hence we shouldn't record such pushes as "magic" which implies that
        // code review is being done.
        String pushKind = magicBranch != null && magicBranch.submit ? "direct_submit" : "magic";
        metrics.pushCount.increment(pushKind, project.getName(), getUpdateType(magicCommands));
      }
      Optional<String> justification =
          pushOptions.get(DIRECT_PUSH_JUSTIFICATION_OPTION).stream().findFirst();
      try (RefUpdateContext ctx = RefUpdateContext.openDirectPush(justification)) {
        if (!regularCommands.isEmpty()) {
          metrics.pushCount.increment("direct", project.getName(), getUpdateType(regularCommands));
        }

        if (!regularCommands.isEmpty()) {
          handleRegularCommands(regularCommands, progress);
          return;
        }
      }

      boolean first = true;
      for (ReceiveCommand cmd : magicCommands) {
        if (first) {
          first = false;
        } else {
          reject(cmd, "duplicate request");
        }
      }
    } catch (PermissionBackendException | NoSuchProjectException | IOException err) {
      logger.atSevere().withCause(err).log("Failed to process refs in %s", project.getName());
      return;
    }

    Task newProgress = progress.beginSubTask("new", UNKNOWN);
    Task replaceProgress = progress.beginSubTask("updated", UNKNOWN);

    ImmutableList<CreateRequest> newChanges = ImmutableList.of();
    try {
      if (magicBranch != null && magicBranch.cmd.getResult() == NOT_ATTEMPTED) {
        try {
          newChanges = selectNewAndReplacedChangesFromMagicBranch(newProgress);
        } catch (IOException e) {
          throw new StorageException("Failed to select new changes in " + project.getName(), e);
        }
      }

      // Commit validation has already happened, so any changes without Change-Id are for the
      // deprecated feature.
      warnAboutMissingChangeId(newChanges);
      preparePatchSetsForReplace(newChanges);
      insertChangesAndPatchSets(newChanges, replaceProgress);
    } finally {
      newProgress.end();
      replaceProgress.end();
    }

    queueSuccessMessages(newChanges);

    logger.atFine().log(
        "Command results: %s",
        lazy(() -> commands.stream().map(ReceiveCommits::commandToString).collect(joining(","))));
  }

  private String getUpdateType(List<ReceiveCommand> commands) {
    return commands.stream()
        .map(ReceiveCommand::getType)
        .map(ReceiveCommand.Type::name)
        .distinct()
        .sorted()
        .collect(joining("/"));
  }

  private void sendErrorMessages() {
    if (!errors.isEmpty()) {
      logger.atFine().log("Handling error conditions: %s", errors.keySet());
      for (String error : errors.keySet()) {
        receivePack.sendMessage("error: " + buildError(error, errors.get(error)));
      }
      receivePack.sendMessage(String.format("User: %s", user.getLoggableName()));
      receivePack.sendMessage(COMMAND_REJECTION_MESSAGE_FOOTER);
    }
  }

  private void handleRegularCommands(List<ReceiveCommand> cmds, MultiProgressMonitor progress)
      throws PermissionBackendException, IOException, NoSuchProjectException {
    try (TraceTimer traceTimer =
        newTimer("handleRegularCommands", Metadata.builder().resourceCount(cmds.size()))) {
      result.magicPush(false);
      for (ReceiveCommand cmd : cmds) {
        parseRegularCommand(cmd);
      }

      Map<BranchNameKey, ReceiveCommand> branches;
      try (BatchUpdate bu =
              batchUpdateFactory.create(
                  project.getNameKey(), user.materializedCopy(), TimeUtil.now());
          ObjectInserter ins = repo.newObjectInserter();
          ObjectReader reader = ins.newReader();
          RevWalk rw = new RevWalk(reader);
          MergeOpRepoManager orm = ormProvider.get()) {
        bu.setRepository(repo, rw, ins);
        bu.setRefLogMessage("push");

        int added = 0;
        for (ReceiveCommand cmd : cmds) {
          if (cmd.getResult() == NOT_ATTEMPTED) {
            bu.addRepoOnlyOp(new UpdateOneRefOp(cmd));
            added++;
          }
        }
        logger.atFine().log("Added %d additional ref updates", added);

        SubmissionExecutor submissionExecutor =
            new SubmissionExecutor(false, superprojectUpdateSubmissionListeners);

        submissionExecutor.execute(ImmutableList.of(bu));

        orm.setContext(TimeUtil.now(), user, NotifyResolver.Result.none());
        submissionExecutor.afterExecutions(orm);

        branches = bu.getSuccessfullyUpdatedBranches(false);
      } catch (UpdateException | RestApiException e) {
        throw new StorageException(e);
      }

      // This could be moved into a SubmissionListener
      branches.values().stream()
          .filter(c -> isHead(c) || isConfig(c))
          .forEach(
              c -> {
                // Most post-update steps should happen in UpdateOneRefOp#postUpdate. The only steps
                // that should happen in this loops are things that can't happen within one
                // BatchUpdate because they involve kicking off an additional BatchUpdate.
                switch (c.getType()) {
                  case CREATE:
                  case UPDATE:
                  case UPDATE_NONFASTFORWARD:
                    Task closeProgress = progress.beginSubTask("closed", UNKNOWN);
                    try (RefUpdateContext ctx =
                        RefUpdateContext.open(RefUpdateType.AUTO_CLOSE_CHANGES)) {
                      autoCloseChanges(c, closeProgress);
                    }
                    closeProgress.end();
                    break;

                  case DELETE:
                    break;
                }
              });
    }
  }

  /** Appends messages for successful change creation/updates. */
  private void queueSuccessMessages(List<CreateRequest> newChanges) {
    // adjacency list for commit => parent
    Map<String, String> adjList = new HashMap<>();
    for (CreateRequest cr : newChanges) {
      String parent = cr.commit.getParentCount() == 0 ? null : cr.commit.getParent(0).name();
      adjList.put(cr.commit.name(), parent);
    }
    for (ReplaceRequest rr : replaceByChange.values()) {
      String parent = null;
      if (rr.revCommit != null) {
        parent = rr.revCommit.getParentCount() == 0 ? null : rr.revCommit.getParent(0).name();
      }
      adjList.put(rr.newCommitId.name(), parent);
    }

    // get commits that are not parents
    Set<String> leafs = new TreeSet<>(adjList.keySet());
    leafs.removeAll(adjList.values());
    // go backwards from the last commit to its parent(s)
    Set<String> ordered = new LinkedHashSet<>();
    for (String leaf : leafs) {
      if (ordered.contains(leaf)) {
        continue;
      }
      while (leaf != null) {
        if (!ordered.contains(leaf)) {
          ordered.add(leaf);
        }
        leaf = adjList.get(leaf);
      }
    }
    // reverse the order to start with earliest commit
    List<String> orderedCommits = new ArrayList<>(ordered);
    Collections.reverse(orderedCommits);

    Map<String, CreateRequest> created =
        newChanges.stream()
            .filter(r -> r.change != null)
            .collect(Collectors.toMap(r -> r.commit.name(), r -> r));
    Map<String, ReplaceRequest> updated =
        replaceByChange.values().stream()
            .filter(r -> r.inputCommand.getResult() == OK)
            .collect(Collectors.toMap(r -> r.newCommitId.name(), r -> r));

    if (created.isEmpty() && updated.isEmpty()) {
      return;
    }

    addMessage("");
    addMessage("SUCCESS");
    addMessage("");

    boolean edit = false;
    Boolean isPrivate = null;
    Boolean wip = null;
    if (!updated.isEmpty()) {
      edit = magicBranch != null && magicBranch.edit;
      if (magicBranch != null) {
        if (magicBranch.isPrivate) {
          isPrivate = true;
        } else if (magicBranch.removePrivate) {
          isPrivate = false;
        }
        if (magicBranch.workInProgress) {
          wip = true;
        } else if (magicBranch.ready) {
          wip = false;
        }
      }
    }

    for (String commit : orderedCommits) {
      if (created.get(commit) != null) {
        addCreatedMessage(created.get(commit));
      } else if (updated.get(commit) != null) {
        addReplacedMessage(updated.get(commit), edit, isPrivate, wip);
      }
    }
    addMessage("");
  }

  private void addCreatedMessage(CreateRequest c) {
    addMessage(
        changeFormatter.newChange(
            ChangeReportFormatter.Input.builder().setChange(c.change).build()));
  }

  private void addReplacedMessage(ReplaceRequest u, boolean edit, Boolean isPrivate, Boolean wip) {
    String subject;
    if (edit) {
      subject =
          u.revCommit == null ? u.notes.getChange().getSubject() : u.revCommit.getShortMessage();
    } else {
      subject = u.info.getSubject();
    }

    if (isPrivate == null) {
      isPrivate = u.notes.getChange().isPrivate();
    }
    if (wip == null) {
      wip = u.notes.getChange().isWorkInProgress();
    }

    ChangeReportFormatter.Input input =
        ChangeReportFormatter.Input.builder()
            .setChange(u.notes.getChange())
            .setSubject(subject)
            .setIsEdit(edit)
            .setIsPrivate(isPrivate)
            .setIsWorkInProgress(wip)
            .build();
    addMessage(changeFormatter.changeUpdated(input));
    u.getOutdatedApprovalsMessage().map(msg -> "\n" + msg + "\n").ifPresent(this::addMessage);
  }

  private void insertChangesAndPatchSets(
      ImmutableList<CreateRequest> newChanges, Task replaceProgress) {
    try (RefUpdateContext ctx = RefUpdateContext.open(CHANGE_MODIFICATION)) {
      try (TraceTimer traceTimer =
          newTimer(
              "insertChangesAndPatchSets", Metadata.builder().resourceCount(newChanges.size()))) {
        ReceiveCommand magicBranchCmd = magicBranch != null ? magicBranch.cmd : null;
        if (magicBranchCmd != null && magicBranchCmd.getResult() != NOT_ATTEMPTED) {
          logger.atWarning().log(
              "Skipping change updates on %s because ref update failed: %s %s",
              project.getName(),
              magicBranchCmd.getResult(),
              Strings.nullToEmpty(magicBranchCmd.getMessage()));
          return;
        }
        try {
          if (!newChanges.isEmpty()) {
            // TODO: Retry lock failures on new change insertions. The retry will
            //  likely have to move to a higher layer to be able to achieve that
            //  due to state that needs to be reset with each retry attempt.
            insertChangesAndPatchSets(magicBranchCmd, newChanges, replaceProgress);
          } else {
            retryHelper
                .changeUpdate(
                    "insertPatchSets",
                    updateFactory -> {
                      insertChangesAndPatchSets(magicBranchCmd, newChanges, replaceProgress);
                      return null;
                    })
                .defaultTimeoutMultiplier(5)
                .call();
          }
        } catch (ResourceConflictException e) {
          addError(e.getMessage());
          reject(magicBranchCmd, "conflict");
        } catch (BadRequestException | UnprocessableEntityException | AuthException e) {
          logger.atFine().withCause(e).log("Rejecting due to client error");
          reject(magicBranchCmd, e.getMessage());
        } catch (RestApiException | IOException | UpdateException e) {
          throw new StorageException("Can't insert change/patch set for " + project.getName(), e);
        }

        if (magicBranch != null && magicBranch.submit) {
          try {
            submit(newChanges, replaceByChange.values());
          } catch (ResourceConflictException e) {
            addError(e.getMessage());
            reject(magicBranchCmd, "conflict");
          } catch (RestApiException
              | StorageException
              | UpdateException
              | IOException
              | ConfigInvalidException
              | PermissionBackendException e) {
            logger.atSevere().withCause(e).log("Error submitting changes to %s", project.getName());
            reject(magicBranchCmd, "error during submit");
          }
        }
      }
    }
  }

  private void insertChangesAndPatchSets(
      ReceiveCommand magicBranchCmd, List<CreateRequest> newChanges, Task replaceProgress)
      throws RestApiException, IOException {
    try (BatchUpdate bu =
            batchUpdateFactory.create(
                project.getNameKey(), user.materializedCopy(), TimeUtil.now());
        ObjectInserter ins = repo.newObjectInserter();
        ObjectReader reader = ins.newReader();
        RevWalk rw = new RevWalk(reader)) {
      bu.setRepository(repo, rw, ins);
      bu.setRefLogMessage("push");
      if (magicBranch != null) {
        bu.setNotify(magicBranch.getNotifyForNewChange());
      }

      logger.atFine().log("Adding %d replace requests", newChanges.size());
      for (ReplaceRequest replace : replaceByChange.values()) {
        replace.addOps(bu, replaceProgress);
        if (magicBranch != null) {
          bu.setNotifyHandling(replace.ontoChange, magicBranch.getNotifyHandling(replace.notes));
          if (magicBranch.shouldPublishComments()) {
            bu.addOp(
                replace.notes.getChangeId(),
                publishCommentsOp.create(replace.psId, project.getNameKey()));
            Optional<ChangeNotes> changeNotes = getChangeNotes(replace.notes.getChangeId());
            if (!changeNotes.isPresent()) {
              // If not present, no need to update attention set here since this is
              // a new change.
              continue;
            }
            List<HumanComment> drafts =
                draftCommentsReader.getDraftsByChangeAndDraftAuthor(
                    changeNotes.get(), user.getAccountId());
            if (drafts.isEmpty()) {
              // If no comments, attention set shouldn't update since the user
              // didn't reply.
              continue;
            }
            replyAttentionSetUpdates.processAutomaticAttentionSetRulesOnReply(
                bu, changeNotes.get(), isReadyForReview(changeNotes.get()), user, drafts);
          }
        }
      }

      logger.atFine().log("Adding %d create requests", newChanges.size());
      for (CreateRequest create : newChanges) {
        create.addOps(bu);
      }

      logger.atFine().log("Executing batch");
      try {
        bu.execute();
      } catch (UpdateException e) {
        throw asRestApiException(e);
      }

      replaceByChange.values().stream()
          .forEach(
              req -> result.addChange(ReceiveCommitsResult.ChangeStatus.REPLACED, req.ontoChange));
      newChanges.stream()
          .forEach(
              req -> result.addChange(ReceiveCommitsResult.ChangeStatus.CREATED, req.changeId));

      if (magicBranchCmd != null) {
        magicBranchCmd.setResult(OK);
      }
      for (ReplaceRequest replace : replaceByChange.values()) {
        String rejectMessage = replace.getRejectMessage();
        if (rejectMessage == null) {
          if (replace.inputCommand.getResult() == NOT_ATTEMPTED) {
            // Not necessarily the magic branch, so need to set OK on the original
            // value.
            replace.inputCommand.setResult(OK);
          }
        } else {
          logger.atFine().log("Rejecting due to message from ReplaceOp");
          reject(replace.inputCommand, rejectMessage);
        }
      }
    }
  }

  private boolean isReadyForReview(ChangeNotes changeNotes) {
    return (!changeNotes.getChange().isWorkInProgress() && !magicBranch.workInProgress)
        || magicBranch.ready;
  }

  private String buildError(String error, List<String> branches) {
    StringBuilder sb = new StringBuilder();
    if (branches.size() == 1) {
      String branch = branches.get(0);
      sb.append("branch ").append(branch).append(":\n");
      // As of 2020, there are still many git-review <1.27 installations in the wild.
      // These users will see failures as their old git-review assumes that
      // `refs/publish/...` is still magic, which it isn't. As Gerrit's default error messages are
      // misleading for these users, we hint them at upgrading their git-review.
      if (branch.startsWith("refs/publish/")) {
        sb.append("If you are using git-review, update to at least git-review 1.27. Otherwise:\n");
      }
      sb.append(error);
      return sb.toString();
    }
    sb.append("branches ").append(Joiner.on(", ").join(branches));
    return sb.append(":\n").append(error).toString();
  }

  /** Parses push options specified as "git push -o OPTION" */
  private void parsePushOptions() {
    List<String> optionList = receivePack.getPushOptions();
    if (optionList != null) {
      for (String option : optionList) {
        int e = option.indexOf('=');
        if (e > 0) {
          pushOptions.put(option.substring(0, e), option.substring(e + 1));
        } else {
          pushOptions.put(option, "");
        }
      }
    }

    List<String> noteDbValues = pushOptions.get("notedb");
    if (!noteDbValues.isEmpty()) {
      // These semantics for duplicates/errors are somewhat arbitrary and may not match e.g. the
      // CmdLineParser behavior used by MagicBranchInput.
      String value = Iterables.getLast(noteDbValues);
      noteDbPushOption = NoteDbPushOption.parse(value);
      if (!noteDbPushOption.isPresent()) {
        addError("Invalid value in -o " + NoteDbPushOption.OPTION_NAME + "=" + value);
      }
    } else {
      noteDbPushOption = Optional.of(NoteDbPushOption.DISALLOW);
    }

    List<String> traceValues = pushOptions.get("trace");
    if (!traceValues.isEmpty()) {
      tracePushOption = Optional.of(Iterables.getLast(traceValues));
    } else {
      tracePushOption = Optional.empty();
    }
  }

  // Wrap ReceiveCommand so the progress counter works automatically.
  private ReceiveCommand wrapReceiveCommand(ReceiveCommand cmd, Task progress) {
    String refname = cmd.getRefName();

    if (isRefsUsersSelf(cmd.getRefName(), projectState.isAllUsers())) {
      refname = RefNames.refsUsers(user.getAccountId());
      logger.atFine().log("Swapping out command for %s to %s", RefNames.REFS_USERS_SELF, refname);
    }

    // We must also update the original, because callers may inspect it afterwards to decide if
    // the command went through or not.
    return new ReceiveCommand(cmd.getOldId(), cmd.getNewId(), refname, cmd.getType()) {
      @Override
      public void setResult(Result s, String m) {
        if (getResult() == NOT_ATTEMPTED) { // Only report the progress update once.
          progress.update(1);
        }
        // Counter intuitively, we don't check that results == NOT_ATTEMPTED here.
        // This is so submit-on-push can still reject the update if the change is created
        // successfully
        // (status OK) but the submit failed (merge failed: REJECTED_OTHER_REASON).
        super.setResult(s, m);
        cmd.setResult(s, m);
      }
    };
  }

  /*
   * Interpret a normal push.
   */
  private void parseRegularCommand(ReceiveCommand cmd)
      throws PermissionBackendException, NoSuchProjectException, IOException {
    try (TraceTimer traceTimer = newTimer("parseRegularCommand")) {
      if (cmd.getResult() != NOT_ATTEMPTED) {
        // Already rejected by the core receive process.
        logger.atFine().log("Already processed by core: %s %s", cmd.getResult(), cmd);
        return;
      }

      if (!Repository.isValidRefName(cmd.getRefName()) || cmd.getRefName().contains("//")) {
        reject(cmd, "not valid ref");
        return;
      }
      if (RefNames.isNoteDbMetaRef(cmd.getRefName())) {
        // Reject pushes to NoteDb refs without a special option and permission. Note that this
        // prohibition doesn't depend on NoteDb being enabled in any way, since all sites will
        // migrate to NoteDb eventually, and we don't want garbage data waiting there when the
        // migration finishes.
        logger.atFine().log(
            "%s NoteDb ref %s with %s=%s",
            cmd.getType(), cmd.getRefName(), NoteDbPushOption.OPTION_NAME, noteDbPushOption);
        if (!Optional.of(NoteDbPushOption.ALLOW).equals(noteDbPushOption)) {
          // Only reject this command, not the whole push. This supports the use case of "git clone
          // --mirror" followed by "git push --mirror", when the user doesn't really intend to clone
          // or mirror the NoteDb data; there is no single refspec that describes all refs *except*
          // NoteDb refs.
          reject(
              cmd,
              "NoteDb update requires -o "
                  + NoteDbPushOption.OPTION_NAME
                  + "="
                  + NoteDbPushOption.ALLOW.value());
          return;
        }
        if (!permissionBackend.user(user).test(GlobalPermission.ACCESS_DATABASE)) {
          reject(cmd, "NoteDb update requires access database permission");
          return;
        }
      }

      switch (cmd.getType()) {
        case CREATE:
          parseCreate(cmd);
          break;

        case UPDATE:
          parseUpdate(cmd);
          break;

        case DELETE:
          parseDelete(cmd);
          break;

        case UPDATE_NONFASTFORWARD:
          parseRewind(cmd);
          break;

        default:
          reject(cmd, "prohibited by Gerrit: unknown command type " + cmd.getType());
          return;
      }

      if (cmd.getResult() != NOT_ATTEMPTED) {
        return;
      }

      if (isConfig(cmd)) {
        validateConfigPush(cmd);
      }
    }
  }

  /** Validates a push to refs/meta/config, and reject the command if it fails. */
  private void validateConfigPush(ReceiveCommand cmd) throws PermissionBackendException {
    try (TraceTimer traceTimer = newTimer("validateConfigPush")) {
      logger.atFine().log("Processing %s command", cmd.getRefName());
      if (!permissions.test(ProjectPermission.WRITE_CONFIG)) {
        reject(
            cmd,
            String.format(
                "must be either project owner or have %s permission",
                ProjectPermission.WRITE_CONFIG.describeForException()));
        return;
      }

      switch (cmd.getType()) {
        case CREATE:
        case UPDATE:
        case UPDATE_NONFASTFORWARD:
          try {
            ProjectConfig cfg = projectConfigFactory.create(project.getNameKey());
            cfg.load(project.getNameKey(), receivePack.getRevWalk(), cmd.getNewId());
            if (!cfg.getValidationErrors().isEmpty()) {
              addError("Invalid project configuration:");
              for (ValidationError err : cfg.getValidationErrors()) {
                addError("  " + err.getMessage());
              }
              reject(cmd, "invalid project configuration");
              logger.atSevere().log(
                  "User %s tried to push invalid project configuration %s for %s",
                  user.getLoggableName(), cmd.getNewId().name(), project.getName());
              return;
            }
            Project.NameKey newParent = cfg.getProject().getParent(allProjectsName);
            Project.NameKey oldParent = project.getParent(allProjectsName);
            if (oldParent == null) {
              // update of the 'All-Projects' project
              if (newParent != null) {
                reject(cmd, "invalid project configuration: root project cannot have parent");
                return;
              }
            } else {
              if (!oldParent.equals(newParent)) {
                if (allowProjectOwnersToChangeParent) {
                  if (!permissionBackend
                      .user(user)
                      .project(project.getNameKey())
                      .test(ProjectPermission.WRITE_CONFIG)) {
                    reject(
                        cmd, "invalid project configuration: only project owners can set parent");
                    return;
                  }
                } else {
                  if (!permissionBackend.user(user).test(GlobalPermission.ADMINISTRATE_SERVER)) {
                    reject(cmd, "invalid project configuration: only Gerrit admin can set parent");
                    return;
                  }
                }
              }

              if (!projectCache.get(newParent).isPresent()) {
                reject(cmd, "invalid project configuration: parent does not exist");
                return;
              }
            }
            validatePluginConfig(cmd, cfg);
          } catch (Exception e) {
            reject(cmd, "invalid project configuration");
            logger.atSevere().withCause(e).log(
                "User %s tried to push invalid project configuration %s for %s",
                user.getLoggableName(), cmd.getNewId().name(), project.getName());
            return;
          }
          break;

        case DELETE:
          break;

        default:
          reject(
              cmd,
              "prohibited by Gerrit: don't know how to handle config update of type "
                  + cmd.getType());
      }
    }
  }

  /**
   * validates a push to refs/meta/config for plugin configuration, and rejects the push if it
   * fails.
   */
  private void validatePluginConfig(ReceiveCommand cmd, ProjectConfig cfg) {
    for (Extension<ProjectConfigEntry> e : pluginConfigEntries) {
      PluginConfig pluginCfg = cfg.getPluginConfig(e.getPluginName());
      ProjectConfigEntry configEntry = e.getProvider().get();
      String value = pluginCfg.getString(e.getExportName());
      String oldValue =
          projectState.getPluginConfig(e.getPluginName()).getString(e.getExportName());
      if (configEntry.getType() == ProjectConfigEntryType.ARRAY) {
        oldValue =
            Arrays.stream(
                    projectState
                        .getPluginConfig(e.getPluginName())
                        .getStringList(e.getExportName()))
                .collect(joining("\n"));
      }

      if ((value == null ? oldValue != null : !value.equals(oldValue))
          && !configEntry.isEditable(projectState)) {
        reject(
            cmd,
            String.format(
                "invalid project configuration: Not allowed to set parameter"
                    + " '%s' of plugin '%s' on project '%s'.",
                e.getExportName(), e.getPluginName(), project.getName()));
        continue;
      }

      if (ProjectConfigEntryType.LIST.equals(configEntry.getType())
          && value != null
          && !configEntry.getPermittedValues().contains(value)) {
        reject(
            cmd,
            String.format(
                "invalid project configuration: The value '%s' is "
                    + "not permitted for parameter '%s' of plugin '%s'.",
                value, e.getExportName(), e.getPluginName()));
      }
    }
  }

  private void parseCreate(ReceiveCommand cmd)
      throws PermissionBackendException, NoSuchProjectException, IOException {
    try (TraceTimer traceTimer = newTimer("parseCreate")) {
      if (repo.resolve(cmd.getRefName()) != null) {
        reject(
            cmd,
            String.format("Cannot create ref '%s' because it already exists.", cmd.getRefName()));
        return;
      }
      RevObject obj;
      try {
        obj = receivePack.getRevWalk().parseAny(cmd.getNewId());
      } catch (IOException e) {
        throw new StorageException(
            String.format(
                "Invalid object %s for %s creation", cmd.getNewId().name(), cmd.getRefName()),
            e);
      }
      logger.atFine().log("Creating %s", cmd);

      if (isHead(cmd) && !isCommit(cmd)) {
        return;
      }

      BranchNameKey branch = BranchNameKey.create(project.getName(), cmd.getRefName());
      try {
        // Must pass explicit user instead of injecting a provider into CreateRefControl, since
        // Provider<CurrentUser> within ReceiveCommits will always return anonymous.
        createRefControl.checkCreateRef(
            Providers.of(user), receivePack.getRepository(), branch, obj, /* forPush= */ true);
      } catch (AuthException denied) {
        rejectProhibited(cmd, denied);
        return;
      } catch (ResourceConflictException denied) {
        reject(cmd, "prohibited by Gerrit: " + denied.getMessage());
        return;
      }

      if (validRefOperation(cmd)) {
        validateRegularPushCommits(
            BranchNameKey.create(project.getNameKey(), cmd.getRefName()), cmd);
      }
    }
  }

  private void parseUpdate(ReceiveCommand cmd) throws PermissionBackendException {
    try (TraceTimer traceTimer = TraceContext.newTimer("parseUpdate")) {
      logger.atFine().log("Updating %s", cmd);
      Optional<AuthException> err = checkRefPermission(cmd, RefPermission.UPDATE);
      if (!err.isPresent()) {
        if (isHead(cmd) && !isCommit(cmd)) {
          reject(cmd, "head must point to commit");
          return;
        }
        if (validRefOperation(cmd)) {
          validateRegularPushCommits(
              BranchNameKey.create(project.getNameKey(), cmd.getRefName()), cmd);
        }
      } else {
        rejectProhibited(cmd, err.get());
      }
    }
  }

  private boolean isCommit(ReceiveCommand cmd) {
    RevObject obj;
    try {
      obj = receivePack.getRevWalk().parseAny(cmd.getNewId());
    } catch (IOException e) {
      throw new StorageException(
          String.format(
              "Invalid object %s for %s creation", cmd.getNewId().name(), cmd.getRefName()),
          e);
    }

    if (obj instanceof RevCommit) {
      return true;
    }
    reject(cmd, "not a commit");
    return false;
  }

  private void parseDelete(ReceiveCommand cmd) throws PermissionBackendException {
    try (TraceTimer traceTimer = newTimer("parseDelete")) {
      logger.atFine().log("Deleting %s", cmd);
      if (cmd.getRefName().startsWith(REFS_CHANGES)) {
        errors.put(CANNOT_DELETE_CHANGES, cmd.getRefName());
        reject(cmd, "cannot delete changes");
      } else if (isConfigRef(cmd.getRefName())) {
        errors.put(CANNOT_DELETE_CONFIG, cmd.getRefName());
        reject(cmd, "cannot delete project configuration");
      }

      Optional<AuthException> err = checkRefPermission(cmd, RefPermission.DELETE);
      if (!err.isPresent()) {
        validRefOperation(cmd);
      } else {
        rejectProhibited(cmd, err.get());
      }
    }
  }

  private void parseRewind(ReceiveCommand cmd) throws PermissionBackendException {
    try (TraceTimer traceTimer = newTimer("parseRewind")) {
      try {
        receivePack.getRevWalk().parseCommit(cmd.getNewId());
      } catch (IOException e) {
        throw new StorageException(
            String.format(
                "Invalid object %s for %s creation", cmd.getNewId().name(), cmd.getRefName()),
            e);
      }
      logger.atFine().log("Rewinding %s", cmd);

      if (!validRefOperation(cmd)) {
        return;
      }
      validateRegularPushCommits(BranchNameKey.create(project.getNameKey(), cmd.getRefName()), cmd);
      if (cmd.getResult() != NOT_ATTEMPTED) {
        return;
      }

      Optional<AuthException> err = checkRefPermission(cmd, RefPermission.FORCE_UPDATE);
      if (err.isPresent()) {
        rejectProhibited(cmd, err.get());
      }
    }
  }

  private Optional<AuthException> checkRefPermission(ReceiveCommand cmd, RefPermission perm)
      throws PermissionBackendException {
    return checkRefPermission(permissions.ref(cmd.getRefName()), perm);
  }

  private Optional<AuthException> checkRefPermission(
      PermissionBackend.ForRef forRef, RefPermission perm) throws PermissionBackendException {
    try {
      forRef.check(perm);
      return Optional.empty();
    } catch (AuthException e) {
      return Optional.of(e);
    }
  }

  private void rejectProhibited(ReceiveCommand cmd, AuthException err) {
    err.getAdvice().ifPresent(a -> errors.put(a, cmd.getRefName()));
    reject(cmd, prohibited(err, cmd.getRefName()));
  }

  private static String prohibited(AuthException e, String alreadyDisplayedResource) {
    String msg = e.getMessage();
    if (e instanceof PermissionDeniedException) {
      PermissionDeniedException pde = (PermissionDeniedException) e;
      if (pde.getResource().isPresent()
          && pde.getResource().get().equals(alreadyDisplayedResource)) {
        // Avoid repeating resource name if exactly the given name was already displayed by the
        // generic git push machinery.
        msg = PermissionDeniedException.MESSAGE_PREFIX + pde.describePermission();
      }
    }
    return "prohibited by Gerrit: " + msg;
  }

  static class MagicBranchInput {
    private static final Splitter COMMAS = Splitter.on(',').omitEmptyStrings();

    private final IdentifiedUser user;
    private final ProjectState projectState;
    private final boolean defaultPublishComments;

    final ReceiveCommand cmd;
    final LabelTypes labelTypes;
    /**
     * Draft comments are published with the commit iff {@code --publish-comments} is set. All
     * drafts are withheld (overriding the option) if at least one of the following conditions are
     * met:
     *
     * <ul>
     *   <li>Installed {@link CommentValidator} plugins reject one or more draft comments.
     *   <li>One or more comments exceed the maximum comment size (see {@link
     *       CommentSizeValidator}).
     *   <li>The maximum number of comments would be exceeded (see {@link CommentCountValidator}).
     * </ul>
     */
    private boolean withholdComments = false;

    BranchNameKey dest;
    PermissionBackend.ForRef perm;
    Set<String> reviewer = Sets.newLinkedHashSet();
    Set<String> cc = Sets.newLinkedHashSet();
    Map<String, Short> labels = new HashMap<>();
    String message;
    List<RevCommit> baseCommit;
    CmdLineParser cmdLineParser;
    Set<String> hashtags = new HashSet<>();

    @Option(name = "--trace", metaVar = "NAME", usage = "enable tracing")
    String trace;

    @Option(
        name = "--deadline",
        metaVar = "NAME",
        usage = "deadline after which the push should be aborted")
    String deadline;

    @Option(name = "--base", metaVar = "BASE", usage = "merge base of changes")
    List<ObjectId> base;

    @Option(name = "--topic", metaVar = "NAME", usage = "attach topic to changes")
    String topic;

    @Option(name = "--private", usage = "mark new/updated change as private")
    boolean isPrivate;

    @Option(name = "--remove-private", usage = "remove privacy flag from updated change")
    boolean removePrivate;

    /**
     * The skip-validation option is defined to allow parsing it using the {@link #cmdLineParser}.
     * However we do not allow this option for pushes to magic branches. This option is used to fail
     * with a proper error message.
     */
    @Option(name = "--skip-validation", usage = "skips commit validation")
    boolean skipValidation;

    @Option(
        name = "--wip",
        aliases = {"-work-in-progress"},
        usage = "mark change as work in progress")
    boolean workInProgress;

    @Option(name = "--ready", usage = "mark change as ready")
    boolean ready;

    @Option(
        name = "--edit",
        aliases = {"-e"},
        usage = "upload as change edit")
    boolean edit;

    @Option(name = "--submit", usage = "immediately submit the change")
    boolean submit;

    @Option(name = "--merged", usage = "create single change for a merged commit")
    boolean merged;

    @Option(name = "--publish-comments", usage = "publish all draft comments on updated changes")
    private boolean publishComments;

    @Option(
        name = "--no-publish-comments",
        aliases = {"--np"},
        usage = "do not publish draft comments")
    private boolean noPublishComments;

    @Option(
        name = "--notify",
        usage =
            "Notify handling that defines to whom email notifications "
                + "should be sent. Allowed values are NONE, OWNER, "
                + "OWNER_REVIEWERS, ALL. If not set, the default is ALL.")
    private NotifyHandling notifyHandling;

    @Option(
        name = "--notify-to",
        metaVar = "USER",
        usage = "user that should be notified one time by email")
    List<Account.Id> notifyTo = new ArrayList<>();

    @Option(
        name = "--notify-cc",
        metaVar = "USER",
        usage = "user that should be CC'd one time by email")
    List<Account.Id> notifyCc = new ArrayList<>();

    @Option(
        name = "--notify-bcc",
        metaVar = "USER",
        usage = "user that should be BCC'd one time by email")
    List<Account.Id> notifyBcc = new ArrayList<>();

    @Option(
        name = "--reviewer",
        aliases = {"-r"},
        metaVar = "REVIEWER",
        usage = "add reviewer to changes")
    void reviewer(String str) {
      reviewer.add(str);
    }

    @Option(name = "--cc", metaVar = "CC", usage = "add CC to changes")
    void cc(String str) {
      cc.add(str);
    }

    @Option(
        name = "--label",
        aliases = {"-l"},
        metaVar = "LABEL+VALUE",
        usage = "label(s) to assign (defaults to +1 if no value provided)")
    void addLabel(String token) throws CmdLineException {
      LabelVote v = LabelVote.parse(token);
      try {
        LabelType.checkName(v.label());
        ApprovalsUtil.checkLabel(labelTypes, v.label(), v.value());
      } catch (BadRequestException e) {
        throw cmdLineParser.reject(e.getMessage());
      }
      labels.put(v.label(), v.value());
    }

    @Option(
        name = "--message",
        aliases = {"-m"},
        metaVar = "MESSAGE",
        usage = "Comment message to apply to the review")
    void addMessage(String token) {
      // Many characters have special meaning in the context of a git ref.
      //
      // Clients can use underscores to represent spaces.
      message = token.replace("_", " ");
      try {
        // Other characters can be represented using percent-encoding.
        message = URLDecoder.decode(message, UTF_8.name());
      } catch (IllegalArgumentException e) {
        // Ignore decoding errors; leave message as percent-encoded.
      } catch (UnsupportedEncodingException e) {
        // This shouldn't happen; surely URLDecoder recognizes UTF-8.
        throw new IllegalStateException(e);
      }
    }

    @Option(
        name = "--hashtag",
        aliases = {"-t"},
        metaVar = "HASHTAG",
        usage = "add hashtag to changes")
    void addHashtag(String token) {
      String hashtag = cleanupHashtag(token);
      if (!hashtag.isEmpty()) {
        hashtags.add(hashtag);
      }
    }

    @UsedAt(UsedAt.Project.GOOGLE)
    @SuppressWarnings("unused") // unused in upstream, but used at Google
    @Option(name = "--create-cod-token", usage = "create a token for consistency-on-demand")
    private boolean createCodToken;

    @Option(
        name = "--ignore-automatic-attention-set-rules",
        aliases = {"-ias", "-ignore-attention-set"},
        usage = "do not change the attention set on this push")
    boolean ignoreAttentionSet;

    MagicBranchInput(
        IdentifiedUser user, ProjectState projectState, ReceiveCommand cmd, LabelTypes labelTypes) {
      this.user = user;
      this.projectState = projectState;
      this.cmd = cmd;
      this.labelTypes = labelTypes;
      GeneralPreferencesInfo prefs = user.state().generalPreferences();
      this.defaultPublishComments =
          prefs != null
              ? firstNonNull(user.state().generalPreferences().publishCommentsOnPush, false)
              : false;
    }

    /**
     * Get reviewer strings from magic branch options, combined with additional recipients computed
     * from some other place.
     *
     * <p>The set of reviewers on a change includes strings passed explicitly via options as well as
     * account IDs computed from the commit message itself.
     *
     * @param additionalRecipients recipients parsed from the commit.
     * @return set of reviewer strings to pass to {@code ReviewerModifier}.
     */
    ImmutableSet<String> getCombinedReviewers(MailRecipients additionalRecipients) {
      return getCombinedReviewers(reviewer, additionalRecipients.getReviewers());
    }

    /**
     * Get CC strings from magic branch options, combined with additional recipients computed from
     * some other place.
     *
     * <p>The set of CCs on a change includes strings passed explicitly via options as well as
     * account IDs computed from the commit message itself.
     *
     * @param additionalRecipients recipients parsed from the commit.
     * @return set of CC strings to pass to {@code ReviewerModifier}.
     */
    ImmutableSet<String> getCombinedCcs(MailRecipients additionalRecipients) {
      return getCombinedReviewers(cc, additionalRecipients.getCcOnly());
    }

    private static ImmutableSet<String> getCombinedReviewers(
        Set<String> strings, Set<Account.Id> ids) {
      return Streams.concat(strings.stream(), ids.stream().map(Account.Id::toString))
          .collect(toImmutableSet());
    }

    void setWithholdComments(boolean withholdComments) {
      this.withholdComments = withholdComments;
    }

    boolean shouldPublishComments() {
      if (withholdComments) {
        // Validation messages of type WARNING have already been added, now withhold the comments.
        return false;
      }
      if (publishComments) {
        return true;
      }
      if (noPublishComments) {
        return false;
      }
      return defaultPublishComments;
    }

    /**
     * returns the destination ref of the magic branch, and populates options in the cmdLineParser.
     */
    String parse(ListMultimap<String, String> pushOptions) throws CmdLineException {
      String ref = RefNames.fullName(MagicBranch.getDestBranchName(cmd.getRefName()));

      ListMultimap<String, String> options = LinkedListMultimap.create(pushOptions);

      // Process and lop off the "%OPTION" suffix.
      int optionStart = ref.indexOf('%');
      if (0 < optionStart) {
        for (String s : COMMAS.split(ref.substring(optionStart + 1))) {
          int e = s.indexOf('=');
          if (0 < e) {
            options.put(s.substring(0, e), s.substring(e + 1));
          } else {
            options.put(s, "");
          }
        }
        ref = ref.substring(0, optionStart);
      }

      if (!options.isEmpty()) {
        cmdLineParser.parseOptionMap(options);
      }
      return ref;
    }

    public boolean shouldSetWorkInProgressOnNewChanges() {
      // When wip or ready explicitly provided, leave it as is.
      if (workInProgress) {
        return true;
      }
      if (ready) {
        return false;
      }

      return projectState.is(BooleanProjectConfig.WORK_IN_PROGRESS_BY_DEFAULT)
          || firstNonNull(user.state().generalPreferences().workInProgressByDefault, false);
    }

    NotifyResolver.Result getNotifyForNewChange() {
      return NotifyResolver.Result.create(
          firstNonNull(
              notifyHandling,
              shouldSetWorkInProgressOnNewChanges() ? NotifyHandling.OWNER : NotifyHandling.ALL),
          ImmutableSetMultimap.<RecipientType, Account.Id>builder()
              .putAll(RecipientType.TO, notifyTo)
              .putAll(RecipientType.CC, notifyCc)
              .putAll(RecipientType.BCC, notifyBcc)
              .build());
    }

    NotifyHandling getNotifyHandling(ChangeNotes notes) {
      requireNonNull(notes);
      if (notifyHandling != null) {
        return notifyHandling;
      }
      if (workInProgress || (!ready && notes.getChange().isWorkInProgress())) {
        return NotifyHandling.OWNER;
      }
      return NotifyHandling.ALL;
    }
  }

  /**
   * Parse the magic branch data (refs/for/BRANCH/OPTIONALTOPIC%OPTIONS) into the magicBranch
   * member.
   *
   * <p>Assumes we are handling a magic branch here.
   */
  private void parseMagicBranch(ReceiveCommand cmd) throws PermissionBackendException, IOException {
    try (TraceTimer traceTimer = newTimer("parseMagicBranch")) {
      logger.atFine().log("Found magic branch %s", cmd.getRefName());
      MagicBranchInput magicBranch = new MagicBranchInput(user, projectState, cmd, labelTypes);

      String ref;
      magicBranch.cmdLineParser = optionParserFactory.create(magicBranch);

      // Filter out plugin push options, as the parser would reject them as unknown.
      ImmutableListMultimap<String, String> pushOptionsToParse =
          pushOptions.entries().stream()
              .filter(e -> !isPluginPushOption(e.getKey()))
              .collect(toImmutableListMultimap(e -> e.getKey(), e -> e.getValue()));
      try {
        ref = magicBranch.parse(pushOptionsToParse);
      } catch (CmdLineException e) {
        if (!magicBranch.cmdLineParser.wasHelpRequestedByOption()) {
          logger.atFine().log("Invalid branch syntax");
          reject(cmd, e.getMessage());
          return;
        }
        ref = null; // never happens
      }

      if (magicBranch.skipValidation) {
        reject(
            cmd,
            String.format(
                "\"--%s\" option is only supported for direct push", PUSH_OPTION_SKIP_VALIDATION));
        return;
      }

      if (magicBranch.topic != null && magicBranch.topic.length() > ChangeUtil.TOPIC_MAX_LENGTH) {
        reject(
            cmd, String.format("topic length exceeds the limit (%d)", ChangeUtil.TOPIC_MAX_LENGTH));
      }

      if (magicBranch.cmdLineParser.wasHelpRequestedByOption()) {
        StringWriter w = new StringWriter();
        w.write("\nHelp for refs/for/branch:\n\n");
        magicBranch.cmdLineParser.printUsage(w, null);

        String pluginPushOptionsHelp =
            StreamSupport.stream(pluginPushOptions.entries().spliterator(), /* parallel= */ false)
                .map(
                    e ->
                        String.format(
                            "-o %s~%s: %s",
                            e.getPluginName(), e.get().getName(), e.get().getDescription()))
                .sorted()
                .collect(joining("\n"));
        if (!pluginPushOptionsHelp.isEmpty()) {
          w.write("\nPlugin push options:\n" + pluginPushOptionsHelp);
        }

        addMessage(w.toString());
        reject(cmd, "see help");
        return;
      }
      if (projectState.isAllUsers() && RefNames.REFS_USERS_SELF.equals(ref)) {
        logger.atFine().log("Handling %s", RefNames.REFS_USERS_SELF);
        ref = RefNames.refsUsers(user.getAccountId());
      }
      // Pushing changes for review usually requires that the target branch exists, but there is an
      // exception for the branch to which HEAD points to and for refs/meta/config. Pushing for
      // review to these branches is allowed even if the branch does not exist yet. This allows to
      // push initial code for review to an empty repository and to review an initial project
      // configuration.
      if (receivePackRefCache.exactRef(ref) == null
          && !ref.equals(readHEAD(repo))
          && !ref.equals(RefNames.REFS_CONFIG)) {
        logger.atFine().log("Ref %s not found", ref);
        if (ref.startsWith(Constants.R_HEADS)) {
          String n = ref.substring(Constants.R_HEADS.length());
          reject(cmd, "branch " + n + " not found");
        } else {
          reject(cmd, ref + " not found");
        }
        return;
      }

      magicBranch.dest = BranchNameKey.create(project.getNameKey(), ref);
      magicBranch.perm = permissions.ref(ref);

      Optional<AuthException> err = checkRefPermission(magicBranch.perm, RefPermission.READ);
      if (err.isEmpty()) {
        err = checkRefPermission(magicBranch.perm, RefPermission.CREATE_CHANGE);
      }
      if (err.isPresent()) {
        rejectProhibited(cmd, err.get());
        return;
      }

      if (magicBranch.isPrivate && magicBranch.removePrivate) {
        reject(cmd, "the options 'private' and 'remove-private' are mutually exclusive");
        return;
      }

      boolean privateByDefault =
          projectCache
              .get(project.getNameKey())
              .orElseThrow(illegalState(project.getNameKey()))
              .is(BooleanProjectConfig.PRIVATE_BY_DEFAULT);
      setChangeAsPrivate =
          magicBranch.isPrivate || (privateByDefault && !magicBranch.removePrivate);

      if (receiveConfig.disablePrivateChanges && setChangeAsPrivate) {
        reject(cmd, "private changes are disabled");
        return;
      }

      if (magicBranch.workInProgress && magicBranch.ready) {
        reject(cmd, "the options 'wip' and 'ready' are mutually exclusive");
        return;
      }
      if (magicBranch.publishComments && magicBranch.noPublishComments) {
        reject(
            cmd, "the options 'publish-comments' and 'no-publish-comments' are mutually exclusive");
        return;
      }

      if (magicBranch.submit) {
        err = checkRefPermission(magicBranch.perm, RefPermission.UPDATE_BY_SUBMIT);
        if (err.isPresent()) {
          rejectProhibited(cmd, err.get());
          return;
        }
      }

      RevWalk walk = receivePack.getRevWalk();
      RevCommit tip;
      try {
        tip = walk.parseCommit(magicBranch.cmd.getNewId());
        logger.atFine().log("Tip of push: %s", tip.name());
      } catch (IOException ex) {
        magicBranch.cmd.setResult(REJECTED_MISSING_OBJECT);
        logger.atSevere().withCause(ex).log(
            "Invalid pack upload; one or more objects weren't sent");
        return;
      }

      String destBranch = magicBranch.dest.branch();
      try {
        if (magicBranch.merged) {
          if (magicBranch.base != null) {
            reject(cmd, "cannot use merged with base");
            return;
          }
          Ref refTip = receivePackRefCache.exactRef(magicBranch.dest.branch());
          if (refTip == null) {
            reject(cmd, magicBranch.dest.branch() + " not found");
            return;
          }
          RevCommit branchTip = receivePack.getRevWalk().parseCommit(refTip.getObjectId());
          if (!walk.isMergedInto(tip, branchTip)) {
            reject(cmd, "not merged into branch");
            return;
          }
        }

        // If tip is a merge commit, or the root commit or
        // if %base or %merged was specified, ignore newChangeForAllNotInTarget.
        if (tip.getParentCount() > 1
            || magicBranch.base != null
            || magicBranch.merged
            || tip.getParentCount() == 0) {
          logger.atFine().log("Forcing newChangeForAllNotInTarget = false");
          newChangeForAllNotInTarget = false;
        }

        if (magicBranch.base != null) {
          logger.atFine().log("Handling %%base: %s", magicBranch.base);
          magicBranch.baseCommit = Lists.newArrayListWithCapacity(magicBranch.base.size());
          for (ObjectId id : magicBranch.base) {
            try {
              magicBranch.baseCommit.add(walk.parseCommit(id));
            } catch (IncorrectObjectTypeException notCommit) {
              reject(cmd, "base must be a commit");
              return;
            } catch (MissingObjectException e) {
              reject(cmd, "base not found");
              return;
            } catch (IOException e) {
              throw new StorageException(
                  String.format("Project %s cannot read %s", project.getName(), id.name()), e);
            }
          }
        } else if (newChangeForAllNotInTarget) {
          Ref refTip = receivePackRefCache.exactRef(magicBranch.dest.branch());
          if (refTip != null) {
            RevCommit branchTip = receivePack.getRevWalk().parseCommit(refTip.getObjectId());
            magicBranch.baseCommit = Collections.singletonList(branchTip);
            logger.atFine().log("Set baseCommit = %s", magicBranch.baseCommit.get(0).name());
          } else {
            // The target branch does not exist. Usually pushing changes for review requires that
            // the
            // target branch exists, but there is an exception for the branch to which HEAD points
            // to
            // and for refs/meta/config. Pushing for review to these branches is allowed even if the
            // branch does not exist yet. This allows to push initial code for review to an empty
            // repository and to review an initial project configuration.
            if (!ref.equals(readHEAD(repo)) && !ref.equals(RefNames.REFS_CONFIG)) {
              reject(cmd, magicBranch.dest.branch() + " not found");
              return;
            }
          }
        }
      } catch (IOException e) {
        throw new StorageException(
            String.format("Error walking to %s in project %s", destBranch, project.getName()), e);
      }

      if (validateConnected(magicBranch.cmd, magicBranch.dest, tip)) {
        this.magicBranch = magicBranch;
        this.result.magicPush(true);
      }
    }
  }

  private boolean isPluginPushOption(String pushOptionName) {
    if (transitionalPluginOptions.contains(pushOptionName)) {
      return true;
    }
    return StreamSupport.stream(pluginPushOptions.entries().spliterator(), /* parallel= */ false)
        .anyMatch(e -> pushOptionName.equals(e.getPluginName() + "~" + e.get().getName()));
  }

  // Validate that the new commits are connected with the target
  // branch.  If they aren't, we want to abort. We do this check by
  // looking to see if we can compute a merge base between the new
  // commits and the target branch head.
  private boolean validateConnected(ReceiveCommand cmd, BranchNameKey dest, RevCommit tip) {
    try (TraceTimer traceTimer =
        newTimer("validateConnected", Metadata.builder().branchName(dest.branch()))) {
      RevWalk walk = receivePack.getRevWalk();
      try {
        Ref targetRef = receivePackRefCache.exactRef(dest.branch());
        if (targetRef == null || targetRef.getObjectId() == null) {
          // The destination branch does not yet exist. Assume the
          // history being sent for review will start it and thus
          // is "connected" to the branch.
          logger.atFine().log("Branch is unborn");

          // This is not an error condition.
          return true;
        }

        RevCommit h = walk.parseCommit(targetRef.getObjectId());
        logger.atFine().log("Current branch tip: %s", h.name());
        RevFilter oldRevFilter = walk.getRevFilter();
        try {
          walk.reset();
          walk.setRevFilter(RevFilter.MERGE_BASE);
          walk.markStart(tip);
          walk.markStart(h);
          if (walk.next() == null) {
            reject(cmd, "no common ancestry");
            return false;
          }
        } finally {
          walk.reset();
          walk.setRevFilter(oldRevFilter);
        }
      } catch (IOException e) {
        cmd.setResult(REJECTED_MISSING_OBJECT);
        logger.atSevere().withCause(e).log("Invalid pack upload; one or more objects weren't sent");
        return false;
      }
      return true;
    }
  }

  private static String readHEAD(Repository repo) {
    try {
      String head = repo.getFullBranch();
      logger.atFine().log("HEAD = %s", head);
      return head;
    } catch (IOException e) {
      throw new StorageException("Cannot read HEAD symref", e);
    }
  }

  /**
   * Update an existing change. If draft comments are to be published, these are validated and may
   * be withheld.
   *
   * @return True if the command succeeded, false if it was rejected.
   */
  private boolean requestReplaceAndValidateComments(
      ReceiveCommand cmd, boolean checkMergedInto, Change change, RevCommit newCommit)
      throws IOException {
    try (TraceTimer traceTimer = newTimer("requestReplaceAndValidateComments")) {
      if (change.isClosed()) {
        reject(
            cmd,
            changeFormatter.changeClosed(
                ChangeReportFormatter.Input.builder().setChange(change).build()));
        return false;
      }

      ReplaceRequest req = new ReplaceRequest(change.getId(), newCommit, cmd, checkMergedInto);
      if (replaceByChange.containsKey(req.ontoChange)) {
        reject(cmd, "duplicate request");
        return false;
      }

      if (magicBranch != null && magicBranch.shouldPublishComments()) {
        List<HumanComment> drafts =
            draftCommentsReader.getDraftsByChangeAndDraftAuthor(
                notesFactory.createChecked(change), user.getAccountId());
        ImmutableList<CommentForValidation> draftsForValidation =
            drafts.stream()
                .map(
                    comment ->
                        CommentForValidation.create(
                            CommentSource.HUMAN,
                            comment.lineNbr > 0
                                ? CommentType.INLINE_COMMENT
                                : CommentType.FILE_COMMENT,
                            comment.message,
                            comment.message.length()))
                .collect(toImmutableList());
        CommentValidationContext ctx =
            CommentValidationContext.create(
                change.getChangeId(), change.getProject().get(), change.getDest().branch());
        ImmutableList<CommentValidationFailure> commentValidationFailures =
            PublishCommentUtil.findInvalidComments(ctx, commentValidators, draftsForValidation);
        magicBranch.setWithholdComments(!commentValidationFailures.isEmpty());
        commentValidationFailures.forEach(
            failure ->
                addMessage(
                    "Comment validation failure: " + failure.getMessage(),
                    ValidationMessage.Type.WARNING));
      }

      replaceByChange.put(req.ontoChange, req);
      return true;
    }
  }

  private void warnAboutMissingChangeId(ImmutableList<CreateRequest> newChanges) {
    for (CreateRequest create : newChanges) {
      try {
        receivePack.getRevWalk().parseBody(create.commit);
      } catch (IOException e) {
        throw new StorageException("Can't parse commit", e);
      }
      List<String> idList = changeUtil.getChangeIdsFromFooter(create.commit);

      if (idList.isEmpty()) {
        messages.add(
            new ValidationMessage("warning: pushing without Change-Id is deprecated", false));
        break;
      }
    }
  }

  private ImmutableList<CreateRequest> selectNewAndReplacedChangesFromMagicBranch(Task newProgress)
      throws IOException {
    try (TraceTimer traceTimer = newTimer("selectNewAndReplacedChangesFromMagicBranch")) {
      logger.atFine().log("Finding new and replaced changes");
      List<CreateRequest> newChanges = new ArrayList<>();

      GroupCollector groupCollector =
          GroupCollector.create(receivePackRefCache, psUtil, notesFactory, project.getNameKey());

      BranchCommitValidator validator =
          commitValidatorFactory.create(projectState, magicBranch.dest, user);

      try {
        RevCommit start = setUpWalkForSelectingChanges();
        if (start == null) {
          return ImmutableList.of();
        }

        LinkedHashMap<RevCommit, ChangeLookup> pending = new LinkedHashMap<>();
        Set<Change.Key> newChangeIds = new HashSet<>();
        int maxBatchChanges = receiveConfig.getEffectiveMaxBatchChangesLimit(user);
        int total = 0;
        int alreadyTracked = 0;
        boolean rejectImplicitMerges =
            start.getParentCount() == 1
                && projectCache
                    .get(project.getNameKey())
                    .orElseThrow(illegalState(project.getNameKey()))
                    .is(BooleanProjectConfig.REJECT_IMPLICIT_MERGES)
                // Don't worry about implicit merges when creating changes for
                // already-merged commits; they're already in history, so it's too
                // late.
                && !magicBranch.merged;
        Set<RevCommit> mergedParents;
        if (rejectImplicitMerges) {
          mergedParents = new HashSet<>();
        } else {
          mergedParents = null;
        }

        for (; ; ) {
          RevCommit c = receivePack.getRevWalk().next();
          if (c == null) {
            break;
          }
          total++;
          receivePack.getRevWalk().parseBody(c);
          String name = c.name();
          groupCollector.visit(c);
          Collection<PatchSet.Id> existingPatchSets =
              receivePackRefCache.patchSetIdsFromObjectId(c);

          if (rejectImplicitMerges) {
            Collections.addAll(mergedParents, c.getParents());
            mergedParents.remove(c);
          }

          boolean commitAlreadyTracked = !existingPatchSets.isEmpty();
          if (commitAlreadyTracked) {
            alreadyTracked++;
            if (!(newChangeForAllNotInTarget || magicBranch.base != null)) {
              continue;
            }
          }

          List<String> idList = changeUtil.getChangeIdsFromFooter(c);
          if (!idList.isEmpty()) {
            pending.put(c, lookupByChangeKey(c, Change.key(idList.get(idList.size() - 1).trim())));
          } else {
            pending.put(c, lookupByCommit(c));
          }

          int n = pending.size() + newChanges.size();
          if (maxBatchChanges != 0 && n > maxBatchChanges) {
            logger.atFine().log("%d changes exceeds limit of %d", n, maxBatchChanges);
            reject(
                magicBranch.cmd,
                "the number of pushed changes in a batch exceeds the max limit " + maxBatchChanges);
            return ImmutableList.of();
          }

          if (commitAlreadyTracked) {
            boolean changeExistsOnDestBranch = false;
            for (ChangeData cd : pending.get(c).destChanges) {
              if (cd.change().getDest().equals(magicBranch.dest)) {
                changeExistsOnDestBranch = true;
                break;
              }
            }
            if (changeExistsOnDestBranch) {
              continue;
            }

            logger.atFine().log(
                "Creating new change for %s even though it is already tracked", name);
          }

          BranchCommitValidator.Result validationResult =
              validator.validateCommit(
                  repo,
                  receivePack.getRevWalk().getObjectReader(),
                  magicBranch.cmd,
                  c,
                  ImmutableListMultimap.copyOf(pushOptions),
                  magicBranch.merged,
                  rejectCommits,
                  null);
          messages.addAll(validationResult.messages());
          if (!validationResult.isValid()) {
            // Not a change the user can propose? Abort as early as possible.
            logger.atFine().log("Aborting early due to invalid commit");
            return ImmutableList.of();
          }

          // Don't allow merges to be uploaded in commit chain via all-not-in-target
          if (newChangeForAllNotInTarget && c.getParentCount() > 1) {
            reject(
                magicBranch.cmd,
                "Pushing merges in commit chains with 'all not in target' is not allowed,\n"
                    + "to override please set the base manually");
            logger.atFine().log("Rejecting merge commit %s with newChangeForAllNotInTarget", name);
            // TODO(dborowitz): Should we early return here?
          }

          if (idList.isEmpty()) {
            newChanges.add(new CreateRequest(c, magicBranch.dest.branch(), newProgress));
            continue;
          }
        }
        logger.atFine().log(
            "Finished initial RevWalk with %d commits total: %d already"
                + " tracked, %d new changes with no Change-Id, and %d deferred"
                + " lookups",
            total, alreadyTracked, newChanges.size(), pending.size());

        if (rejectImplicitMerges) {
          rejectImplicitMerges(mergedParents);
        }

        for (Iterator<ChangeLookup> itr = pending.values().iterator(); itr.hasNext(); ) {
          ChangeLookup p = itr.next();
          if (p.changeKey == null) {
            continue;
          }

          if (newChangeIds.contains(p.changeKey)) {
            logger.atFine().log("Multiple commits with Change-Id %s", p.changeKey);
            reject(magicBranch.cmd, SAME_CHANGE_ID_IN_MULTIPLE_CHANGES);
            return ImmutableList.of();
          }

          List<ChangeData> changes = p.destChanges;
          if (changes.size() > 1) {
            logger.atFine().log(
                "Multiple changes in branch %s with Change-Id %s: %s",
                magicBranch.dest,
                p.changeKey,
                changes.stream().map(cd -> cd.getId().toString()).collect(joining()));
            // WTF, multiple changes in this branch have the same key?
            // Since the commit is new, the user should recreate it with
            // a different Change-Id. In practice, we should never see
            // this error message as Change-Id should be unique per branch.
            //
            reject(magicBranch.cmd, p.changeKey.get() + " has duplicates");
            return ImmutableList.of();
          }

          if (changes.size() == 1) {
            // Schedule as a replacement to this one matching change.
            //

            ObjectId currentPs = changes.get(0).currentPatchSet().commitId();
            // If Commit is already current PatchSet of target Change.
            if (p.commit.equals(currentPs)) {
              if (pending.size() == 1) {
                // There are no commits left to check, all commits in pending were already
                // current PatchSet of the corresponding target changes.
                reject(magicBranch.cmd, "commit(s) already exists (as current patchset)");
              } else {
                // Commit is already current PatchSet.
                // Remove from pending and try next commit.
                itr.remove();
                continue;
              }
            }
            if (requestReplaceAndValidateComments(
                magicBranch.cmd, false, changes.get(0).change(), p.commit)) {
              continue;
            }
            return ImmutableList.of();
          }

          if (changes.isEmpty()) {
            if (!isValidChangeId(p.changeKey.get())) {
              reject(magicBranch.cmd, "invalid Change-Id");
              return ImmutableList.of();
            }

            // In case the change look up from the index failed,
            // double check against the existing refs
            if (foundInExistingPatchSets(receivePackRefCache.patchSetIdsFromObjectId(p.commit))) {
              if (pending.size() == 1) {
                reject(magicBranch.cmd, "commit(s) already exists (as current patchset)");
                return ImmutableList.of();
              }
              itr.remove();
              continue;
            }
            newChangeIds.add(p.changeKey);
          }
          newChanges.add(new CreateRequest(p.commit, magicBranch.dest.branch(), newProgress));
        }
        logger.atFine().log(
            "Finished deferred lookups with %d updates and %d new changes",
            replaceByChange.size(), newChanges.size());
      } catch (IOException e) {
        // Should never happen, the core receive process would have
        // identified the missing object earlier before we got control.
        throw new StorageException("Invalid pack upload; one or more objects weren't sent", e);
      }

      if (newChanges.isEmpty() && replaceByChange.isEmpty()) {
        reject(magicBranch.cmd, "no new changes");
        return ImmutableList.of();
      }
      if (!newChanges.isEmpty() && magicBranch.edit) {
        reject(magicBranch.cmd, "edit is not supported for new changes");
        return ImmutableList.copyOf(newChanges);
      }

      SortedSetMultimap<ObjectId, String> groups = groupCollector.getGroups();
      List<Integer> newIds = seq.nextChangeIds(newChanges.size());
      for (int i = 0; i < newChanges.size(); i++) {
        CreateRequest create = newChanges.get(i);
        create.setChangeId(newIds.get(i));
        create.groups = ImmutableList.copyOf(groups.get(create.commit));
      }
      for (ReplaceRequest replace : replaceByChange.values()) {
        replace.groups = ImmutableList.copyOf(groups.get(replace.newCommitId));
      }
      logger.atFine().log("Finished updating groups from GroupCollector");
      return ImmutableList.copyOf(newChanges);
    }
  }

  private boolean foundInExistingPatchSets(Collection<PatchSet.Id> existingPatchSets) {
    try (TraceTimer traceTimer = newTimer("foundInExistingPatchSet")) {
      for (PatchSet.Id psId : existingPatchSets) {
        ChangeNotes notes = notesFactory.create(project.getNameKey(), psId.changeId());
        Change change = notes.getChange();
        if (change.getDest().equals(magicBranch.dest)) {
          logger.atFine().log("Found change %s from existing refs.", change.getKey());
          // Reindex the change asynchronously, ignoring errors.
          @SuppressWarnings("unused")
          Future<?> possiblyIgnoredError = indexer.indexAsync(project.getNameKey(), change.getId());
          return true;
        }
      }
      return false;
    }
  }

  private RevCommit setUpWalkForSelectingChanges() throws IOException {
    try (TraceTimer traceTimer = newTimer("setUpWalkForSelectingChanges")) {
      RevWalk rw = receivePack.getRevWalk();
      RevCommit start = rw.parseCommit(magicBranch.cmd.getNewId());

      rw.reset();
      rw.sort(RevSort.TOPO);
      rw.sort(RevSort.REVERSE, true);
      receivePack.getRevWalk().markStart(start);
      if (magicBranch.baseCommit != null) {
        markExplicitBasesUninteresting();
      } else if (magicBranch.merged) {
        logger.atFine().log("Marking parents of merged commit %s uninteresting", start.name());
        for (RevCommit c : start.getParents()) {
          rw.markUninteresting(c);
        }
      } else {
        markHeadsAsUninteresting(rw, magicBranch.dest != null ? magicBranch.dest.branch() : null);
      }
      return start;
    }
  }

  private void markExplicitBasesUninteresting() throws IOException {
    try (TraceTimer traceTimer = newTimer("markExplicitBasesUninteresting")) {
      logger.atFine().log("Marking %d base commits uninteresting", magicBranch.baseCommit.size());
      for (RevCommit c : magicBranch.baseCommit) {
        receivePack.getRevWalk().markUninteresting(c);
      }
      Ref targetRef = receivePackRefCache.exactRef(magicBranch.dest.branch());
      if (targetRef != null) {
        logger.atFine().log(
            "Marking target ref %s (%s) uninteresting",
            magicBranch.dest.branch(), targetRef.getObjectId().name());
        receivePack
            .getRevWalk()
            .markUninteresting(receivePack.getRevWalk().parseCommit(targetRef.getObjectId()));
      }
    }
  }

  private void rejectImplicitMerges(Set<RevCommit> mergedParents) throws IOException {
    try (TraceTimer traceTimer = newTimer("rejectImplicitMerges")) {
      if (!mergedParents.isEmpty()) {
        Ref targetRef = receivePackRefCache.exactRef(magicBranch.dest.branch());
        if (targetRef != null) {
          RevWalk rw = receivePack.getRevWalk();
          RevCommit tip = rw.parseCommit(targetRef.getObjectId());
          boolean containsImplicitMerges = true;
          for (RevCommit p : mergedParents) {
            containsImplicitMerges &= !rw.isMergedInto(p, tip);
          }

          if (containsImplicitMerges) {
            rw.reset();
            for (RevCommit p : mergedParents) {
              rw.markStart(p);
            }
            rw.markUninteresting(tip);
            RevCommit c;
            while ((c = rw.next()) != null) {
              rw.parseBody(c);
              messages.add(
                  new CommitValidationMessage(
                      "Implicit Merge of "
                          + abbreviateName(c, rw.getObjectReader())
                          + " "
                          + c.getShortMessage(),
                      ValidationMessage.Type.ERROR));
            }
            reject(magicBranch.cmd, "implicit merges detected");
          }
        }
      }
    }
  }

  // Mark all branch tips as uninteresting in the given revwalk,
  // so we get only the new commits when walking rw.
  private void markHeadsAsUninteresting(RevWalk rw, @Nullable String forRef) throws IOException {
    try (TraceTimer traceTimer =
        newTimer("markHeadsAsUninteresting", Metadata.builder().branchName(forRef))) {
      int i = 0;
      for (Ref ref :
          Iterables.concat(
              receivePackRefCache.byPrefix(R_HEADS),
              Collections.singletonList(receivePackRefCache.exactRef(forRef)))) {
        if (ref != null && ref.getObjectId() != null) {
          try {
            rw.markUninteresting(rw.parseCommit(ref.getObjectId()));
            i++;
          } catch (IOException e) {
            logger.atWarning().withCause(e).log(
                "Invalid ref %s in %s", ref.getName(), project.getName());
          }
        }
      }
      logger.atFine().log("Marked %d heads as uninteresting", i);
    }
  }

  private static boolean isValidChangeId(String idStr) {
    return idStr.matches("^I[0-9a-fA-F]{40}$") && !idStr.matches("^I00*$");
  }

  private static class ChangeLookup {
    final RevCommit commit;

    @Nullable final Change.Key changeKey;
    final List<ChangeData> destChanges;

    ChangeLookup(RevCommit c, @Nullable Change.Key key, final List<ChangeData> destChanges) {
      this.commit = c;
      this.changeKey = key;
      this.destChanges = destChanges;
    }
  }

  private ChangeLookup lookupByChangeKey(RevCommit c, Change.Key key) {
    try (TraceTimer traceTimer = newTimer("lookupByChangeKey")) {
      List<ChangeData> byBranchKeyExactMatch =
          queryProvider.get().byBranchKey(magicBranch.dest, key).stream()
              .filter(cd -> cd.change().getKey().equals(key))
              .collect(toList());
      return new ChangeLookup(c, key, byBranchKeyExactMatch);
    }
  }

  private ChangeLookup lookupByCommit(RevCommit c) {
    try (TraceTimer traceTimer = newTimer("lookupByCommit")) {
      return new ChangeLookup(
          c, null, queryProvider.get().byBranchCommit(magicBranch.dest, c.getName()));
    }
  }

  /** Represents a commit for which a Change should be created. */
  private class CreateRequest {
    final RevCommit commit;
    final Task progress;
    final String refName;

    Change.Id changeId;
    ReceiveCommand cmd;
    ChangeInserter ins;
    List<String> groups = ImmutableList.of();

    Change change;

    CreateRequest(RevCommit commit, String refName, Task progress) {
      this.commit = commit;
      this.refName = refName;
      this.progress = progress;
    }

    private void setChangeId(int id) {
      try (TraceTimer traceTimer = newTimer(CreateRequest.class, "setChangeId")) {
        changeId = Change.id(id);
        ins =
            changeInserterFactory
                .create(changeId, commit, refName)
                .setTopic(magicBranch.topic)
                .setPrivate(setChangeAsPrivate)
                .setWorkInProgress(magicBranch.shouldSetWorkInProgressOnNewChanges())
                // Changes already validated in validateNewCommits.
                .setValidate(false);

        if (magicBranch.merged) {
          ins.setStatus(Change.Status.MERGED);
        }
        cmd = new ReceiveCommand(ObjectId.zeroId(), commit, ins.getPatchSetId().toRefName());
        if (receivePack.getPushCertificate() != null) {
          ins.setPushCertificate(receivePack.getPushCertificate().toTextWithSignature());
        }
      }
    }

    private void addOps(BatchUpdate bu) throws RestApiException {
      try (TraceTimer traceTimer = newTimer(CreateRequest.class, "addOps")) {
        checkState(changeId != null, "must call setChangeId before addOps");
        try {
          RevWalk rw = receivePack.getRevWalk();
          rw.parseBody(commit);
          final PatchSet.Id psId = ins.setGroups(groups).getPatchSetId();
          Account.Id me = user.getAccountId();
          List<FooterLine> footerLines = commit.getFooterLines();
          requireNonNull(magicBranch);

          // TODO(dborowitz): Support reviewers by email from footers? Maybe not: kernel developers
          // with AOSP accounts already complain about these notifications, and that would make it
          // worse. Might be better to get rid of the feature entirely:
          // https://groups.google.com/d/topic/repo-discuss/tIFxY7L4DXk/discussion
          MailRecipients fromFooters = getRecipientsFromFooters(accountResolver, footerLines);
          fromFooters.remove(me);

          Map<String, Short> approvals = magicBranch.labels;
          StringBuilder msg =
              new StringBuilder(
                  ApprovalsUtil.renderMessageWithApprovals(
                      psId.get(), approvals, Collections.emptyMap()));
          msg.append('.');
          if (!Strings.isNullOrEmpty(magicBranch.message)) {
            msg.append("\n").append(magicBranch.message);
          }

          bu.setNotify(magicBranch.getNotifyForNewChange());
          bu.insertChange(
              ins.setReviewersAndCcsAsStrings(
                      magicBranch.getCombinedReviewers(fromFooters),
                      magicBranch.getCombinedCcs(fromFooters))
                  .setApprovals(approvals)
                  .setMessage(msg.toString())
                  .setRequestScopePropagator(requestScopePropagator)
                  .setSendMail(true)
                  .setPatchSetDescription(magicBranch.message));
          if (!magicBranch.hashtags.isEmpty()) {
            // Any change owner is allowed to add hashtags when creating a change.
            bu.addOp(
                changeId,
                hashtagsFactory
                    .create(new HashtagsInput(magicBranch.hashtags))
                    .setFireEvent(false));
          }
          if (!Strings.isNullOrEmpty(magicBranch.topic)) {
            bu.addOp(changeId, setTopicFactory.create(magicBranch.topic));
          }
          if (magicBranch.ignoreAttentionSet) {
            bu.addOp(changeId, new AttentionSetUnchangedOp());
          }
          bu.addOp(
              changeId,
              new BatchUpdateOp() {
                @Override
                public boolean updateChange(ChangeContext ctx) {
                  CreateRequest.this.change = ctx.getChange();
                  return false;
                }
              });
          bu.addOp(changeId, new ChangeProgressOp(progress));
        } catch (Exception e) {
          throw asRestApiException(e);
        }
      }
    }
  }

  private void submit(Collection<CreateRequest> create, Collection<ReplaceRequest> replace)
      throws RestApiException, UpdateException, IOException, ConfigInvalidException,
          PermissionBackendException {
    try (TraceTimer traceTimer = newTimer("submit")) {
      Map<ObjectId, Change> bySha = Maps.newHashMapWithExpectedSize(create.size() + replace.size());
      for (CreateRequest r : create) {
        requireNonNull(
            r.change,
            () -> String.format("cannot submit new change %s; op may not have run", r.changeId));
        bySha.put(r.commit, r.change);
      }
      for (ReplaceRequest r : replace) {
        bySha.put(r.newCommitId, r.notes.getChange());
      }
      Change tipChange = bySha.get(magicBranch.cmd.getNewId());
      requireNonNull(
          tipChange,
          () ->
              String.format(
                  "tip of push does not correspond to a change; found these changes: %s", bySha));
      logger.atFine().log(
          "Processing submit with tip change %s (%s)",
          tipChange.getId(), magicBranch.cmd.getNewId());
      try (MergeOp op = mergeOpProvider.get()) {
        SubmitInput submitInput = new SubmitInput();
        submitInput.notify = magicBranch.notifyHandling;
        submitInput.notifyDetails = new HashMap<>();
        submitInput.notifyDetails.put(
            RecipientType.TO,
            new NotifyInfo(magicBranch.notifyTo.stream().map(Object::toString).collect(toList())));
        submitInput.notifyDetails.put(
            RecipientType.CC,
            new NotifyInfo(magicBranch.notifyCc.stream().map(Object::toString).collect(toList())));
        submitInput.notifyDetails.put(
            RecipientType.BCC,
            new NotifyInfo(magicBranch.notifyBcc.stream().map(Object::toString).collect(toList())));
        op.merge(tipChange, user, false, submitInput, false);
      }
    }
  }

  private void preparePatchSetsForReplace(ImmutableList<CreateRequest> newChanges) {
    try (TraceTimer traceTimer =
        newTimer(
            "preparePatchSetsForReplace", Metadata.builder().resourceCount(newChanges.size()))) {
      try {
        readChangesForReplace();
        for (ReplaceRequest req : replaceByChange.values()) {
          if (req.inputCommand.getResult() == NOT_ATTEMPTED) {
            req.validateNewPatchSet();
          }
        }
      } catch (IOException | PermissionBackendException e) {
        throw new StorageException(
            "Cannot read repository before replacement for project " + project.getName(), e);
      }
      logger.atFine().log("Read %d changes to replace", replaceByChange.size());

      if (magicBranch != null && magicBranch.cmd.getResult() != NOT_ATTEMPTED) {
        // Cancel creations tied to refs/for/ command.
        for (ReplaceRequest req : replaceByChange.values()) {
          if (req.inputCommand == magicBranch.cmd && req.cmd != null) {
            req.cmd.setResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, "aborted");
          }
        }
        for (CreateRequest req : newChanges) {
          req.cmd.setResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, "aborted");
        }
      }
    }
  }

  private void readChangesForReplace() {
    try (TraceTimer traceTimer = newTimer("readChangesForReplace")) {
      replaceByChange.values().stream()
          .map(r -> r.ontoChange)
          .map(id -> notesFactory.create(repo, project.getNameKey(), id))
          .forEach(notes -> replaceByChange.get(notes.getChangeId()).notes = notes);
    }
  }

  /** Represents a commit that should be stored in a new patchset of an existing change. */
  private class ReplaceRequest {
    final Change.Id ontoChange;
    final ObjectId newCommitId;
    final ReceiveCommand inputCommand;
    final boolean checkMergedInto;
    RevCommit revCommit;
    ChangeNotes notes;
    BiMap<RevCommit, PatchSet.Id> revisions;
    PatchSet.Id psId;
    ReceiveCommand prev;
    ReceiveCommand cmd;
    PatchSetInfo info;
    PatchSet.Id priorPatchSet;
    List<String> groups = ImmutableList.of();
    ReplaceOp replaceOp;

    ReplaceRequest(
        Change.Id toChange, RevCommit newCommit, ReceiveCommand cmd, boolean checkMergedInto)
        throws IOException {
      this.ontoChange = toChange;
      this.newCommitId = newCommit.copy();
      this.inputCommand = requireNonNull(cmd);
      this.checkMergedInto = checkMergedInto;

      try {
        revCommit = receivePack.getRevWalk().parseCommit(newCommitId);
      } catch (IOException e) {
        revCommit = null;
      }
      revisions = HashBiMap.create();
      for (Ref ref : receivePackRefCache.byPrefix(RefNames.changeRefPrefix(toChange))) {
        try {
          PatchSet.Id psId = PatchSet.Id.fromRef(ref.getName());
          if (psId != null) {
            revisions.forcePut(receivePack.getRevWalk().parseCommit(ref.getObjectId()), psId);
          }
        } catch (IOException err) {
          logger.atWarning().withCause(err).log(
              "Project %s contains invalid change ref %s", project.getName(), ref.getName());
        }
      }
    }

    /**
     * Validate the new patch set commit for this change.
     *
     * <p><strong>Side effects:</strong>
     *
     * <ul>
     *   <li>May add error or warning messages to the progress monitor
     *   <li>Will reject {@code cmd} prior to returning false
     *   <li>May reset {@code receivePack.getRevWalk()}; do not call in the middle of a walk.
     * </ul>
     *
     * @return whether the new commit is valid
     */
    boolean validateNewPatchSet() throws IOException, PermissionBackendException {
      try (TraceTimer traceTimer = newTimer("validateNewPatchSet")) {
        if (!validateNewPatchSetNoteDb()) {
          return false;
        }
        sameTreeWarning();

        if (magicBranch != null) {
          validateMagicBranchWipStatusChange();
          if (inputCommand.getResult() != NOT_ATTEMPTED) {
            return false;
          }

          if (magicBranch.edit) {
            return newEdit();
          }
        }

        newPatchSet();
        return true;
      }
    }

    boolean validateNewPatchSetForAutoClose() throws IOException, PermissionBackendException {
      if (!validateNewPatchSetNoteDb()) {
        return false;
      }

      newPatchSet();
      return true;
    }

    /** Validates the new PS against permissions and notedb status. */
    private boolean validateNewPatchSetNoteDb() throws IOException, PermissionBackendException {
      try (TraceTimer traceTimer = newTimer("validateNewPatchSetNoteDb")) {
        if (notes == null) {
          reject(inputCommand, "change " + ontoChange + " not found");
          return false;
        }

        Change change = notes.getChange();
        priorPatchSet = change.currentPatchSetId();
        if (!revisions.containsValue(priorPatchSet)) {
          metrics.psRevisionMissing.increment();
          logger.atWarning().log(
              "Change %d is missing revision for patch set %s"
                  + " (it has revisions for these patch sets: %s)",
              change.getChangeId(),
              priorPatchSet.getId(),
              Iterables.toString(
                  revisions.values().stream()
                      .limit(100) // Enough for "normal" changes.
                      .map(PatchSet.Id::getId)
                      .collect(Collectors.toList())));
          reject(inputCommand, "change " + ontoChange + " missing revisions");
          return false;
        }

        RevCommit newCommit = receivePack.getRevWalk().parseCommit(newCommitId);

        // Not allowed to create a new patch set if the current patch set is locked.
        if (psUtil.isPatchSetLocked(notes)) {
          reject(inputCommand, "cannot add patch set to " + ontoChange + ".");
          return false;
        }

        if (!permissions.change(notes).test(ChangePermission.ADD_PATCH_SET)) {
          reject(inputCommand, "cannot add patch set to " + ontoChange + ".");
          return false;
        }

        if (change.isClosed()) {
          reject(inputCommand, "change " + ontoChange + " closed");
          return false;
        } else if (revisions.containsKey(newCommit)) {
          reject(inputCommand, "commit already exists (in the change)");
          return false;
        }

        List<PatchSet.Id> existingPatchSetsWithSameCommit =
            receivePackRefCache.patchSetIdsFromObjectId(newCommit);
        if (!existingPatchSetsWithSameCommit.isEmpty()) {
          // TODO(hiesel, hanwen): Remove this check entirely when Gerrit requires change IDs
          //  without the option to turn that off.
          reject(
              inputCommand,
              "commit already exists (in the project): "
                  + existingPatchSetsWithSameCommit.get(0).toRefName());
          return false;
        }

        try (TraceTimer traceTimer2 = newTimer("validateNewPatchSetNoteDb#isMergedInto")) {
          for (RevCommit prior : revisions.keySet()) {
            // Don't allow a change to directly depend upon itself. This is a
            // very common error due to users making a new commit rather than
            // amending when trying to address review comments.
            if (receivePack.getRevWalk().isMergedInto(prior, newCommit)) {
              reject(inputCommand, SAME_CHANGE_ID_IN_MULTIPLE_CHANGES);
              return false;
            }
          }
        }

        return true;
      }
    }

    /** Validates whether the WIP change is allowed. Rejects inputCommand if not. */
    private void validateMagicBranchWipStatusChange() throws PermissionBackendException {
      Change change = notes.getChange();
      if ((magicBranch.workInProgress || magicBranch.ready)
          && magicBranch.workInProgress != change.isWorkInProgress()
          && !user.getAccountId().equals(change.getOwner())) {
        if (!permissions.test(ProjectPermission.WRITE_CONFIG)) {
          if (!permissions.change(notes).test(ChangePermission.TOGGLE_WORK_IN_PROGRESS_STATE)) {
            reject(inputCommand, ONLY_USERS_WITH_TOGGLE_WIP_STATE_PERM_CAN_MODIFY_WIP);
          }
        }
      }
    }

    /** prints a warning if the new PS has the same tree as the previous commit. */
    private void sameTreeWarning() throws IOException {
      try (TraceTimer traceTimer = newTimer("sameTreeWarning")) {
        RevWalk rw = receivePack.getRevWalk();
        RevCommit newCommit = rw.parseCommit(newCommitId);
        RevCommit priorCommit = revisions.inverse().get(priorPatchSet);

        if (newCommit.getTree().equals(priorCommit.getTree())) {
          rw.parseBody(newCommit);
          rw.parseBody(priorCommit);
          boolean messageEq =
              Objects.equals(newCommit.getFullMessage(), priorCommit.getFullMessage());
          boolean parentsEq = parentsEqual(newCommit, priorCommit);
          boolean authorEq = authorEqual(newCommit, priorCommit);
          ObjectReader reader = receivePack.getRevWalk().getObjectReader();

          if (messageEq && parentsEq && authorEq) {
            addMessage(
                String.format(
                    "warning: no changes between prior commit %s and new commit %s",
                    abbreviateName(priorCommit, reader), abbreviateName(newCommit, reader)));
          } else {
            StringBuilder msg = new StringBuilder();
            msg.append("warning: ").append(abbreviateName(newCommit, reader));
            msg.append(":");
            msg.append(" no files changed");
            if (!authorEq) {
              msg.append(", author changed");
            }
            if (!messageEq) {
              msg.append(", message updated");
            }
            if (!parentsEq) {
              msg.append(", was rebased");
            }
            addMessage(msg.toString());
          }
        }
      }
    }

    /**
     * Sets cmd and prev to the ReceiveCommands for change edits. Returns false if there was a
     * failure.
     */
    private boolean newEdit() {
      try (TraceTimer traceTimer = newTimer("newEdit")) {
        psId = notes.getChange().currentPatchSetId();
        Optional<ChangeEdit> edit;

        try {
          edit = editUtil.byChange(notes, user);
        } catch (AuthException | IOException e) {
          logger.atSevere().withCause(e).log("Cannot retrieve edit");
          return false;
        }

        if (edit.isPresent()) {
          if (edit.get().getBasePatchSet().id().equals(psId)) {
            // replace edit
            cmd =
                new ReceiveCommand(
                    edit.get().getEditCommit(), newCommitId, edit.get().getRefName());
          } else {
            // delete old edit ref on rebase
            prev =
                new ReceiveCommand(
                    edit.get().getEditCommit(), ObjectId.zeroId(), edit.get().getRefName());
            createEditCommand();
          }
        } else {
          createEditCommand();
        }

        return true;
      }
    }

    /** Creates a ReceiveCommand for a new edit. */
    private void createEditCommand() {
      cmd =
          new ReceiveCommand(
              ObjectId.zeroId(),
              newCommitId,
              RefNames.refsEdit(user.getAccountId(), notes.getChangeId(), psId));
    }

    /** Updates 'this' to add a new patchset. */
    private void newPatchSet() throws IOException {
      try (TraceTimer traceTimer = newTimer("newPatchSet")) {
        RevCommit newCommit = receivePack.getRevWalk().parseCommit(newCommitId);
        psId = nextPatchSetId(notes.getChange().currentPatchSetId());
        info = patchSetInfoFactory.get(receivePack.getRevWalk(), newCommit, psId);
        cmd = new ReceiveCommand(ObjectId.zeroId(), newCommitId, psId.toRefName());
      }
    }

    private PatchSet.Id nextPatchSetId(PatchSet.Id psId) throws IOException {
      PatchSet.Id next = ChangeUtil.nextPatchSetId(psId);
      while (receivePackRefCache.exactRef(next.toRefName()) != null) {
        next = ChangeUtil.nextPatchSetId(next);
      }
      return next;
    }

    void addOps(BatchUpdate bu, @Nullable Task progress) throws IOException {
      try (TraceTimer traceTimer = newTimer("addOps")) {
        if (magicBranch != null && magicBranch.edit) {
          bu.addOp(notes.getChangeId(), new ReindexOnlyOp());
          if (prev != null) {
            bu.addRepoOnlyOp(new UpdateOneRefOp(prev));
          }
          bu.addRepoOnlyOp(new UpdateOneRefOp(cmd));
          return;
        }
        RevWalk rw = receivePack.getRevWalk();
        // TODO(dborowitz): Move to ReplaceOp#updateRepo.
        RevCommit newCommit = rw.parseCommit(newCommitId);
        rw.parseBody(newCommit);

        RevCommit priorCommit = revisions.inverse().get(priorPatchSet);
        replaceOp =
            replaceOpFactory.create(
                projectState,
                notes.getChange(),
                checkMergedInto,
                checkMergedInto ? inputCommand.getNewId().name() : null,
                priorPatchSet,
                priorCommit,
                psId,
                newCommit,
                info,
                groups,
                magicBranch,
                receivePack.getPushCertificate(),
                requestScopePropagator);
        bu.addOp(notes.getChangeId(), replaceOp);
        if (progress != null) {
          bu.addOp(notes.getChangeId(), new ChangeProgressOp(progress));
        }
        bu.addRepoOnlyOp(
            new RepoOnlyOp() {
              @Override
              public void updateRepo(RepoContext ctx) throws Exception {
                // Create auto merge ref if the new patch set is a merge commit. This is only
                // required for new patch sets on existing changes as these do not go through
                // PatchSetInserter. New changes pushed via git go through ChangeInserter and have
                // their auto merge commits created there.
                Optional<ReceiveCommand> autoMerge =
                    autoMerger.createAutoMergeCommitIfNecessary(
                        ctx.getRepoView(),
                        ctx.getRevWalk(),
                        ctx.getInserter(),
                        ctx.getRevWalk().parseCommit(newCommitId));
                if (autoMerge.isPresent()) {
                  ctx.addRefUpdate(autoMerge.get());
                }
              }
            });
      }
    }

    @Nullable
    String getRejectMessage() {
      return replaceOp != null ? replaceOp.getRejectMessage() : null;
    }

    Optional<String> getOutdatedApprovalsMessage() {
      return replaceOp != null ? replaceOp.getOutdatedApprovalsMessage() : Optional.empty();
    }
  }

  private class UpdateOneRefOp implements RepoOnlyOp {
    final ReceiveCommand cmd;

    private UpdateOneRefOp(ReceiveCommand cmd) {
      this.cmd = requireNonNull(cmd);
    }

    @Override
    public void updateRepo(RepoContext ctx) throws IOException {
      ctx.addRefUpdate(cmd);
    }

    @Override
    public void postUpdate(PostUpdateContext ctx) {
      String refName = cmd.getRefName();
      if (cmd.getType() == ReceiveCommand.Type.UPDATE) { // aka fast-forward
        logger.atFine().log("Updating tag cache on fast-forward of %s", cmd.getRefName());
        tagCache.updateFastForward(project.getNameKey(), refName, cmd.getOldId(), cmd.getNewId());
      }
      if (isConfig(cmd)) {
        logger.atFine().log("Reloading project in cache");
        projectCache.evictAndReindex(project);
        ProjectState ps =
            projectCache.get(project.getNameKey()).orElseThrow(illegalState(project.getNameKey()));
        try {
          logger.atFine().log("Updating project description");
          repo.setGitwebDescription(ps.getProject().getDescription());
        } catch (IOException e) {
          throw new StorageException("cannot update description of " + project.getName(), e);
        }
        if (allProjectsName.equals(project.getNameKey())) {
          try {
            createGroupPermissionSyncer.syncIfNeeded();
          } catch (IOException | ConfigInvalidException e) {
            throw new StorageException("cannot update description of " + project.getName(), e);
          }
        }
      }
    }
  }

  private static class ReindexOnlyOp implements BatchUpdateOp {
    @Override
    public boolean updateChange(ChangeContext ctx) {
      // Trigger reindexing even though change isn't actually updated.
      return true;
    }
  }

  private static boolean parentsEqual(RevCommit a, RevCommit b) {
    if (a.getParentCount() != b.getParentCount()) {
      return false;
    }
    for (int i = 0; i < a.getParentCount(); i++) {
      if (!a.getParent(i).equals(b.getParent(i))) {
        return false;
      }
    }
    return true;
  }

  private static boolean authorEqual(RevCommit a, RevCommit b) {
    PersonIdent aAuthor = a.getAuthorIdent();
    PersonIdent bAuthor = b.getAuthorIdent();

    if (aAuthor == null && bAuthor == null) {
      return true;
    } else if (aAuthor == null || bAuthor == null) {
      return false;
    }

    return Objects.equals(aAuthor.getName(), bAuthor.getName())
        && Objects.equals(aAuthor.getEmailAddress(), bAuthor.getEmailAddress());
  }

  // Run RefValidators on the command. If any validator fails, the command status is set to
  // REJECTED, and the return value is 'false'
  private boolean validRefOperation(ReceiveCommand cmd) {
    try (TraceTimer traceTimer = newTimer("validRefOperation")) {
      RefOperationValidators refValidators =
          refValidatorsFactory.create(
              getProject(), user, cmd, ImmutableListMultimap.copyOf(pushOptions));

      try {
        messages.addAll(refValidators.validateForRefOperation());
      } catch (RefOperationValidationException e) {
        messages.addAll(e.getMessages());
        reject(cmd, e.getMessage());
        return false;
      }

      return true;
    }
  }

  /**
   * Validates the commits that a regular push brings in.
   *
   * <p>On validation failure, the command is rejected.
   */
  private void validateRegularPushCommits(BranchNameKey branch, ReceiveCommand cmd)
      throws PermissionBackendException {
    try (TraceTimer traceTimer =
        newTimer("validateRegularPushCommits", Metadata.builder().branchName(branch.branch()))) {
      boolean skipValidation =
          !RefNames.REFS_CONFIG.equals(cmd.getRefName())
              && !(MagicBranch.isMagicBranch(cmd.getRefName())
                  || NEW_PATCHSET_PATTERN.matcher(cmd.getRefName()).matches())
              && pushOptions.containsKey(PUSH_OPTION_SKIP_VALIDATION);
      if (skipValidation) {
        if (projectState.is(BooleanProjectConfig.USE_SIGNED_OFF_BY)) {
          reject(cmd, "requireSignedOffBy prevents option " + PUSH_OPTION_SKIP_VALIDATION);
          return;
        }

        Optional<AuthException> err =
            checkRefPermission(permissions.ref(branch.branch()), RefPermission.SKIP_VALIDATION);
        if (err.isPresent()) {
          rejectProhibited(cmd, err.get());
          return;
        }
        if (!Iterables.isEmpty(rejectCommits)) {
          reject(cmd, "reject-commits prevents " + PUSH_OPTION_SKIP_VALIDATION);
        }
      }

      BranchCommitValidator validator = commitValidatorFactory.create(projectState, branch, user);
      RevWalk walk = receivePack.getRevWalk();
      walk.reset();
      walk.sort(RevSort.NONE);
      try {
        RevObject parsedObject = walk.parseAny(cmd.getNewId());
        if (!(parsedObject instanceof RevCommit)) {
          return;
        }
        walk.markStart((RevCommit) parsedObject);
        markHeadsAsUninteresting(walk, cmd.getRefName());
        int limit = receiveConfig.maxBatchCommits;
        int n = 0;
        for (RevCommit c; (c = walk.next()) != null; ) {
          // Even if skipValidation is set, we still get here when at least one plugin
          // commit validator requires to validate all commits. In this case, however,
          // we don't need to check the commit limit.
          if (++n > limit && !skipValidation) {
            logger.atFine().log("Number of new commits exceeds limit of %d", limit);
            reject(
                cmd,
                String.format(
                    "more than %d commits, and %s not set", limit, PUSH_OPTION_SKIP_VALIDATION));
            return;
          }
          if (!receivePackRefCache.patchSetIdsFromObjectId(c).isEmpty()) {
            continue;
          }

          BranchCommitValidator.Result validationResult =
              validator.validateCommit(
                  repo,
                  walk.getObjectReader(),
                  cmd,
                  c,
                  ImmutableListMultimap.copyOf(pushOptions),
                  false,
                  rejectCommits,
                  null,
                  skipValidation);
          messages.addAll(validationResult.messages());
          if (!validationResult.isValid()) {
            break;
          }
        }
        logger.atFine().log("Validated %d new commits", n);
      } catch (IOException err) {
        cmd.setResult(REJECTED_MISSING_OBJECT);
        logger.atSevere().withCause(err).log(
            "Invalid pack upload; one or more objects weren't sent");
      }
    }
  }

  private void autoCloseChanges(ReceiveCommand cmd, Task progress) {
    try (TraceTimer traceTimer = newTimer("autoCloseChanges")) {
      logger.atFine().log("Starting auto-closing of changes");
      String refName = cmd.getRefName();
      Set<Change.Id> ids = new HashSet<>();

      // TODO(dborowitz): Combine this BatchUpdate with the main one in
      // handleRegularCommands
      try {
        retryHelper
            .changeUpdate(
                "autoCloseChanges",
                updateFactory -> {
                  try (BatchUpdate bu =
                          updateFactory.create(projectState.getNameKey(), user, TimeUtil.now());
                      ObjectInserter ins = repo.newObjectInserter();
                      ObjectReader reader = ins.newReader();
                      RevWalk rw = new RevWalk(reader)) {
                    if (ObjectId.zeroId().equals(cmd.getOldId())) {
                      // The user is creating a new branch. The branch can't contain any changes, so
                      // auto-closing doesn't apply. Exiting here early to spare any further,
                      // potentially expensive computation that loop over all commits.
                      return null;
                    }

                    bu.setRepository(repo, rw, ins);
                    // TODO(dborowitz): Teach BatchUpdate to ignore missing changes.

                    RevCommit newTip = rw.parseCommit(cmd.getNewId());
                    BranchNameKey branch = BranchNameKey.create(project.getNameKey(), refName);

                    rw.reset();
                    rw.sort(RevSort.REVERSE);
                    rw.markStart(newTip);
                    rw.markUninteresting(rw.parseCommit(cmd.getOldId()));

                    Map<Change.Key, ChangeData> changeDataByKey = null;
                    List<ReplaceRequest> replaceAndClose = new ArrayList<>();

                    int existingPatchSets = 0;
                    int newPatchSets = 0;
                    SubmissionId submissionId = null;
                    COMMIT:
                    for (RevCommit c; (c = rw.next()) != null; ) {
                      rw.parseBody(c);

                      // Check if change refs point to this commit. Usually there are 0-1 change
                      // refs pointing to this commit.
                      for (PatchSet.Id psId :
                          receivePackRefCache.patchSetIdsFromObjectId(c.copy())) {
                        Optional<ChangeNotes> notes = getChangeNotes(psId.changeId());
                        if (notes.isPresent() && notes.get().getChange().getDest().equals(branch)) {
                          if (submissionId == null) {
                            submissionId = new SubmissionId(notes.get().getChange());
                          }
                          existingPatchSets++;
                          bu.addOp(
                              notes.get().getChangeId(), setPrivateOpFactory.create(false, null));
                          bu.addOp(
                              psId.changeId(),
                              mergedByPushOpFactory.create(
                                  requestScopePropagator,
                                  psId,
                                  submissionId,
                                  refName,
                                  newTip.getId().getName()));
                          continue COMMIT;
                        }
                      }

                      for (String changeId : changeUtil.getChangeIdsFromFooter(c)) {
                        if (changeDataByKey == null) {
                          changeDataByKey =
                              retryHelper
                                  .changeIndexQuery(
                                      "queryOpenChangesByKeyByBranch",
                                      q -> openChangesByKeyByBranch(q, branch))
                                  .call();
                        }

                        ChangeData onto = changeDataByKey.get(Change.key(changeId.trim()));
                        if (onto != null) {
                          newPatchSets++;
                          // Hold onto this until we're done with the walk, as the call to
                          // req.validate below calls isMergedInto which resets the walk.
                          ChangeNotes ontoNotes = onto.notes();
                          ReplaceRequest req =
                              new ReplaceRequest(ontoNotes.getChangeId(), c, cmd, false);
                          req.notes = ontoNotes;
                          replaceAndClose.add(req);
                          continue COMMIT;
                        }
                      }
                    }

                    for (ReplaceRequest req : replaceAndClose) {
                      Change.Id id = req.notes.getChangeId();
                      if (!req.validateNewPatchSetForAutoClose()) {
                        logger.atFine().log("Not closing %s because validation failed", id);
                        continue;
                      }
                      if (submissionId == null) {
                        submissionId = new SubmissionId(req.notes.getChange());
                      }
                      req.addOps(bu, null);
                      bu.addOp(id, setPrivateOpFactory.create(false, null));
                      bu.addOp(
                          id,
                          mergedByPushOpFactory
                              .create(
                                  requestScopePropagator,
                                  req.psId,
                                  submissionId,
                                  refName,
                                  newTip.getId().getName())
                              .setPatchSetProvider(req.replaceOp::getPatchSet));
                      bu.addOp(id, new ChangeProgressOp(progress));
                      ids.add(id);
                    }

                    logger.atFine().log(
                        "Auto-closing %d changes with existing patch sets and %d with new patch"
                            + " sets",
                        existingPatchSets, newPatchSets);
                    bu.execute();
                  } catch (IOException | StorageException | PermissionBackendException e) {
                    throw new StorageException("Failed to auto-close changes", e);
                  }

                  // If we are here, we didn't throw UpdateException. Record the result.
                  // The ordering is indeterminate due to the HashSet; unfortunately, Change.Id
                  // doesn't
                  // fit into TreeSet.
                  ids.stream()
                      .forEach(
                          id -> result.addChange(ReceiveCommitsResult.ChangeStatus.AUTOCLOSED, id));

                  return null;
                })
            // Use a multiple of the default timeout to account for inner retries that may otherwise
            // eat up the whole timeout so that no time is left to retry this outer action.
            .defaultTimeoutMultiplier(5)
            .call();
      } catch (RestApiException e) {
        logger.atSevere().withCause(e).log("Can't insert patchset");
      } catch (UpdateException e) {
        logger.atSevere().withCause(e).log("Failed to auto-close changes");
      } finally {
        logger.atFine().log("Done auto-closing changes");
      }
    }
  }

  private Optional<ChangeNotes> getChangeNotes(Change.Id changeId) {
    try {
      return Optional.of(notesFactory.createChecked(project.getNameKey(), changeId));
    } catch (NoSuchChangeException e) {
      return Optional.empty();
    }
  }

  private Map<Change.Key, ChangeData> openChangesByKeyByBranch(
      InternalChangeQuery internalChangeQuery, BranchNameKey branch) {
    try (TraceTimer traceTimer =
        newTimer("openChangesByKeyByBranch", Metadata.builder().branchName(branch.branch()))) {
      Map<Change.Key, ChangeData> r = new HashMap<>();
      for (ChangeData cd : internalChangeQuery.byBranchOpen(branch)) {
        try {
          // ChangeData is not materialised into a ChangeNotes for avoiding
          // to load a potentially large number of changes meta-data into memory
          // which would cause unnecessary disk I/O, CPU and heap utilisation.
          r.put(cd.change().getKey(), cd);
        } catch (NoSuchChangeException e) {
          // Ignore deleted change
        }
      }
      return r;
    }
  }

  private TraceTimer newTimer(String name) {
    return newTimer(getClass(), name);
  }

  private TraceTimer newTimer(Class<?> clazz, String name) {
    return newTimer(clazz, name, Metadata.builder());
  }

  private TraceTimer newTimer(String name, Metadata.Builder metadataBuilder) {
    return newTimer(getClass(), name, metadataBuilder);
  }

  private TraceTimer newTimer(Class<?> clazz, String name, Metadata.Builder metadataBuilder) {
    metadataBuilder.projectName(project.getName());
    return TraceContext.newTimer(clazz.getSimpleName() + "#" + name, metadataBuilder.build());
  }

  private static void reject(ReceiveCommand cmd, String why) {
    logger.atFine().log("Rejecting command '%s': %s", cmd, why);
    cmd.setResult(REJECTED_OTHER_REASON, why);
  }

  private static void rejectRemaining(Collection<ReceiveCommand> commands, String why) {
    rejectRemaining(commands.stream(), why);
  }

  private static void rejectRemaining(Stream<ReceiveCommand> commands, String why) {
    commands.filter(cmd -> cmd.getResult() == NOT_ATTEMPTED).forEach(cmd -> reject(cmd, why));
  }

  private static boolean isHead(ReceiveCommand cmd) {
    return cmd.getRefName().startsWith(Constants.R_HEADS);
  }

  private static boolean isConfig(ReceiveCommand cmd) {
    return cmd.getRefName().equals(RefNames.REFS_CONFIG);
  }

  private static String commandToString(ReceiveCommand cmd) {
    StringBuilder b = new StringBuilder();
    b.append(cmd);
    b.append("  (").append(cmd.getResult());
    if (cmd.getMessage() != null) {
      b.append(": ").append(cmd.getMessage());
    }
    b.append(")\n");
    return b.toString();
  }
}
