// Copyright (C) 2012 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.restapi.change;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.gerrit.server.project.ProjectCache.noSuchProject;

import com.google.auto.value.AutoValue;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.changes.CherryPickInput;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MergeConflictException;
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.server.ChangeUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.approval.ApprovalsUtil;
import com.google.gerrit.server.change.ChangeInserter;
import com.google.gerrit.server.change.NotifyResolver;
import com.google.gerrit.server.change.PatchSetInserter;
import com.google.gerrit.server.change.ResetCherryPickOp;
import com.google.gerrit.server.change.SetCherryPickOp;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.GroupCollector;
import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.git.MergeUtilFactory;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.notedb.Sequences;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
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.submit.IntegrationConflictException;
import com.google.gerrit.server.submit.MergeIdenticalTreeException;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.util.CommitMessageUtil;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneId;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.InvalidObjectIdException;
import org.eclipse.jgit.errors.MissingObjectException;
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.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.ChangeIdUtil;

@Singleton
public class CherryPickChange {
  @AutoValue
  abstract static class Result {
    static Result create(Change.Id changeId, ImmutableSet<String> filesWithGitConflicts) {
      return new AutoValue_CherryPickChange_Result(changeId, filesWithGitConflicts);
    }

    abstract Change.Id changeId();

    abstract ImmutableSet<String> filesWithGitConflicts();
  }

  private final Sequences seq;
  private final Provider<InternalChangeQuery> queryProvider;
  private final GitRepositoryManager gitManager;
  private final ZoneId serverZoneId;
  private final Provider<IdentifiedUser> user;
  private final ChangeInserter.Factory changeInserterFactory;
  private final PatchSetInserter.Factory patchSetInserterFactory;
  private final SetCherryPickOp.Factory setCherryPickOfFactory;
  private final MergeUtilFactory mergeUtilFactory;
  private final ChangeNotes.Factory changeNotesFactory;
  private final ProjectCache projectCache;
  private final ApprovalsUtil approvalsUtil;
  private final NotifyResolver notifyResolver;
  private final BatchUpdate.Factory batchUpdateFactory;

  @Inject
  CherryPickChange(
      Sequences seq,
      Provider<InternalChangeQuery> queryProvider,
      @GerritPersonIdent PersonIdent myIdent,
      GitRepositoryManager gitManager,
      Provider<IdentifiedUser> user,
      ChangeInserter.Factory changeInserterFactory,
      PatchSetInserter.Factory patchSetInserterFactory,
      SetCherryPickOp.Factory setCherryPickOfFactory,
      MergeUtilFactory mergeUtilFactory,
      ChangeNotes.Factory changeNotesFactory,
      ProjectCache projectCache,
      ApprovalsUtil approvalsUtil,
      NotifyResolver notifyResolver,
      BatchUpdate.Factory batchUpdateFactory) {
    this.seq = seq;
    this.queryProvider = queryProvider;
    this.gitManager = gitManager;
    this.serverZoneId = myIdent.getZoneId();
    this.user = user;
    this.changeInserterFactory = changeInserterFactory;
    this.patchSetInserterFactory = patchSetInserterFactory;
    this.setCherryPickOfFactory = setCherryPickOfFactory;
    this.mergeUtilFactory = mergeUtilFactory;
    this.changeNotesFactory = changeNotesFactory;
    this.projectCache = projectCache;
    this.approvalsUtil = approvalsUtil;
    this.notifyResolver = notifyResolver;
    this.batchUpdateFactory = batchUpdateFactory;
  }

  /**
   * This function is used for cherry picking a change.
   *
   * @param change Change to cherry pick.
   * @param patch The patch of that change.
   * @param input Input object for different configurations of cherry pick.
   * @param dest Destination branch for the cherry pick.
   * @return Result object that describes the cherry pick.
   * @throws IOException Unable to open repository or read from the database.
   * @throws InvalidChangeOperationException Parent or branch don't exist, or two changes with same
   *     key exist in the branch.
   * @throws UpdateException Problem updating the database using batchUpdateFactory.
   * @throws RestApiException Error such as invalid SHA1
   * @throws ConfigInvalidException Can't find account to notify.
   * @throws NoSuchProjectException Can't find project state.
   */
  public Result cherryPick(Change change, PatchSet patch, CherryPickInput input, BranchNameKey dest)
      throws IOException, InvalidChangeOperationException, UpdateException, RestApiException,
          ConfigInvalidException, NoSuchProjectException {
    return cherryPick(
        change,
        change.getProject(),
        patch.commitId(),
        input,
        dest,
        TimeUtil.now(),
        null,
        null,
        null,
        null);
  }

  /**
   * This function is called directly to cherry pick a commit. Also, it is used to cherry pick a
   * change as well as long as sourceChange is not null.
   *
   * @param sourceChange Change to cherry pick. Can be null, and then the function will only cherry
   *     pick a commit.
   * @param project Project name
   * @param sourceCommit Id of the commit to be cherry picked.
   * @param input Input object for different configurations of cherry pick.
   * @param dest Destination branch for the cherry pick.
   * @return Result object that describes the cherry pick.
   * @throws IOException Unable to open repository or read from the database.
   * @throws InvalidChangeOperationException Parent or branch don't exist, or two changes with same
   *     key exist in the branch.
   * @throws UpdateException Problem updating the database using batchUpdateFactory.
   * @throws RestApiException Error such as invalid SHA1
   * @throws ConfigInvalidException Can't find account to notify.
   * @throws NoSuchProjectException Can't find project state.
   */
  public Result cherryPick(
      @Nullable Change sourceChange,
      Project.NameKey project,
      ObjectId sourceCommit,
      CherryPickInput input,
      BranchNameKey dest)
      throws IOException, InvalidChangeOperationException, UpdateException, RestApiException,
          ConfigInvalidException, NoSuchProjectException {
    return cherryPick(
        sourceChange, project, sourceCommit, input, dest, TimeUtil.now(), null, null, null, null);
  }

  /**
   * This function can be called directly to cherry-pick a change (or commit if sourceChange is
   * null) with a few other parameters that are especially useful for cherry-picking a commit that
   * is the revert-of another change.
   *
   * @param sourceChange Change to cherry pick. Can be null, and then the function will only cherry
   *     pick a commit.
   * @param project Project name
   * @param sourceCommit Id of the commit to be cherry picked.
   * @param input Input object for different configurations of cherry pick.
   * @param dest Destination branch for the cherry pick.
   * @param timestamp the current timestamp.
   * @param revertedChange The id of the change that is reverted. This is used for the "revertOf"
   *     field to mark the created cherry pick change as "revertOf" the original change that was
   *     reverted.
   * @param changeIdForNewChange The Change-Id that the new change of the cherry pick will have.
   * @param idForNewChange The ID that the new change of the cherry pick will have. If provided and
   *     the cherry-pick doesn't result in creating a new change, then
   *     InvalidChangeOperationException is thrown.
   * @return Result object that describes the cherry pick.
   * @throws IOException Unable to open repository or read from the database.
   * @throws InvalidChangeOperationException Parent or branch don't exist, or two changes with same
   *     key exist in the branch. Also thrown when idForNewChange is not null but cherry-pick only
   *     creates a new patchset rather than a new change.
   * @throws UpdateException Problem updating the database using batchUpdateFactory.
   * @throws RestApiException Error such as invalid SHA1
   * @throws ConfigInvalidException Can't find account to notify.
   * @throws NoSuchProjectException Can't find project state.
   */
  public Result cherryPick(
      @Nullable Change sourceChange,
      Project.NameKey project,
      ObjectId sourceCommit,
      CherryPickInput input,
      BranchNameKey dest,
      Instant timestamp,
      @Nullable Change.Id revertedChange,
      @Nullable ObjectId changeIdForNewChange,
      @Nullable Change.Id idForNewChange,
      @Nullable Boolean workInProgress)
      throws IOException, InvalidChangeOperationException, UpdateException, RestApiException,
          ConfigInvalidException, NoSuchProjectException {
    IdentifiedUser identifiedUser = user.get();
    try (Repository git = gitManager.openRepository(project);
        // This inserter and revwalk *must* be passed to any BatchUpdates
        // created later on, to ensure the cherry-picked commit is flushed
        // before patch sets are updated.
        ObjectInserter oi = git.newObjectInserter();
        ObjectReader reader = oi.newReader();
        CodeReviewRevWalk revWalk = CodeReviewCommit.newRevWalk(reader)) {
      Ref destRef = git.getRefDatabase().exactRef(dest.branch());
      if (destRef == null) {
        throw new InvalidChangeOperationException(
            String.format("Branch %s does not exist.", dest.branch()));
      }

      RevCommit baseCommit = getBaseCommit(destRef, project.get(), revWalk, input.base);

      CodeReviewCommit commitToCherryPick = revWalk.parseCommit(sourceCommit);

      if (input.parent <= 0 || input.parent > commitToCherryPick.getParentCount()) {
        throw new InvalidChangeOperationException(
            String.format(
                "Cherry Pick: Parent %s does not exist. Please specify a parent in"
                    + " range [1, %s].",
                input.parent, commitToCherryPick.getParentCount()));
      }

      // If the commit message is not set, the commit message of the source commit will be used.
      String commitMessage = Strings.nullToEmpty(input.message);
      commitMessage = commitMessage.isEmpty() ? commitToCherryPick.getFullMessage() : commitMessage;

      String destChangeId = getDestinationChangeId(commitMessage, changeIdForNewChange);

      ChangeData destChange = null;
      if (destChangeId != null) {
        // If "idForNewChange" is not null we must fail, since we are not expecting an already
        // existing change.
        destChange = getDestChangeWithVerification(destChangeId, dest, idForNewChange != null);
      }

      if (changeIdForNewChange != null) {
        // If Change-Id was explicitly provided for the new change, override the value in commit
        // message.
        commitMessage = ChangeIdUtil.insertId(commitMessage, changeIdForNewChange, true);
      } else if (destChangeId == null) {
        // If commit message did not specify Change-Id, generate a new one and insert to the
        // message.
        commitMessage =
            ChangeIdUtil.insertId(commitMessage, CommitMessageUtil.generateChangeId(), true);
      }
      commitMessage = CommitMessageUtil.checkAndSanitizeCommitMessage(commitMessage);

      CodeReviewCommit cherryPickCommit;
      ProjectState projectState =
          projectCache.get(dest.project()).orElseThrow(noSuchProject(dest.project()));
      PersonIdent committerIdent = identifiedUser.newCommitterIdent(timestamp, serverZoneId);

      try {
        MergeUtil mergeUtil;
        if (input.allowConflicts) {
          // allowConflicts requires to use content merge
          mergeUtil = mergeUtilFactory.create(projectState, true);
        } else {
          // use content merge only if it's configured on the project
          mergeUtil = mergeUtilFactory.create(projectState);
        }
        cherryPickCommit =
            mergeUtil.createCherryPickFromCommit(
                oi,
                git.getConfig(),
                baseCommit,
                commitToCherryPick,
                committerIdent,
                commitMessage,
                revWalk,
                input.parent - 1,
                input.allowEmpty,
                input.allowConflicts);
        oi.flush();
      } catch (MergeIdenticalTreeException | MergeConflictException e) {
        throw new IntegrationConflictException("Cherry pick failed: " + e.getMessage(), e);
      }

      try (BatchUpdate bu = batchUpdateFactory.create(project, identifiedUser, timestamp)) {
        bu.setRepository(git, revWalk, oi);
        bu.setNotify(resolveNotify(input));
        Change.Id changeId;
        String newTopic = null;
        if (input.topic != null) {
          newTopic = Strings.emptyToNull(input.topic.trim());
        }
        if (newTopic == null
            && sourceChange != null
            && !Strings.isNullOrEmpty(sourceChange.getTopic())) {
          newTopic = sourceChange.getTopic() + "-" + dest.shortName();
        }
        if (destChange != null) {
          // The change key exists on the destination branch. The cherry pick
          // will be added as a new patch set.
          changeId =
              insertPatchSet(
                  bu,
                  git,
                  destChange.notes(),
                  cherryPickCommit,
                  sourceChange,
                  newTopic,
                  input,
                  workInProgress);
        } else {
          // Change key not found on destination branch. We can create a new
          // change.
          changeId =
              createNewChange(
                  bu,
                  cherryPickCommit,
                  dest.branch(),
                  newTopic,
                  project,
                  sourceChange,
                  sourceCommit,
                  input,
                  revertedChange,
                  idForNewChange,
                  workInProgress);
        }
        bu.execute();
        return Result.create(changeId, cherryPickCommit.getFilesWithGitConflicts());
      }
    }
  }

  private RevCommit getBaseCommit(Ref destRef, String project, RevWalk revWalk, String base)
      throws RestApiException, IOException {
    RevCommit destRefTip = revWalk.parseCommit(destRef.getObjectId());
    // The tip commit of the destination ref is the default base for the newly created change.
    if (Strings.isNullOrEmpty(base)) {
      return destRefTip;
    }

    ObjectId baseObjectId;
    try {
      baseObjectId = ObjectId.fromString(base);
    } catch (InvalidObjectIdException e) {
      throw new BadRequestException(
          String.format("Base %s doesn't represent a valid SHA-1", base), e);
    }

    RevCommit baseCommit;
    try {
      baseCommit = revWalk.parseCommit(baseObjectId);
    } catch (MissingObjectException e) {
      throw new UnprocessableEntityException(
          String.format("Base %s doesn't exist", baseObjectId.name()), e);
    }

    InternalChangeQuery changeQuery = queryProvider.get();
    changeQuery.enforceVisibility(true);
    List<ChangeData> changeDatas = changeQuery.byBranchCommit(project, destRef.getName(), base);

    if (changeDatas.isEmpty()) {
      if (revWalk.isMergedInto(baseCommit, destRefTip)) {
        // The base commit is a merged commit with no change associated.
        return baseCommit;
      }
      throw new UnprocessableEntityException(
          String.format("Commit %s does not exist on branch %s", base, destRef.getName()));
    } else if (changeDatas.size() != 1) {
      throw new ResourceConflictException("Multiple changes found for commit " + base);
    }

    Change change = changeDatas.get(0).change();
    if (!change.isAbandoned()) {
      // The base commit is a valid change revision.
      return baseCommit;
    }

    throw new ResourceConflictException(
        String.format(
            "Change %s with commit %s is %s",
            change.getChangeId(), base, ChangeUtil.status(change)));
  }

  private Change.Id insertPatchSet(
      BatchUpdate bu,
      Repository git,
      ChangeNotes destNotes,
      CodeReviewCommit cherryPickCommit,
      @Nullable Change sourceChange,
      String topic,
      CherryPickInput input,
      @Nullable Boolean workInProgress)
      throws IOException {
    Change destChange = destNotes.getChange();
    PatchSet.Id psId = ChangeUtil.nextPatchSetId(git, destChange.currentPatchSetId());
    PatchSetInserter inserter = patchSetInserterFactory.create(destNotes, psId, cherryPickCommit);
    inserter.setMessage("Uploaded patch set " + inserter.getPatchSetId().get() + ".");
    inserter.setTopic(topic);
    if (workInProgress != null) {
      inserter.setWorkInProgress(workInProgress);
    }
    if (shouldSetToReady(cherryPickCommit, destNotes, workInProgress)) {
      inserter.setWorkInProgress(false);
    }
    inserter.setValidationOptions(getValidateOptionsAsMultimap(input.validationOptions));
    bu.addOp(destChange.getId(), inserter);
    PatchSet.Id sourcePatchSetId = sourceChange == null ? null : sourceChange.currentPatchSetId();
    // If sourceChange is not provided, reset cherryPickOf to avoid stale value.
    if (sourcePatchSetId == null) {
      bu.addOp(destChange.getId(), new ResetCherryPickOp());
    } else if (destChange.getCherryPickOf() == null
        || !destChange.getCherryPickOf().equals(sourcePatchSetId)) {
      SetCherryPickOp cherryPickOfUpdater = setCherryPickOfFactory.create(sourcePatchSetId);
      bu.addOp(destChange.getId(), cherryPickOfUpdater);
    }
    return destChange.getId();
  }

  /**
   * We should set the change to be "ready for review" if: 1. workInProgress is not already set on
   * this request. 2. The patch-set doesn't have any git conflict markers. 3. The change used to be
   * work in progress (because of a previous patch-set).
   */
  private boolean shouldSetToReady(
      CodeReviewCommit cherryPickCommit,
      ChangeNotes destChangeNotes,
      @Nullable Boolean workInProgress) {
    return workInProgress == null
        && cherryPickCommit.getFilesWithGitConflicts().isEmpty()
        && destChangeNotes.getChange().isWorkInProgress();
  }

  private Change.Id createNewChange(
      BatchUpdate bu,
      CodeReviewCommit cherryPickCommit,
      String refName,
      String topic,
      Project.NameKey project,
      @Nullable Change sourceChange,
      @Nullable ObjectId sourceCommit,
      CherryPickInput input,
      @Nullable Change.Id revertOf,
      @Nullable Change.Id idForNewChange,
      @Nullable Boolean workInProgress)
      throws IOException, InvalidChangeOperationException {
    Change.Id changeId = idForNewChange != null ? idForNewChange : Change.id(seq.nextChangeId());
    ChangeInserter ins = changeInserterFactory.create(changeId, cherryPickCommit, refName);
    ins.setRevertOf(revertOf);
    if (workInProgress != null) {
      ins.setWorkInProgress(workInProgress);
    } else {
      ins.setWorkInProgress(
          (sourceChange != null && sourceChange.isWorkInProgress())
              || !cherryPickCommit.getFilesWithGitConflicts().isEmpty());
    }
    ins.setValidationOptions(getValidateOptionsAsMultimap(input.validationOptions));
    BranchNameKey sourceBranch = sourceChange == null ? null : sourceChange.getDest();
    PatchSet.Id sourcePatchSetId = sourceChange == null ? null : sourceChange.currentPatchSetId();
    ins.setMessage(
            revertOf == null
                ? messageForDestinationChange(
                    ins.getPatchSetId(), sourceBranch, sourceCommit, cherryPickCommit)
                : "Uploaded patch set 1.") // For revert commits, the message should not include
        // cherry-pick information.
        .setTopic(topic);
    if (revertOf == null) {
      ins.setCherryPickOf(sourcePatchSetId);
    }
    if (input.keepReviewers && sourceChange != null) {
      ReviewerSet reviewerSet =
          approvalsUtil.getReviewers(changeNotesFactory.createChecked(sourceChange));
      Set<Account.Id> reviewers =
          new HashSet<>(reviewerSet.byState(ReviewerStateInternal.REVIEWER));
      reviewers.add(sourceChange.getOwner());
      reviewers.remove(user.get().getAccountId());
      Set<Account.Id> ccs = new HashSet<>(reviewerSet.byState(ReviewerStateInternal.CC));
      ccs.remove(user.get().getAccountId());
      ins.setReviewersAndCcs(reviewers, ccs);
    }
    // If there is a base, and the base is not merged, the groups will be overridden by the base's
    // groups.
    ins.setGroups(GroupCollector.getDefaultGroups(cherryPickCommit.getId()));
    if (input.base != null) {
      List<ChangeData> changes =
          queryProvider.get().setLimit(2).byBranchCommitOpen(project.get(), refName, input.base);
      if (changes.size() > 1) {
        throw new InvalidChangeOperationException(
            "Several changes with key "
                + input.base
                + " reside on the same branch. "
                + "Cannot cherry-pick on target branch.");
      }
      if (changes.size() == 1) {
        Change change = changes.get(0).change();
        ins.setGroups(changeNotesFactory.createChecked(change).getCurrentPatchSet().groups());
      }
    }
    bu.insertChange(ins);
    return changeId;
  }

  private static ImmutableListMultimap<String, String> getValidateOptionsAsMultimap(
      @Nullable Map<String, String> validationOptions) {
    if (validationOptions == null) {
      return ImmutableListMultimap.of();
    }

    ImmutableListMultimap.Builder<String, String> validationOptionsBuilder =
        ImmutableListMultimap.builder();
    validationOptions
        .entrySet()
        .forEach(e -> validationOptionsBuilder.put(e.getKey(), e.getValue()));
    return validationOptionsBuilder.build();
  }

  private NotifyResolver.Result resolveNotify(CherryPickInput input)
      throws BadRequestException, ConfigInvalidException, IOException {
    return notifyResolver.resolve(
        firstNonNull(input.notify, NotifyHandling.ALL), input.notifyDetails);
  }

  private String messageForDestinationChange(
      PatchSet.Id patchSetId,
      BranchNameKey sourceBranch,
      ObjectId sourceCommit,
      CodeReviewCommit cherryPickCommit) {
    StringBuilder stringBuilder = new StringBuilder("Patch Set ").append(patchSetId.get());
    if (sourceBranch != null) {
      stringBuilder.append(": Cherry Picked from branch ").append(sourceBranch.shortName());
    } else {
      stringBuilder.append(": Cherry Picked from commit ").append(sourceCommit.getName());
    }
    stringBuilder.append(".");

    if (!cherryPickCommit.getFilesWithGitConflicts().isEmpty()) {
      stringBuilder.append("\n\nThe following files contain Git conflicts:");
      cherryPickCommit.getFilesWithGitConflicts().stream()
          .sorted()
          .forEach(filePath -> stringBuilder.append("\n* ").append(filePath));
    }

    return stringBuilder.toString();
  }

  /**
   * Returns the Change-Id of destination change (as intended by the caller of cherry-pick
   * operation).
   *
   * <p>The Change-Id can be provided in one of the following ways:
   *
   * <ul>
   *   <li>Explicitly provided for the new change.
   *   <li>Provided in the input commit message.
   *   <li>Taken from the source commit if commit message was not set.
   * </ul>
   *
   * Otherwise should be generated.
   *
   * @param commitMessage the commit message, as intended by the caller of cherry-pick operation.
   * @param changeIdForNewChange the explicitly provided Change-Id for the new change.
   * @return The Change-Id of destination change, {@code null} if Change-Id was not provided by the
   *     caller of cherry-pick operation and should be generated.
   */
  @Nullable
  private String getDestinationChangeId(
      String commitMessage, @Nullable ObjectId changeIdForNewChange) {
    if (changeIdForNewChange != null) {
      return CommitMessageUtil.getChangeIdFromObjectId(changeIdForNewChange);
    }
    return CommitMessageUtil.getChangeIdFromCommitMessageFooter(commitMessage).orElse(null);
  }

  /**
   * Returns the change from the destination branch, if it exists and is valid for the cherry-pick.
   *
   * @param destChangeId the Change-ID of the change in the destination branch.
   * @param destBranch the branch to search by the Change-ID.
   * @param verifyIsMissing if {@code true}, verifies that the change should be missing in the
   *     destination branch.
   * @return the verified change or {@code null} if the change was not found.
   * @throws InvalidChangeOperationException if the change was found but failed validation
   */
  @Nullable
  private ChangeData getDestChangeWithVerification(
      String destChangeId, BranchNameKey destBranch, boolean verifyIsMissing)
      throws InvalidChangeOperationException {
    List<ChangeData> destChanges =
        queryProvider.get().setLimit(2).byBranchKey(destBranch, Change.key(destChangeId));
    if (destChanges.size() > 1) {
      throw new InvalidChangeOperationException(
          "Several changes with key "
              + destChangeId
              + " reside on the same branch. "
              + "Cannot create a new patch set.");
    }
    if (destChanges.size() == 1 && verifyIsMissing) {
      throw new InvalidChangeOperationException(
          String.format(
              "Expected that cherry-pick with Change-Id %s to branch %s "
                  + "in project %s creates a new change, but found existing change %d",
              destChangeId,
              destBranch.branch(),
              destBranch.project().get(),
              destChanges.get(0).getId().get()));
    }
    ChangeData destChange = destChanges.size() == 1 ? destChanges.get(0) : null;

    if (destChange != null && destChange.change().isClosed()) {
      throw new InvalidChangeOperationException(
          String.format(
              "Cherry-pick with Change-Id %s could not update the existing change %d "
                  + "in destination branch %s of project %s, because the change was closed (%s)",
              destChangeId,
              destChange.getId().get(),
              destBranch.branch(),
              destBranch.project(),
              destChange.change().getStatus().name()));
    }
    return destChange;
  }
}
