// 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;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import com.google.auto.value.AutoValue;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.common.data.SubmitTypeRecord;
import com.google.gerrit.extensions.api.changes.SubmitInput;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.InternalUser;
import com.google.gerrit.server.git.BatchUpdate.ChangeContext;
import com.google.gerrit.server.git.MergeOpRepoManager.OpenBranch;
import com.google.gerrit.server.git.MergeOpRepoManager.OpenRepo;
import com.google.gerrit.server.git.strategy.SubmitStrategy;
import com.google.gerrit.server.git.strategy.SubmitStrategyFactory;
import com.google.gerrit.server.git.strategy.SubmitStrategyListener;
import com.google.gerrit.server.git.validators.MergeValidationException;
import com.google.gerrit.server.git.validators.MergeValidators;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.SubmitRuleEvaluator;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.util.RequestId;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;

import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Merges changes in submission order into a single branch.
 * <p>
 * Branches are reduced to the minimum number of heads needed to merge
 * everything. This allows commits to be entered into the queue in any order
 * (such as ancestors before descendants) and only the most recent commit on any
 * line of development will be merged. All unmerged commits along a line of
 * development must be in the submission queue in order to merge the tip of that
 * line.
 * <p>
 * Conflicts are handled by discarding the entire line of development and
 * marking it as conflicting, even if an earlier commit along that same line can
 * be merged cleanly.
 */
public class MergeOp implements AutoCloseable {
  private static final Logger log = LoggerFactory.getLogger(MergeOp.class);

  public static class CommitStatus {
    private final ImmutableMap<Change.Id, ChangeData> changes;
    private final ImmutableSetMultimap<Branch.NameKey, Change.Id> byBranch;
    private final Map<Change.Id, CodeReviewCommit> commits;
    private final Multimap<Change.Id, String> problems;

    private CommitStatus(ChangeSet cs) throws OrmException {
      checkArgument(!cs.furtherHiddenChanges(),
          "CommitStatus must not be called with hidden changes");
      changes = cs.changesById();
      ImmutableSetMultimap.Builder<Branch.NameKey, Change.Id> bb =
          ImmutableSetMultimap.builder();
      for (ChangeData cd : cs.changes()) {
        bb.put(cd.change().getDest(), cd.getId());
      }
      byBranch = bb.build();
      commits = new HashMap<>();
      problems = MultimapBuilder.treeKeys(
          Ordering.natural().onResultOf(new Function<Change.Id, Integer>() {
            @Override
            public Integer apply(Change.Id in) {
              return in.get();
            }
          })).arrayListValues(1).build();
    }

    public ImmutableSet<Change.Id> getChangeIds() {
      return changes.keySet();
    }

    public ImmutableSet<Change.Id> getChangeIds(Branch.NameKey branch) {
      return byBranch.get(branch);
    }

    public CodeReviewCommit get(Change.Id changeId) {
      return commits.get(changeId);
    }

    public void put(CodeReviewCommit c) {
      commits.put(c.change().getId(), c);
    }

    public void problem(Change.Id id, String problem) {
      problems.put(id, problem);
    }

    public void logProblem(Change.Id id, Throwable t) {
      String msg = "Error reading change";
      log.error(msg + " " + id, t);
      problems.put(id, msg);
    }

    public void logProblem(Change.Id id, String msg) {
      log.error(msg + " " + id);
      problems.put(id, msg);
    }

    public boolean isOk() {
      return problems.isEmpty();
    }

    public ImmutableMultimap<Change.Id, String> getProblems() {
      return ImmutableMultimap.copyOf(problems);
    }

    public List<SubmitRecord> getSubmitRecords(Change.Id id) {
      // Use the cached submit records from the original ChangeData in the input
      // ChangeSet, which were checked earlier in the integrate process. Even in
      // the case of a race where the submit records may have changed, it makes
      // more sense to store the original results of the submit rule evaluator
      // than to fail at this point.
      //
      // However, do NOT expose that ChangeData directly, as it is way out of
      // date by this point.
      ChangeData cd = checkNotNull(changes.get(id), "ChangeData for %s", id);
      return checkNotNull(cd.getSubmitRecords(),
          "getSubmitRecord only valid after submit rules are evalutated");
    }

    public void maybeFailVerbose() throws ResourceConflictException {
      if (isOk()) {
        return;
      }
      String msg = "Failed to submit " + changes.size() + " change"
          + (changes.size() > 1 ? "s" : "")
          + " due to the following problems:\n";
      List<String> ps = new ArrayList<>(problems.keySet().size());
      for (Change.Id id : problems.keySet()) {
        ps.add("Change " + id + ": " + Joiner.on("; ").join(problems.get(id)));
      }
      throw new ResourceConflictException(msg + Joiner.on('\n').join(ps));
    }

    public void maybeFail(String msgPrefix) throws ResourceConflictException {
      if (isOk()) {
        return;
      }
      StringBuilder msg = new StringBuilder(msgPrefix).append(" of change");
      Set<Change.Id> ids = problems.keySet();
      if (ids.size() == 1) {
        msg.append(" ").append(ids.iterator().next());
      } else {
        msg.append("s ").append(Joiner.on(", ").join(ids));
      }
      throw new ResourceConflictException(msg.toString());
    }
  }

  private final ChangeMessagesUtil cmUtil;
  private final BatchUpdate.Factory batchUpdateFactory;
  private final InternalUser.Factory internalUserFactory;
  private final MergeSuperSet mergeSuperSet;
  private final MergeValidators.Factory mergeValidatorsFactory;
  private final InternalChangeQuery internalChangeQuery;
  private final SubmitStrategyFactory submitStrategyFactory;
  private final SubmoduleOp.Factory subOpFactory;
  private final MergeOpRepoManager orm;

  private Timestamp ts;
  private RequestId submissionId;
  private IdentifiedUser caller;

  private CommitStatus commits;
  private ReviewDb db;
  private SubmitInput submitInput;

  @Inject
  MergeOp(ChangeMessagesUtil cmUtil,
      BatchUpdate.Factory batchUpdateFactory,
      InternalUser.Factory internalUserFactory,
      MergeSuperSet mergeSuperSet,
      MergeValidators.Factory mergeValidatorsFactory,
      InternalChangeQuery internalChangeQuery,
      SubmitStrategyFactory submitStrategyFactory,
      SubmoduleOp.Factory subOpFactory,
      MergeOpRepoManager orm) {
    this.cmUtil = cmUtil;
    this.batchUpdateFactory = batchUpdateFactory;
    this.internalUserFactory = internalUserFactory;
    this.mergeSuperSet = mergeSuperSet;
    this.mergeValidatorsFactory = mergeValidatorsFactory;
    this.internalChangeQuery = internalChangeQuery;
    this.submitStrategyFactory = submitStrategyFactory;
    this.subOpFactory = subOpFactory;
    this.orm = orm;
  }

  @Override
  public void close() {
    orm.close();
  }

  private static Optional<SubmitRecord> findOkRecord(
      Collection<SubmitRecord> in) {
    if (in == null) {
      return Optional.absent();
    }
    return Iterables.tryFind(in, new Predicate<SubmitRecord>() {
      @Override
      public boolean apply(SubmitRecord input) {
        return input.status == SubmitRecord.Status.OK;
      }
    });
  }

  public static void checkSubmitRule(ChangeData cd)
      throws ResourceConflictException, OrmException {
    PatchSet patchSet = cd.currentPatchSet();
    if (patchSet == null) {
      throw new ResourceConflictException(
          "missing current patch set for change " + cd.getId());
    }
    List<SubmitRecord> results = getSubmitRecords(cd);
    if (findOkRecord(results).isPresent()) {
      // Rules supplied a valid solution.
      return;
    } else if (results.isEmpty()) {
      throw new IllegalStateException(String.format(
          "SubmitRuleEvaluator.evaluate for change %s " +
          "returned empty list for %s in %s",
          cd.getId(),
          patchSet.getId(),
          cd.change().getProject().get()));
    }

    for (SubmitRecord record : results) {
      switch (record.status) {
        case CLOSED:
          throw new ResourceConflictException("change is closed");

        case RULE_ERROR:
          throw new ResourceConflictException(
              "submit rule error: " + record.errorMessage);

        case NOT_READY:
          throw new ResourceConflictException(
              describeLabels(cd, record.labels));

        case FORCED:
        case OK:
        default:
          throw new IllegalStateException(String.format(
              "Unexpected SubmitRecord status %s for %s in %s",
              record.status,
              patchSet.getId().getId(),
              cd.change().getProject().get()));
      }
    }
    throw new IllegalStateException();
  }

  private static List<SubmitRecord> getSubmitRecords(ChangeData cd)
      throws OrmException {
    List<SubmitRecord> results = cd.getSubmitRecords();
    if (results == null) {
      results = new SubmitRuleEvaluator(cd).evaluate();
      cd.setSubmitRecords(results);
    }
    return results;
  }

  private static String describeLabels(ChangeData cd,
      List<SubmitRecord.Label> labels) throws OrmException {
    List<String> labelResults = new ArrayList<>();
    for (SubmitRecord.Label lbl : labels) {
      switch (lbl.status) {
        case OK:
        case MAY:
          break;

        case REJECT:
          labelResults.add("blocked by " + lbl.label);
          break;

        case NEED:
          labelResults.add("needs " + lbl.label);
          break;

        case IMPOSSIBLE:
          labelResults.add(
              "needs " + lbl.label + " (check project access)");
          break;

        default:
          throw new IllegalStateException(String.format(
              "Unsupported SubmitRecord.Label %s for %s in %s",
              lbl,
              cd.change().currentPatchSetId(),
              cd.change().getProject()));
      }
    }
    return Joiner.on("; ").join(labelResults);
  }

  private void checkSubmitRulesAndState(ChangeSet cs)
      throws ResourceConflictException {
    checkArgument(!cs.furtherHiddenChanges(),
        "checkSubmitRulesAndState called for topic with hidden change");
    for (ChangeData cd : cs.changes()) {
      try {
        if (cd.change().getStatus() != Change.Status.NEW) {
          commits.problem(cd.getId(), "Change " + cd.getId() + " is "
              + cd.change().getStatus().toString().toLowerCase());
        } else {
          checkSubmitRule(cd);
        }
      } catch (ResourceConflictException e) {
        commits.problem(cd.getId(), e.getMessage());
      } catch (OrmException e) {
        String msg = "Error checking submit rules for change";
        log.warn(msg + " " + cd.getId(), e);
        commits.problem(cd.getId(), msg);
      }
    }
    commits.maybeFailVerbose();
  }

  private void bypassSubmitRules(ChangeSet cs) {
    checkArgument(!cs.furtherHiddenChanges(),
        "cannot bypass submit rules for topic with hidden change");
    for (ChangeData cd : cs.changes()) {
      List<SubmitRecord> records;
      try {
        records = new ArrayList<>(getSubmitRecords(cd));
      } catch (OrmException e) {
        log.warn("Error checking submit rules for change " + cd.getId(), e);
        records = new ArrayList<>(1);
      }
      SubmitRecord forced = new SubmitRecord();
      forced.status = SubmitRecord.Status.FORCED;
      records.add(forced);
      cd.setSubmitRecords(records);
    }
  }

  public void merge(ReviewDb db, Change change, IdentifiedUser caller,
      boolean checkSubmitRules, SubmitInput submitInput)
      throws OrmException, RestApiException {
    this.submitInput = submitInput;
    this.caller = caller;
    this.ts = TimeUtil.nowTs();
    submissionId = RequestId.forChange(change);
    this.db = db;
    orm.setContext(db, ts, caller, submissionId);

    logDebug("Beginning integration of {}", change);
    try {
      ChangeSet cs = mergeSuperSet.completeChangeSet(db, change, caller);
      checkState(cs.ids().contains(change.getId()),
          "change %s missing from %s", change.getId(), cs);
      if (cs.furtherHiddenChanges()) {
        throw new AuthException("A change to be submitted with "
            + change.getId() + " is not visible");
      }
      this.commits = new CommitStatus(cs);
      MergeSuperSet.reloadChanges(cs);
      logDebug("Calculated to merge {}", cs);
      if (checkSubmitRules) {
        logDebug("Checking submit rules and state");
        checkSubmitRulesAndState(cs);
      } else {
        logDebug("Bypassing submit rules");
        bypassSubmitRules(cs);
      }
      try {
        integrateIntoHistory(cs);
      } catch (IntegrationException e) {
        logError("Error from integrateIntoHistory", e);
        throw new ResourceConflictException(e.getMessage(), e);
      }
    } catch (IOException e) {
      // Anything before the merge attempt is an error
      throw new OrmException(e);
    }
  }

  private void integrateIntoHistory(ChangeSet cs)
      throws IntegrationException, RestApiException {
    checkArgument(!cs.furtherHiddenChanges(),
        "cannot integrate hidden changes into history");
    logDebug("Beginning merge attempt on {}", cs);
    Map<Branch.NameKey, BranchBatch> toSubmit = new HashMap<>();
    logDebug("Perform the merges");

    Multimap<Project.NameKey, Branch.NameKey> br;
    Multimap<Branch.NameKey, ChangeData> cbb;
    try {
      br = cs.branchesByProject();
      cbb = cs.changesByBranch();
    } catch (OrmException e) {
      throw new IntegrationException("Error reading changes to submit", e);
    }
    Set<Project.NameKey> projects = br.keySet();
    Set<Branch.NameKey> branches = cbb.keySet();
    openRepos(projects);

    for (Branch.NameKey branch : branches) {
      OpenRepo or = orm.getRepo(branch.getParentKey());
      toSubmit.put(branch, validateChangeList(or, cbb.get(branch)));
    }
    // Done checks that don't involve running submit strategies.
    commits.maybeFailVerbose();
    SubmoduleOp submoduleOp = subOpFactory.create(branches, orm);
    try {
      List<SubmitStrategy> strategies = getSubmitStrategies(toSubmit, submoduleOp);
      Set<Project.NameKey> allProjects = submoduleOp.getProjectsInOrder();
      // in case superproject subscription is disabled, allProjects would be null
      if (allProjects == null) {
        allProjects = projects;
      }
      BatchUpdate.execute(
          orm.batchUpdates(allProjects),
          new SubmitStrategyListener(submitInput, strategies, commits),
          submissionId);
    } catch (UpdateException | SubmoduleException e) {
      // BatchUpdate may have inadvertently wrapped an IntegrationException
      // thrown by some legacy SubmitStrategyOp code that intended the error
      // message to be user-visible. Copy the message from the wrapped
      // exception.
      //
      // If you happen across one of these, the correct fix is to convert the
      // inner IntegrationException to a ResourceConflictException.
      String msg;
      if (e.getCause() instanceof IntegrationException) {
        msg = e.getCause().getMessage();
      } else {
        msg = "Error submitting change" + (cs.size() != 1 ? "s" : "") + ": \n"
            + e.getMessage();
      }
      throw new IntegrationException(msg, e);
    }
  }

  private List<SubmitStrategy> getSubmitStrategies(
      Map<Branch.NameKey, BranchBatch> toSubmit, SubmoduleOp submoduleOp)
      throws IntegrationException {
    List<SubmitStrategy> strategies = new ArrayList<>();
    Set<Branch.NameKey> allBranches = submoduleOp.getBranchesInOrder();
    // in case superproject subscription is disabled, allBranches would be null
    if (allBranches == null) {
      allBranches = toSubmit.keySet();
    }

    for (Branch.NameKey branch : allBranches) {
      OpenRepo or = orm.getRepo(branch.getParentKey());
      if (toSubmit.containsKey(branch)) {
        BranchBatch submitting = toSubmit.get(branch);
        OpenBranch ob = or.getBranch(branch);
        checkNotNull(submitting.submitType(),
            "null submit type for %s; expected to previously fail fast",
            submitting);
        Set<CodeReviewCommit> commitsToSubmit = commits(submitting.changes());
        ob.mergeTip = new MergeTip(ob.oldTip, commitsToSubmit);
        SubmitStrategy strategy = createStrategy(or, ob.mergeTip, branch,
            submitting.submitType(), ob.oldTip, submoduleOp);
        strategies.add(strategy);
        strategy.addOps(or.getUpdate(), commitsToSubmit);
      } else {
        // no open change for this branch
        // add submodule triggered op into BatchUpdate
        submoduleOp.addOp(or.getUpdate(), branch);
      }
    }
    return strategies;
  }

  private Set<CodeReviewCommit> commits(List<ChangeData> cds) {
    LinkedHashSet<CodeReviewCommit> result =
        Sets.newLinkedHashSetWithExpectedSize(cds.size());
    for (ChangeData cd : cds) {
      CodeReviewCommit commit = commits.get(cd.getId());
      checkState(commit != null,
          "commit for %s not found by validateChangeList", cd.getId());
      result.add(commit);
    }
    return result;
  }

  private SubmitStrategy createStrategy(OpenRepo or,
      MergeTip mergeTip, Branch.NameKey destBranch, SubmitType submitType,
      CodeReviewCommit branchTip, SubmoduleOp submoduleOp) throws IntegrationException {
    return submitStrategyFactory.create(submitType, db, or.repo, or.rw, or.ins,
        or.canMergeFlag, getAlreadyAccepted(or, branchTip), destBranch, caller,
        mergeTip, commits, submissionId, submitInput.notify, submoduleOp);
  }

  private Set<RevCommit> getAlreadyAccepted(OpenRepo or,
      CodeReviewCommit branchTip) throws IntegrationException {
    Set<RevCommit> alreadyAccepted = new HashSet<>();

    if (branchTip != null) {
      alreadyAccepted.add(branchTip);
    }

    try {
      for (Ref r : or.repo.getRefDatabase().getRefs(Constants.R_HEADS)
          .values()) {
        try {
          CodeReviewCommit aac = or.rw.parseCommit(r.getObjectId());
          if (!commits.commits.values().contains(aac)) {
            alreadyAccepted.add(aac);
          }
        } catch (IncorrectObjectTypeException iote) {
          // Not a commit? Skip over it.
        }
      }
    } catch (IOException e) {
      throw new IntegrationException(
          "Failed to determine already accepted commits.", e);
    }

    logDebug("Found {} existing heads", alreadyAccepted.size());
    return alreadyAccepted;
  }

  @AutoValue
  abstract static class BranchBatch {
    @Nullable abstract SubmitType submitType();
    abstract List<ChangeData> changes();
  }

  private BranchBatch validateChangeList(OpenRepo or,
      Collection<ChangeData> submitted) throws IntegrationException {
    logDebug("Validating {} changes", submitted.size());
    List<ChangeData> toSubmit = new ArrayList<>(submitted.size());
    Multimap<ObjectId, PatchSet.Id> revisions = getRevisions(or, submitted);

    SubmitType submitType = null;
    ChangeData choseSubmitTypeFrom = null;
    for (ChangeData cd : submitted) {
      Change.Id changeId = cd.getId();
      ChangeControl ctl;
      Change chg;
      try {
        ctl = cd.changeControl();
        chg = cd.change();
      } catch (OrmException e) {
        commits.logProblem(changeId, e);
        continue;
      }

      SubmitType st = getSubmitType(cd);
      if (st == null) {
        commits.logProblem(changeId, "No submit type for change");
        continue;
      }
      if (submitType == null) {
        submitType = st;
        choseSubmitTypeFrom = cd;
      } else if (st != submitType) {
        commits.problem(changeId, String.format(
            "Change has submit type %s, but previously chose submit type %s "
            + "from change %s in the same batch",
            st, submitType, choseSubmitTypeFrom.getId()));
        continue;
      }
      if (chg.currentPatchSetId() == null) {
        String msg = "Missing current patch set on change";
        logError(msg + " " + changeId);
        commits.problem(changeId, msg);
        continue;
      }

      PatchSet ps;
      Branch.NameKey destBranch = chg.getDest();
      try {
        ps = cd.currentPatchSet();
      } catch (OrmException e) {
        commits.logProblem(changeId, e);
        continue;
      }
      if (ps == null || ps.getRevision() == null
          || ps.getRevision().get() == null) {
        commits.logProblem(changeId, "Missing patch set or revision on change");
        continue;
      }

      String idstr = ps.getRevision().get();
      ObjectId id;
      try {
        id = ObjectId.fromString(idstr);
      } catch (IllegalArgumentException e) {
        commits.logProblem(changeId, e);
        continue;
      }

      if (!revisions.containsEntry(id, ps.getId())) {
        // TODO this is actually an error, the branch is gone but we
        // want to merge the issue. We can't safely do that if the
        // tip is not reachable.
        //
        commits.logProblem(changeId, "Revision " + idstr + " of patch set "
            + ps.getPatchSetId() + " does not match " + ps.getId().toRefName()
            + " for change");
        continue;
      }

      CodeReviewCommit commit;
      try {
        commit = or.rw.parseCommit(id);
      } catch (IOException e) {
        commits.logProblem(changeId, e);
        continue;
      }

      // TODO(dborowitz): Consider putting ChangeData in CodeReviewCommit.
      commit.setControl(ctl);
      commit.setPatchsetId(ps.getId());
      commits.put(commit);

      MergeValidators mergeValidators = mergeValidatorsFactory.create();
      try {
        mergeValidators.validatePreMerge(
            or.repo, commit, or.project, destBranch, ps.getId(), caller);
      } catch (MergeValidationException mve) {
        commits.problem(changeId, mve.getMessage());
        continue;
      }
      commit.add(or.canMergeFlag);
      toSubmit.add(cd);
    }
    logDebug("Submitting on this run: {}", toSubmit);
    return new AutoValue_MergeOp_BranchBatch(submitType, toSubmit);
  }

  private Multimap<ObjectId, PatchSet.Id> getRevisions(OpenRepo or,
      Collection<ChangeData> cds) throws IntegrationException {
    try {
      List<String> refNames = new ArrayList<>(cds.size());
      for (ChangeData cd : cds) {
        Change c = cd.change();
        if (c != null) {
          refNames.add(c.currentPatchSetId().toRefName());
        }
      }
      Multimap<ObjectId, PatchSet.Id> revisions =
          HashMultimap.create(cds.size(), 1);
      for (Map.Entry<String, Ref> e : or.repo.getRefDatabase().exactRef(
          refNames.toArray(new String[refNames.size()])).entrySet()) {
        revisions.put(
            e.getValue().getObjectId(), PatchSet.Id.fromRef(e.getKey()));
      }
      return revisions;
    } catch (IOException | OrmException e) {
      throw new IntegrationException("Failed to validate changes", e);
    }
  }

  private SubmitType getSubmitType(ChangeData cd) {
    try {
      SubmitTypeRecord str = cd.submitTypeRecord();
      return str.isOk() ? str.type : null;
    } catch (OrmException e) {
      logError("Failed to get submit type for " + cd.getId(), e);
      return null;
    }
  }

  private void openRepos(Collection<Project.NameKey> projects)
      throws IntegrationException {
    for (Project.NameKey project : projects) {
      try {
        orm.openRepo(project, true);
      } catch (NoSuchProjectException noProject) {
        logWarn("Project " + noProject.project() + " no longer exists, "
            + "abandoning open changes");
        abandonAllOpenChangeForDeletedProject(noProject.project());
      } catch (IOException e) {
        throw new IntegrationException("Error opening project " + project, e);
      }
    }
  }

  private void abandonAllOpenChangeForDeletedProject(
      Project.NameKey destProject) {
    try {
      for (ChangeData cd : internalChangeQuery.byProjectOpen(destProject)) {
        try (BatchUpdate bu = batchUpdateFactory.create(db, destProject,
            internalUserFactory.create(), ts)) {
          bu.setRequestId(submissionId);
          bu.addOp(cd.getId(), new BatchUpdate.Op() {
            @Override
            public boolean updateChange(ChangeContext ctx) throws OrmException {
              Change change = ctx.getChange();
              if (!change.getStatus().isOpen()) {
                return false;
              }

              change.setStatus(Change.Status.ABANDONED);

              ChangeMessage msg = new ChangeMessage(
                  new ChangeMessage.Key(change.getId(),
                      ChangeUtil.messageUUID(ctx.getDb())),
                  null, change.getLastUpdatedOn(), change.currentPatchSetId());
              msg.setMessage("Project was deleted.");
              cmUtil.addChangeMessage(ctx.getDb(),
                  ctx.getUpdate(change.currentPatchSetId()), msg);

              return true;
            }
          });
          try {
            bu.execute();
          } catch (UpdateException | RestApiException e) {
            logWarn("Cannot abandon changes for deleted project " + destProject,
                e);
          }
        }
      }
    } catch (OrmException e) {
      logWarn("Cannot abandon changes for deleted project " + destProject, e);
    }
  }

  private void logDebug(String msg, Object... args) {
    if (log.isDebugEnabled()) {
      log.debug(submissionId + msg, args);
    }
  }

  private void logWarn(String msg, Throwable t) {
    if (log.isWarnEnabled()) {
      log.warn(submissionId + msg, t);
    }
  }

  private void logWarn(String msg) {
    if (log.isWarnEnabled()) {
      log.warn(submissionId + msg);
    }
  }

  private void logError(String msg, Throwable t) {
    if (log.isErrorEnabled()) {
      if (t != null) {
        log.error(submissionId + msg, t);
      } else {
        log.error(submissionId + msg);
      }
    }
  }

  private void logError(String msg) {
    logError(msg, null);
  }
}
