// Copyright (C) 2019 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.extensions.conditions.BooleanCondition.and;
import static com.google.gerrit.server.permissions.ChangePermission.REVERT;
import static com.google.gerrit.server.permissions.RefPermission.CREATE_CHANGE;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;
import static java.util.Objects.requireNonNull;

import com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.changes.CherryPickInput;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.RevertInput;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.RevertSubmissionInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.server.change.ChangeMessages;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.NotifyResolver;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.change.WalkSorter;
import com.google.gerrit.server.change.WalkSorter.PatchSetData;
import com.google.gerrit.server.git.CommitUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ContributorAgreementsChecker;
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.restapi.change.CherryPickChange.Result;
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.UpdateException;
import com.google.gerrit.server.update.context.RefUpdateContext;
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 java.io.IOException;
import java.text.MessageFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.apache.commons.lang3.RandomStringUtils;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

public class RevertSubmission
    implements RestModifyView<ChangeResource, RevertInput>, UiAction<ChangeResource> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final Provider<InternalChangeQuery> queryProvider;
  private final Provider<CurrentUser> user;
  private final PermissionBackend permissionBackend;
  private final ProjectCache projectCache;
  private final PatchSetUtil psUtil;
  private final ContributorAgreementsChecker contributorAgreements;
  private final CherryPickChange cherryPickChange;
  private final ChangeJson.Factory json;
  private final GitRepositoryManager repoManager;
  private final WalkSorter sorter;
  private final CommitUtil commitUtil;
  private final ChangeNotes.Factory changeNotesFactory;
  private final Sequences seq;
  private final NotifyResolver notifyResolver;
  private final BatchUpdate.Factory updateFactory;
  private final ChangeResource.Factory changeResourceFactory;
  private final GetRelated getRelated;

  private CherryPickInput cherryPickInput;
  private List<ChangeInfo> results;
  private static final Pattern patternRevertSubject = Pattern.compile("Revert \"(.+)\"");
  private static final Pattern patternRevertSubjectWithNum =
      Pattern.compile("Revert\\^(\\d+) \"(.+)\"");

  @Inject
  RevertSubmission(
      Provider<InternalChangeQuery> queryProvider,
      Provider<CurrentUser> user,
      PermissionBackend permissionBackend,
      ProjectCache projectCache,
      PatchSetUtil psUtil,
      ContributorAgreementsChecker contributorAgreements,
      CherryPickChange cherryPickChange,
      ChangeJson.Factory json,
      GitRepositoryManager repoManager,
      WalkSorter sorter,
      CommitUtil commitUtil,
      ChangeNotes.Factory changeNotesFactory,
      Sequences seq,
      NotifyResolver notifyResolver,
      BatchUpdate.Factory updateFactory,
      ChangeResource.Factory changeResourceFactory,
      GetRelated getRelated) {
    this.queryProvider = queryProvider;
    this.user = user;
    this.permissionBackend = permissionBackend;
    this.projectCache = projectCache;
    this.psUtil = psUtil;
    this.contributorAgreements = contributorAgreements;
    this.cherryPickChange = cherryPickChange;
    this.json = json;
    this.repoManager = repoManager;
    this.sorter = sorter;
    this.commitUtil = commitUtil;
    this.changeNotesFactory = changeNotesFactory;
    this.seq = seq;
    this.notifyResolver = notifyResolver;
    this.updateFactory = updateFactory;
    this.changeResourceFactory = changeResourceFactory;
    this.getRelated = getRelated;
    results = new ArrayList<>();
    cherryPickInput = null;
  }

  @Override
  public Response<RevertSubmissionInfo> apply(ChangeResource changeResource, RevertInput input)
      throws RestApiException,
          IOException,
          UpdateException,
          PermissionBackendException,
          NoSuchProjectException,
          ConfigInvalidException,
          StorageException {

    if (!changeResource.getChange().isMerged()) {
      throw new ResourceConflictException(
          String.format("change is %s.", ChangeUtil.status(changeResource.getChange())));
    }

    String submissionId = changeResource.getChange().getSubmissionId();
    if (submissionId == null) {
      throw new ResourceConflictException(
          "This change is merged but doesn't have a submission id,"
              + " meaning it was not submitted through Gerrit.");
    }
    List<ChangeData> changeDatas = queryProvider.get().bySubmissionId(submissionId);

    checkPermissionsForAllChanges(changeResource, changeDatas);
    input.topic = createTopic(input.topic, submissionId);

    return Response.ok(revertSubmission(changeDatas, input));
  }

  private String createTopic(String topic, String submissionId) {
    if (topic != null) {
      topic = Strings.emptyToNull(topic.trim());
    }
    if (topic == null) {
      return String.format(
          "revert-%s-%s",
          submissionId, RandomStringUtils.randomAlphabetic(10).toUpperCase(Locale.US));
    }
    return topic;
  }

  private void checkPermissionsForAllChanges(
      ChangeResource changeResource, List<ChangeData> changeDatas)
      throws IOException, AuthException, PermissionBackendException, ResourceConflictException {
    for (ChangeData changeData : changeDatas) {
      Change change = changeData.change();

      // Might do the permission tests multiple times, but these are necessary to ensure that the
      // user has permissions to revert all changes. If they lack any permission, no revert will be
      // done.

      contributorAgreements.check(change.getProject(), changeResource.getUser());
      permissionBackend.currentUser().ref(change.getDest()).check(CREATE_CHANGE);
      permissionBackend.currentUser().change(changeData).check(REVERT);
      permissionBackend.currentUser().change(changeData).check(ChangePermission.READ);
      projectCache
          .get(change.getProject())
          .orElseThrow(illegalState(change.getProject()))
          .checkStatePermitsWrite();

      requireNonNull(
          psUtil.get(changeData.notes(), change.currentPatchSetId()),
          String.format(
              "current patch set %s of change %s not found",
              change.currentPatchSetId(), change.currentPatchSetId()));
    }
  }

  private RevertSubmissionInfo revertSubmission(
      List<ChangeData> changeData, RevertInput revertInput)
      throws RestApiException,
          IOException,
          UpdateException,
          ConfigInvalidException,
          StorageException,
          PermissionBackendException {

    ListMultimap<BranchNameKey, ChangeData> changesPerProjectAndBranch = ArrayListMultimap.create();
    changeData.stream().forEach(c -> changesPerProjectAndBranch.put(c.change().getDest(), c));
    cherryPickInput = createCherryPickInput(revertInput);
    Instant timestamp = TimeUtil.now();

    String initialMessage = revertInput.message;
    for (BranchNameKey projectAndBranch : changesPerProjectAndBranch.keySet()) {
      cherryPickInput.base = null;
      Project.NameKey project = projectAndBranch.project();
      cherryPickInput.destination = projectAndBranch.branch();
      List<ChangeData> changesInProjectAndBranch = changesPerProjectAndBranch.get(projectAndBranch);

      // Sort the changes topologically.
      Iterator<PatchSetData> sortedChangesInProjectAndBranch =
          sorter.sort(changesInProjectAndBranch).iterator();

      Set<ObjectId> commitIdsInProjectAndBranch =
          changesInProjectAndBranch.stream()
              .map(c -> c.currentPatchSet().commitId())
              .collect(Collectors.toSet());

      revertAllChangesInProjectAndBranch(
          initialMessage,
          revertInput,
          project,
          sortedChangesInProjectAndBranch,
          commitIdsInProjectAndBranch,
          timestamp);
    }
    results.sort(Comparator.comparing(c -> c.revertOf));
    RevertSubmissionInfo revertSubmissionInfo = new RevertSubmissionInfo();
    revertSubmissionInfo.revertChanges = results;
    return revertSubmissionInfo;
  }

  // Warning: reuses and modifies revertInput.message.
  private void revertAllChangesInProjectAndBranch(
      String initialMessage,
      RevertInput revertInput,
      Project.NameKey project,
      Iterator<PatchSetData> sortedChangesInProjectAndBranch,
      Set<ObjectId> commitIdsInProjectAndBranch,
      Instant timestamp)
      throws IOException,
          RestApiException,
          UpdateException,
          ConfigInvalidException,
          PermissionBackendException {
    while (sortedChangesInProjectAndBranch.hasNext()) {
      ChangeNotes changeNotes = sortedChangesInProjectAndBranch.next().data().notes();
      if (cherryPickInput.base == null) {
        // If no base was provided, the first change will be used to find a common base.
        cherryPickInput.base = getBase(changeNotes, commitIdsInProjectAndBranch).name();
      }

      // Set revert message for the current revert change.
      revertInput.message = getMessage(initialMessage, changeNotes);
      if (cherryPickInput.base.equals(changeNotes.getCurrentPatchSet().commitId().getName())) {
        // This is the code in case this is the first revert of this project + branch, and the
        // revert would be on top of the change being reverted.
        createNormalRevert(revertInput, changeNotes, timestamp);
      } else {
        createCherryPickedRevert(revertInput, project, changeNotes, timestamp);
      }
    }
  }

  private void createCherryPickedRevert(
      RevertInput revertInput, Project.NameKey project, ChangeNotes changeNotes, Instant timestamp)
      throws IOException, ConfigInvalidException, UpdateException, RestApiException {
    RevCommit revCommit =
        commitUtil.createRevertCommit(revertInput.message, changeNotes, user.get(), timestamp);
    // TODO (paiking): As a future change, the revert should just be done directly on the
    // target rather than just creating a commit and then cherry-picking it.
    cherryPickInput.message = revCommit.getFullMessage();
    ObjectId generatedChangeId = CommitMessageUtil.generateChangeId();
    Change.Id cherryPickRevertChangeId = Change.id(seq.nextChangeId());
    RevCommit baseCommit = null;
    if (cherryPickInput.base != null) {
      try (Repository git = repoManager.openRepository(changeNotes.getProjectName());
          RevWalk revWalk = new RevWalk(git.newObjectReader())) {
        baseCommit = revWalk.parseCommit(ObjectId.fromString(cherryPickInput.base));
      }
    }
    try (RefUpdateContext ctx = RefUpdateContext.open(CHANGE_MODIFICATION)) {
      try (BatchUpdate bu = updateFactory.create(project, user.get(), TimeUtil.now())) {
        bu.setNotify(
            notifyResolver.resolve(
                firstNonNull(cherryPickInput.notify, NotifyHandling.ALL),
                cherryPickInput.notifyDetails));
        bu.addOp(
            changeNotes.getChange().getId(),
            new CreateCherryPickOp(
                revCommit,
                generatedChangeId,
                cherryPickRevertChangeId,
                timestamp,
                revertInput.getWorkInProgress(),
                baseCommit));
        if (!revertInput.getWorkInProgress()) {
          commitUtil.addChangeRevertedNotificationOps(
              bu, changeNotes.getChangeId(), cherryPickRevertChangeId, generatedChangeId.name());
        }
        bu.execute();
      }
    }
  }

  private void createNormalRevert(
      RevertInput revertInput, ChangeNotes changeNotes, Instant timestamp)
      throws IOException, RestApiException, UpdateException, ConfigInvalidException {

    Change.Id revertId =
        commitUtil.createRevertChange(changeNotes, user.get(), revertInput, timestamp);
    results.add(json.noOptions().format(changeNotes.getProjectName(), revertId));
    cherryPickInput.base =
        changeNotesFactory
            .createChecked(changeNotes.getProjectName(), revertId)
            .getCurrentPatchSet()
            .commitId()
            .getName();
  }

  private CherryPickInput createCherryPickInput(RevertInput revertInput) {
    cherryPickInput = new CherryPickInput();
    // To create a revert change, we create a revert commit that is then cherry-picked. The revert
    // change is created for the cherry-picked commit. Notifications are sent only for this change,
    // but not for the intermediately created revert commit.
    cherryPickInput.notify = revertInput.notify;
    if (revertInput.getWorkInProgress()) {
      cherryPickInput.notify = firstNonNull(cherryPickInput.notify, NotifyHandling.NONE);
    }
    cherryPickInput.notifyDetails = revertInput.notifyDetails;
    cherryPickInput.parent = 1;
    cherryPickInput.keepReviewers = true;
    cherryPickInput.topic = revertInput.topic;
    cherryPickInput.allowEmpty = true;
    return cherryPickInput;
  }

  private String getMessage(String initialMessage, ChangeNotes changeNotes) {
    String subject = changeNotes.getChange().getSubject();
    if (subject.length() > 60) {
      subject = subject.substring(0, 56) + "...";
    }
    if (initialMessage == null) {
      initialMessage =
          MessageFormat.format(
              ChangeMessages.revertSubmissionDefaultMessage,
              changeNotes.getCurrentPatchSet().commitId().name());
    }

    // For performance purposes: Almost all cases will end here.
    if (!subject.startsWith("Revert")) {
      return MessageFormat.format(
          ChangeMessages.revertSubmissionUserMessage, subject, initialMessage);
    }

    Matcher matcher = patternRevertSubjectWithNum.matcher(subject);

    if (matcher.matches()) {
      return MessageFormat.format(
          ChangeMessages.revertSubmissionOfRevertSubmissionUserMessage,
          Integer.valueOf(matcher.group(1)) + 1,
          matcher.group(2),
          changeNotes.getCurrentPatchSet().commitId().name());
    }

    matcher = patternRevertSubject.matcher(subject);
    if (matcher.matches()) {
      return MessageFormat.format(
          ChangeMessages.revertSubmissionOfRevertSubmissionUserMessage,
          2,
          matcher.group(1),
          changeNotes.getCurrentPatchSet().commitId().name());
    }

    return MessageFormat.format(
        ChangeMessages.revertSubmissionUserMessage, subject, initialMessage);
  }

  /**
   * This function finds the base that the first revert in a project + branch should be based on.
   *
   * <p>If there is only one change, we will base the revert on that change. If all changes are
   * related, we will base on the first commit of this submission in the topological order.
   *
   * <p>If none of those special cases applies, the only case left is the case where we have at
   * least 2 independent changes in the same project + branch (and possibly other dependent
   * changes). In this case, it searches using BFS for the first commit that is either: 1. Has 2 or
   * more parents, and has as parents at least one commit that is part of the submission. 2. A
   * commit that is part of the submission. If neither of those are true, it just continues the
   * search by going to the parents.
   *
   * <p>If 1 is true, it means that this merge commit was created when this submission was
   * submitted. It also means that this merge commit is a descendant of all of the changes in this
   * submission and project + branch. Therefore, we return this merge commit.
   *
   * <p>If 2 is true, it will return the commit that WalkSorter has decided that it should be the
   * first commit reverted (e.g changeNotes, which is also the commit that is the first in the
   * topological sorting).
   *
   * <p>It doesn't run through the entire graph since it will stop once it finds at least one commit
   * that is part of the submission.
   *
   * @param changeNotes changeNotes for the change that is found by WalkSorter to be the first one
   *     that should be reverted, the first in the topological sorting.
   * @param commitIds The commitIds of this project and branch.
   * @return the base of the first revert.
   */
  private ObjectId getBase(ChangeNotes changeNotes, Set<ObjectId> commitIds)
      throws StorageException, IOException, PermissionBackendException {
    // If there is only one change in that project and branch, just base the revert on that one
    // change.
    if (commitIds.size() == 1) {
      return Iterables.getOnlyElement(commitIds);
    }
    // If all changes are related, just return the first commit of this submission in the
    // topological sorting.
    if (getRelated.getRelated(getRevisionResource(changeNotes)).stream()
        .map(changes -> ObjectId.fromString(changes.commit.commit))
        .collect(Collectors.toSet())
        .containsAll(commitIds)) {
      return changeNotes.getCurrentPatchSet().commitId();
    }
    // There are independent changes in this submission and repository + branch.
    try (Repository git = repoManager.openRepository(changeNotes.getProjectName());
        ObjectInserter oi = git.newObjectInserter();
        ObjectReader reader = oi.newReader();
        RevWalk revWalk = new RevWalk(reader)) {

      ObjectId startCommit =
          git.getRefDatabase().findRef(changeNotes.getChange().getDest().branch()).getObjectId();
      revWalk.markStart(revWalk.parseCommit(startCommit));
      markChangesParentsUninteresting(commitIds, revWalk);
      Iterator<RevCommit> revWalkIterator = revWalk.iterator();
      while (revWalkIterator.hasNext()) {
        RevCommit revCommit = revWalkIterator.next();
        if (commitIds.contains(revCommit.getId())) {
          return changeNotes.getCurrentPatchSet().commitId();
        }
        if (Arrays.stream(revCommit.getParents())
            .anyMatch(parent -> commitIds.contains(parent.getId()))) {
          // Found a merge commit that at least one parent is in this submission. we should only
          // reach here if both conditions apply:
          // 1. There is more than one change in that project + branch in this submission.
          // 2. Not all changes in that project + branch are related in this submission.
          // Therefore, there are at least 2 unrelated changes in this project + branch that got
          // submitted together,
          // and since we found a merge commit with one of those as parents, this merge commit is
          // the first common descendant of all those changes.
          return revCommit.getId();
        }
      }
      // This should never happen since it can only happen if we go through the entire repository
      // without finding a single commit that matches any commit from the submission.
      throw new StorageException(
          String.format(
              "Couldn't find change %s in the repository %s",
              changeNotes.getChangeId(), changeNotes.getProjectName().get()));
    }
  }

  private RevisionResource getRevisionResource(ChangeNotes changeNotes) {
    return new RevisionResource(
        changeResourceFactory.create(changeNotes, user.get()), psUtil.current(changeNotes));
  }

  // The parents are not interesting since there is no reason to base the reverts on any of the
  // parents or their ancestors.
  private void markChangesParentsUninteresting(Set<ObjectId> commitIds, RevWalk revWalk)
      throws IOException {
    for (ObjectId id : commitIds) {
      RevCommit revCommit = revWalk.parseCommit(id);
      for (int i = 0; i < revCommit.getParentCount(); i++) {
        revWalk.markUninteresting(revCommit.getParent(i));
      }
    }
  }

  @Override
  public Description getDescription(ChangeResource rsrc) {
    Change change = rsrc.getChange();
    boolean projectStatePermitsWrite = false;
    try {
      projectStatePermitsWrite =
          projectCache.get(rsrc.getProject()).map(ProjectState::statePermitsWrite).orElse(false);
    } catch (StorageException e) {
      logger.atSevere().withCause(e).log(
          "Failed to check if project state permits write: %s", rsrc.getProject());
    }
    return new UiAction.Description()
        .setLabel("Revert submission")
        .setTitle(
            "Revert this change and all changes that have been submitted together with this change")
        .setVisible(
            and(
                and(
                    change.isMerged()
                        && change.getSubmissionId() != null
                        && isChangePartOfSubmission(change.getSubmissionId())
                        && projectStatePermitsWrite,
                    permissionBackend
                        .user(rsrc.getUser())
                        .ref(change.getDest())
                        .testCond(CREATE_CHANGE)),
                permissionBackend.user(rsrc.getUser()).change(rsrc.getNotes()).testCond(REVERT)));
  }

  /**
   * @param submissionId the submission id of the change.
   * @return True if the submission has more than one change, false otherwise.
   */
  private Boolean isChangePartOfSubmission(String submissionId) {
    return (queryProvider.get().setLimit(2).bySubmissionId(submissionId).size() > 1);
  }

  private class CreateCherryPickOp implements BatchUpdateOp {
    private final ObjectId revCommitId;
    private final ObjectId computedChangeId;
    private final Change.Id cherryPickRevertChangeId;
    private final Instant timestamp;
    private final boolean workInProgress;
    private final RevCommit baseCommit;

    CreateCherryPickOp(
        ObjectId revCommitId,
        ObjectId computedChangeId,
        Change.Id cherryPickRevertChangeId,
        Instant timestamp,
        Boolean workInProgress,
        RevCommit baseCommit) {
      this.revCommitId = revCommitId;
      this.computedChangeId = computedChangeId;
      this.cherryPickRevertChangeId = cherryPickRevertChangeId;
      this.timestamp = timestamp;
      this.workInProgress = workInProgress;
      this.baseCommit = baseCommit;
    }

    @Override
    public boolean updateChange(ChangeContext ctx) throws Exception {
      Change change = ctx.getChange();
      Result cherryPickResult =
          cherryPickChange.cherryPick(
              change,
              change.currentPatchSetId(),
              change.getProject(),
              revCommitId,
              cherryPickInput,
              BranchNameKey.create(
                  change.getProject(), RefNames.fullName(cherryPickInput.destination)),
              timestamp,
              change.getId(),
              computedChangeId,
              cherryPickRevertChangeId,
              workInProgress,
              Optional.ofNullable(baseCommit));
      // save the commit as base for next cherryPick of that branch
      cherryPickInput.base =
          changeNotesFactory
              .createChecked(ctx.getProject(), cherryPickResult.changeId())
              .getCurrentPatchSet()
              .commitId()
              .getName();
      results.add(json.noOptions().format(change.getProject(), cherryPickResult.changeId()));
      return true;
    }
  }
}
