// Copyright (C) 2014 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.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;
import static org.eclipse.jgit.lib.Constants.SIGNED_OFF_BY_TAG;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.UsedAt;
import com.google.gerrit.entities.BooleanProjectConfig;
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.entities.RefNames;
import com.google.gerrit.entities.converter.ChangeInputProtoConverter;
import com.google.gerrit.exceptions.InvalidMergeStrategyException;
import com.google.gerrit.exceptions.MergeWithConflictsNotSupportedException;
import com.google.gerrit.extensions.api.accounts.AccountInput;
import com.google.gerrit.extensions.api.changes.ApplyPatchInput;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeInput;
import com.google.gerrit.extensions.common.MergeInput;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestCollectionModifyView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.proto.Entities;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.change.ChangeFinder;
import com.google.gerrit.server.change.ChangeInserter;
import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.NotifyResolver;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.git.CommitUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
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.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.RefPermission;
import com.google.gerrit.server.project.ContributorAgreementsChecker;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.ProjectResource;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.restapi.project.CommitsCollection;
import com.google.gerrit.server.restapi.project.ProjectsCollection;
import com.google.gerrit.server.update.BatchUpdate;
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 com.google.inject.Singleton;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneId;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.InvalidObjectIdException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.NoMergeBaseException;
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.lib.TreeFormatter;
import org.eclipse.jgit.patch.PatchApplier;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.ChangeIdUtil;

@Singleton
public class CreateChange
    implements RestCollectionModifyView<TopLevelResource, ChangeResource, ChangeInput> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
  private static final ChangeInputProtoConverter CHANGE_INPUT_PROTO_CONVERTER =
      ChangeInputProtoConverter.INSTANCE;

  private final BatchUpdate.Factory updateFactory;
  private final String anonymousCowardName;
  private final GitRepositoryManager gitManager;
  private final Sequences seq;
  private final ZoneId serverZoneId;
  private final PermissionBackend permissionBackend;
  private final Provider<CurrentUser> user;
  private final ProjectsCollection projectsCollection;
  private final CommitsCollection commits;
  private final ChangeInserter.Factory changeInserterFactory;
  private final ChangeJson.Factory jsonFactory;
  private final ChangeFinder changeFinder;
  private final Provider<InternalChangeQuery> queryProvider;
  private final PatchSetUtil psUtil;
  private final MergeUtilFactory mergeUtilFactory;
  private final SubmitType submitType;
  private final NotifyResolver notifyResolver;
  private final ContributorAgreementsChecker contributorAgreements;
  private final boolean disablePrivateChanges;

  @Inject
  CreateChange(
      BatchUpdate.Factory updateFactory,
      @AnonymousCowardName String anonymousCowardName,
      GitRepositoryManager gitManager,
      Sequences seq,
      @GerritPersonIdent PersonIdent myIdent,
      PermissionBackend permissionBackend,
      Provider<CurrentUser> user,
      ProjectsCollection projectsCollection,
      CommitsCollection commits,
      ChangeInserter.Factory changeInserterFactory,
      ChangeJson.Factory json,
      ChangeFinder changeFinder,
      Provider<InternalChangeQuery> queryProvider,
      PatchSetUtil psUtil,
      @GerritServerConfig Config config,
      MergeUtilFactory mergeUtilFactory,
      NotifyResolver notifyResolver,
      ContributorAgreementsChecker contributorAgreements) {
    this.updateFactory = updateFactory;
    this.anonymousCowardName = anonymousCowardName;
    this.gitManager = gitManager;
    this.seq = seq;
    this.serverZoneId = myIdent.getZoneId();
    this.permissionBackend = permissionBackend;
    this.user = user;
    this.projectsCollection = projectsCollection;
    this.commits = commits;
    this.changeInserterFactory = changeInserterFactory;
    this.jsonFactory = json;
    this.changeFinder = changeFinder;
    this.queryProvider = queryProvider;
    this.psUtil = psUtil;
    this.submitType = config.getEnum("project", null, "submitType", SubmitType.MERGE_IF_NECESSARY);
    this.disablePrivateChanges = config.getBoolean("change", null, "disablePrivateChanges", false);
    this.mergeUtilFactory = mergeUtilFactory;
    this.notifyResolver = notifyResolver;
    this.contributorAgreements = contributorAgreements;
  }

  @Override
  public Response<ChangeInfo> apply(TopLevelResource parent, ChangeInput input)
      throws IOException, InvalidChangeOperationException, RestApiException, UpdateException,
          PermissionBackendException, ConfigInvalidException {
    if (Strings.isNullOrEmpty(input.project)) {
      throw new BadRequestException("project must be non-empty");
    }

    return execute(updateFactory, input, projectsCollection.parse(input.project));
  }

  @UsedAt(UsedAt.Project.GOOGLE)
  @FunctionalInterface
  public interface CommitTreeSupplier {
    @NonNull
    ObjectId get(
        Repository repo, ObjectInserter oi, ObjectReader or, ChangeInput input, RevCommit mergeTip)
        throws IOException, RestApiException;
  }

  /**
   * Creates the changes in the given project, using the proto representation of ChangeInput -
   * {@link com.google.gerrit.proto.Entities.ChangeInput}.
   */
  @UsedAt(UsedAt.Project.GOOGLE)
  public Response<ChangeInfo> execute(
      BatchUpdate.Factory updateFactory,
      Entities.ChangeInput input,
      CommitTreeSupplier commitTreeSupplier)
      throws IOException, RestApiException, UpdateException, PermissionBackendException,
          ConfigInvalidException {
    return execute(
        updateFactory,
        CHANGE_INPUT_PROTO_CONVERTER.fromProto(input),
        projectsCollection.parse(input.getProject()),
        Optional.of(commitTreeSupplier));
  }

  /**
   * Creates the changes in the given project, using the java-class representation of ChangeInput -
   * {@link com.google.gerrit.extensions.common.ChangeInput}. This is public for reuse in the
   * project API.
   */
  public Response<ChangeInfo> execute(
      BatchUpdate.Factory updateFactory, ChangeInput input, ProjectResource projectResource)
      throws IOException, RestApiException, UpdateException, PermissionBackendException,
          ConfigInvalidException {
    return execute(updateFactory, input, projectResource, Optional.empty());
  }

  private Response<ChangeInfo> execute(
      BatchUpdate.Factory updateFactory,
      ChangeInput input,
      ProjectResource projectResource,
      Optional<CommitTreeSupplier> commitTreeSupplier)
      throws IOException, RestApiException, UpdateException, PermissionBackendException,
          ConfigInvalidException {
    if (!user.get().isIdentifiedUser()) {
      throw new AuthException("Authentication required");
    }

    ProjectState projectState = projectResource.getProjectState();
    projectState.checkStatePermitsWrite();

    IdentifiedUser me = user.get().asIdentifiedUser();
    checkAndSanitizeChangeInput(input, me, commitTreeSupplier);

    Project.NameKey project = projectResource.getNameKey();
    contributorAgreements.check(project, user.get());

    checkRequiredPermissions(project, input.branch, input.author);

    ChangeInfo newChange =
        createNewChange(input, me, projectState, updateFactory, commitTreeSupplier);
    return Response.created(newChange);
  }

  /**
   * Checks and sanitizes the user input, e.g. check whether the input is legal; clean the input so
   * that it meets the requirement for creating a change; set a field based on the global configs,
   * etc.
   *
   * @param input the {@code ChangeInput} from the request. Note this method modify the {@code
   *     ChangeInput} object so that it can be reused directly by follow-up code.
   * @param me the user who sent the current request to create a change.
   * @throws BadRequestException if the input is not legal.
   */
  private void checkAndSanitizeChangeInput(
      ChangeInput input, IdentifiedUser me, Optional<CommitTreeSupplier> commitTreeSupplier)
      throws RestApiException, PermissionBackendException, IOException {
    if (Strings.isNullOrEmpty(input.branch)) {
      throw new BadRequestException("branch must be non-empty");
    }
    input.branch = RefNames.fullName(input.branch);
    if (!isBranchAllowed(input.branch)) {
      throw new BadRequestException(
          "Cannot create a change on ref "
              + input.branch
              + ". Gerrit internal refs and refs/tags/* are not allowed.");
    }

    String subject = Strings.nullToEmpty(input.subject);
    subject = subject.replaceAll("(?m)^#.*$\n?", "").trim();
    if (subject.isEmpty()) {
      throw new BadRequestException("commit message must be non-empty");
    }
    input.subject = subject;

    Optional<String> changeId = getChangeIdFromMessage(input.subject);
    if (changeId.isPresent()) {
      if (!queryProvider
          .get()
          .setLimit(1)
          .byBranchKey(
              BranchNameKey.create(input.project, input.branch), Change.key(changeId.get()))
          .isEmpty()) {
        throw new ResourceConflictException(
            String.format(
                "A change with Change-Id %s already exists for this branch.", changeId.get()));
      }
    }

    if (input.topic != null) {
      input.topic = Strings.emptyToNull(input.topic.trim());
    }

    if (input.status != null && input.status != ChangeStatus.NEW) {
      throw new BadRequestException("unsupported change status");
    }

    if (input.baseChange != null && input.baseCommit != null) {
      throw new BadRequestException("only provide one of base_change or base_commit");
    }

    ProjectResource projectResource = projectsCollection.parse(input.project);
    // Checks whether the change to be created should be a private change.
    boolean privateByDefault =
        projectResource.getProjectState().is(BooleanProjectConfig.PRIVATE_BY_DEFAULT);
    boolean isPrivate = input.isPrivate == null ? privateByDefault : input.isPrivate;
    if (isPrivate && disablePrivateChanges) {
      throw new MethodNotAllowedException("private changes are disabled");
    }
    input.isPrivate = isPrivate;

    ProjectState projectState = projectResource.getProjectState();

    if (input.workInProgress == null) {
      if (projectState.is(BooleanProjectConfig.WORK_IN_PROGRESS_BY_DEFAULT)) {
        input.workInProgress = true;
      } else {
        input.workInProgress =
            firstNonNull(me.state().generalPreferences().workInProgressByDefault, false);
      }
    }

    if (input.merge != null) {
      if (!(submitType.equals(SubmitType.MERGE_ALWAYS)
          || submitType.equals(SubmitType.MERGE_IF_NECESSARY))) {
        throw new BadRequestException("Submit type: " + submitType + " is not supported");
      }
    }

    if (input.merge != null && input.patch != null) {
      throw new BadRequestException("Only one of `merge` and `patch` arguments can be set.");
    }

    if ((input.merge != null || input.patch != null) && commitTreeSupplier.isPresent()) {
      throw new BadRequestException(
          "`CommitTreeSupplier` cannot be provided along with `merge` or `patch` arguments");
    }

    if (input.author != null
        && (Strings.isNullOrEmpty(input.author.email)
            || Strings.isNullOrEmpty(input.author.name))) {
      throw new BadRequestException("Author must specify name and email");
    }
  }

  /** Changes are allowed to be created on any ref that is not Gerrit internal or a tag ref. */
  private boolean isBranchAllowed(String branch) {
    return !RefNames.isGerritRef(branch) && !branch.startsWith(RefNames.REFS_TAGS);
  }

  private void checkRequiredPermissions(
      Project.NameKey project, String refName, @Nullable AccountInput author)
      throws ResourceNotFoundException, AuthException, PermissionBackendException {
    PermissionBackend.ForRef forRef = permissionBackend.currentUser().project(project).ref(refName);
    if (!forRef.test(RefPermission.READ)) {
      throw new ResourceNotFoundException(String.format("ref %s not found", refName));
    }
    forRef.check(RefPermission.CREATE_CHANGE);
    if (author != null) {
      forRef.check(RefPermission.FORGE_AUTHOR);
    }
  }

  private ChangeInfo createNewChange(
      ChangeInput input,
      IdentifiedUser me,
      ProjectState projectState,
      BatchUpdate.Factory updateFactory,
      Optional<CommitTreeSupplier> commitTreeSupplier)
      throws RestApiException, PermissionBackendException, IOException, ConfigInvalidException,
          UpdateException {
    try (RefUpdateContext ctx = RefUpdateContext.open(CHANGE_MODIFICATION)) {
      logger.atFine().log(
          "Creating new change for target branch %s in project %s"
              + " (new branch = %s, base change = %s, base commit = %s)",
          input.branch,
          projectState.getName(),
          input.newBranch,
          input.baseChange,
          input.baseCommit);

      try (Repository git = gitManager.openRepository(projectState.getNameKey());
          ObjectInserter oi = git.newObjectInserter();
          ObjectReader reader = oi.newReader();
          CodeReviewRevWalk rw = CodeReviewCommit.newRevWalk(reader)) {
        PatchSet basePatchSet = null;
        List<String> groups = Collections.emptyList();

        if (input.baseChange != null) {
          ChangeNotes baseChange = getBaseChange(input.baseChange);
          basePatchSet = psUtil.current(baseChange);
          groups = basePatchSet.groups();
          logger.atFine().log("base patch set = %s (groups = %s)", basePatchSet.id(), groups);
        }

        ObjectId parentCommit =
            getParentCommit(
                git,
                rw,
                input.branch,
                input.newBranch,
                basePatchSet,
                input.baseCommit,
                input.merge);
        logger.atFine().log(
            "parent commit = %s", parentCommit != null ? parentCommit.name() : "NULL");

        RevCommit mergeTip = parentCommit == null ? null : rw.parseCommit(parentCommit);

        Instant now = TimeUtil.now();

        PersonIdent committer = me.newCommitterIdent(now, serverZoneId);
        PersonIdent author =
            input.author == null
                ? committer
                : new PersonIdent(input.author.name, input.author.email, now, serverZoneId);

        String commitMessage = getCommitMessage(input.subject, me);

        CodeReviewCommit c;
        if (input.merge != null) {
          // create a merge commit
          c =
              newMergeCommit(
                  git,
                  oi,
                  rw,
                  projectState,
                  mergeTip,
                  input.merge,
                  author,
                  committer,
                  commitMessage);
          if (!c.getFilesWithGitConflicts().isEmpty()) {
            logger.atFine().log(
                "merge commit has conflicts in the following files: %s",
                c.getFilesWithGitConflicts());
          }
        } else if (input.patch != null) {
          // create a commit with the given patch.
          c =
              createCommitWithPatch(
                  git, reader, oi, rw, mergeTip, input.patch, input.subject, author, committer, me);
        } else if (commitTreeSupplier.isPresent()) {
          c =
              createCommitWithSuppliedTree(
                  git,
                  oi,
                  reader,
                  rw,
                  mergeTip,
                  input,
                  commitTreeSupplier.get(),
                  author,
                  committer,
                  commitMessage);

        } else {
          // create an empty commit.
          c = createEmptyCommit(oi, rw, author, committer, mergeTip, commitMessage);
        }
        // Flush inserter so that commit becomes visible to validators
        logger.atFine().log("flushing inserter %s", oi);
        oi.flush();

        Change.Id changeId = Change.id(seq.nextChangeId());
        ChangeInserter ins = changeInserterFactory.create(changeId, c, input.branch);
        ins.setMessage(messageForNewChange(ins.getPatchSetId(), c));
        ins.setTopic(input.topic);
        ins.setPrivate(input.isPrivate);
        ins.setWorkInProgress(input.workInProgress || !c.getFilesWithGitConflicts().isEmpty());
        ins.setGroups(groups);

        if (input.validationOptions != null) {
          ImmutableListMultimap.Builder<String, String> validationOptions =
              ImmutableListMultimap.builder();
          input
              .validationOptions
              .entrySet()
              .forEach(e -> validationOptions.put(e.getKey(), e.getValue()));
          ins.setValidationOptions(validationOptions.build());
        }

        if (input.customKeyedValues != null) {
          ImmutableMap.Builder<String, String> customKeyedValues = ImmutableMap.builder();
          input
              .customKeyedValues
              .entrySet()
              .forEach(e -> customKeyedValues.put(e.getKey(), e.getValue()));
          ins.setCustomKeyedValues(customKeyedValues.build());
        }

        try (BatchUpdate bu = updateFactory.create(projectState.getNameKey(), me, now)) {
          bu.setRepository(git, rw, oi);
          bu.setNotify(
              notifyResolver.resolve(
                  firstNonNull(input.notify, NotifyHandling.ALL), input.notifyDetails));
          bu.insertChange(ins);
          bu.execute();
        }
        List<ListChangesOption> opts = input.responseFormatOptions;
        if (opts == null) {
          opts = ImmutableList.of();
        }
        ChangeInfo changeInfo = jsonFactory.create(opts).format(ins.getChange());
        changeInfo.containsGitConflicts = !c.getFilesWithGitConflicts().isEmpty() ? true : null;
        return changeInfo;
      } catch (InvalidMergeStrategyException | MergeWithConflictsNotSupportedException e) {
        throw new BadRequestException(e.getMessage());
      }
    }
  }

  private ChangeNotes getBaseChange(String baseChange)
      throws UnprocessableEntityException, PermissionBackendException {
    List<ChangeNotes> notes = changeFinder.find(baseChange);
    if (notes.size() != 1) {
      throw new UnprocessableEntityException("Base change not found: " + baseChange);
    }
    ChangeNotes change = Iterables.getOnlyElement(notes);
    try {
      permissionBackend.currentUser().change(change).check(ChangePermission.READ);
    } catch (AuthException e) {
      throw new UnprocessableEntityException("Read not permitted for " + baseChange, e);
    }

    return change;
  }

  @Nullable
  private ObjectId getParentCommit(
      Repository repo,
      RevWalk revWalk,
      String inputBranch,
      @Nullable Boolean newBranch,
      @Nullable PatchSet basePatchSet,
      @Nullable String baseCommit,
      @Nullable MergeInput mergeInput)
      throws BadRequestException, IOException, UnprocessableEntityException,
          ResourceConflictException {
    if (basePatchSet != null) {
      return basePatchSet.commitId();
    }

    Ref destRef = repo.getRefDatabase().exactRef(inputBranch);
    ObjectId parentCommit;
    if (baseCommit != null) {
      try {
        parentCommit = ObjectId.fromString(baseCommit);
      } catch (InvalidObjectIdException e) {
        throw new UnprocessableEntityException(
            String.format("Base %s doesn't represent a valid SHA-1", baseCommit), e);
      }

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

      if (destRef == null) {
        throw new BadRequestException("Destination branch does not exist");
      }
      RevCommit destRefRevCommit = revWalk.parseCommit(destRef.getObjectId());

      if (!revWalk.isMergedInto(parentRevCommit, destRefRevCommit)) {
        throw new BadRequestException(
            String.format("Commit %s doesn't exist on ref %s", baseCommit, inputBranch));
      }
    } else {
      if (destRef != null) {
        if (Boolean.TRUE.equals(newBranch)) {
          throw new ResourceConflictException(
              String.format("Branch %s already exists.", inputBranch));
        }
        parentCommit = destRef.getObjectId();
      } else {
        if (Boolean.TRUE.equals(newBranch)) {
          if (mergeInput != null) {
            throw new BadRequestException("Cannot create merge: destination branch does not exist");
          }
          parentCommit = null;
        } else {
          throw new BadRequestException(
              String.format("Destination branch does not exist %s", inputBranch));
        }
      }
    }

    return parentCommit;
  }

  private Optional<String> getChangeIdFromMessage(String subject) {
    int indexOfChangeId = ChangeIdUtil.indexOfChangeId(subject, "\n");
    if (indexOfChangeId == -1) {
      return Optional.empty();
    }
    return Optional.of(
        subject.substring(
            indexOfChangeId + 11 /* "Change-Id: "*/,
            indexOfChangeId + 12 /* "Change-Id: I" */ + Constants.OBJECT_ID_STRING_LENGTH));
  }

  private String getCommitMessage(String subject, IdentifiedUser me) {
    // Add a Change-Id line if there isn't already one
    String commitMessage = subject;
    if (ChangeIdUtil.indexOfChangeId(commitMessage, "\n") == -1) {
      ObjectId id = CommitMessageUtil.generateChangeId();
      commitMessage = ChangeIdUtil.insertId(commitMessage, id);
    }

    if (Boolean.TRUE.equals(me.state().generalPreferences().signedOffBy)) {
      commitMessage =
          Joiner.on("\n")
              .join(
                  commitMessage.trim(),
                  String.format(
                      "%s%s",
                      SIGNED_OFF_BY_TAG, me.state().account().getNameEmail(anonymousCowardName)));
    }

    return commitMessage;
  }

  private static CodeReviewCommit createEmptyCommit(
      ObjectInserter oi,
      CodeReviewRevWalk rw,
      PersonIdent authorIdent,
      PersonIdent committerIdent,
      @Nullable RevCommit mergeTip,
      String commitMessage)
      throws IOException {
    logger.atFine().log("Creating empty commit (mergeTip = %s)", mergeTip);
    ObjectId treeId = mergeTip == null ? emptyTreeId(oi) : mergeTip.getTree().getId();
    logger.atFine().log("Tree ID of empty commit: %s", treeId.name());
    List<RevCommit> parents = mergeTip == null ? ImmutableList.of() : ImmutableList.of(mergeTip);
    return rw.parseCommit(
        CommitUtil.createCommitWithTree(
            oi, authorIdent, committerIdent, parents, commitMessage, treeId));
  }

  private CodeReviewCommit createCommitWithPatch(
      Repository repo,
      ObjectReader reader,
      ObjectInserter oi,
      CodeReviewRevWalk rw,
      RevCommit mergeTip,
      ApplyPatchInput patch,
      String subject,
      PersonIdent authorIdent,
      PersonIdent committerIdent,
      IdentifiedUser me)
      throws IOException, RestApiException {
    if (mergeTip == null) {
      throw new BadRequestException("Cannot apply patch on top of an empty tree.");
    }
    PatchApplier.Result applyResult = ApplyPatchUtil.applyPatch(repo, oi, patch, mergeTip);
    ObjectId treeId = applyResult.getTreeId();
    logger.atFine().log("tree ID after applying patch: %s", treeId.name());
    String appliedPatchCommitMessage =
        getCommitMessage(
            ApplyPatchUtil.buildCommitMessage(
                subject,
                ImmutableList.of(),
                patch.patch,
                ApplyPatchUtil.getResultPatch(repo, reader, mergeTip, rw.lookupTree(treeId)),
                applyResult.getErrors()),
            me);
    return rw.parseCommit(
        CommitUtil.createCommitWithTree(
            oi,
            authorIdent,
            committerIdent,
            ImmutableList.of(mergeTip),
            appliedPatchCommitMessage,
            treeId));
  }

  private static CodeReviewCommit createCommitWithSuppliedTree(
      Repository repo,
      ObjectInserter oi,
      ObjectReader or,
      CodeReviewRevWalk rw,
      RevCommit mergeTip,
      ChangeInput input,
      CommitTreeSupplier commitTreeSupplier,
      PersonIdent authorIdent,
      PersonIdent committerIdent,
      String commitMessage)
      throws IOException, RestApiException {
    if (mergeTip == null) {
      throw new BadRequestException("`CommitTreeSupplier` cannot be used on top of an empty tree.");
    }
    ObjectId treeId = commitTreeSupplier.get(repo, oi, or, input, mergeTip);
    return rw.parseCommit(
        CommitUtil.createCommitWithTree(
            oi, authorIdent, committerIdent, ImmutableList.of(mergeTip), commitMessage, treeId));
  }

  private static ObjectId emptyTreeId(ObjectInserter inserter) throws IOException {
    return inserter.insert(new TreeFormatter());
  }

  private CodeReviewCommit newMergeCommit(
      Repository repo,
      ObjectInserter oi,
      CodeReviewRevWalk rw,
      ProjectState projectState,
      RevCommit mergeTip,
      MergeInput merge,
      PersonIdent authorIdent,
      PersonIdent committerIdent,
      String commitMessage)
      throws RestApiException, IOException {
    logger.atFine().log(
        "Creating merge commit: source = %s, strategy = %s, allowConflicts = %s",
        merge.source, merge.strategy, merge.allowConflicts);

    if (Strings.isNullOrEmpty(merge.source)) {
      throw new BadRequestException("merge.source must be non-empty");
    }

    RevCommit sourceCommit = MergeUtil.resolveCommit(repo, rw, merge.source);
    if (merge.sourceBranch != null) {
      Ref ref = repo.findRef(merge.sourceBranch);
      logger.atFine().log("checking visibility for branch %s", merge.sourceBranch);
      if (ref == null || !commits.canRead(projectState, repo, sourceCommit, ref)) {
        throw new BadRequestException("do not have read permission for: " + merge.source);
      }
    } else if (!commits.canRead(projectState, repo, sourceCommit)) {
      throw new BadRequestException("do not have read permission for: " + merge.source);
    }

    MergeUtil mergeUtil = mergeUtilFactory.create(projectState);
    // default merge strategy from project settings
    String mergeStrategy =
        firstNonNull(Strings.emptyToNull(merge.strategy), mergeUtil.mergeStrategyName());
    logger.atFine().log("merge strategy = %s", mergeStrategy);

    try {
      CodeReviewCommit mergeCommit =
          MergeUtil.createMergeCommit(
              oi,
              repo.getConfig(),
              mergeTip,
              sourceCommit,
              mergeStrategy,
              merge.allowConflicts,
              authorIdent,
              committerIdent,
              commitMessage,
              rw);
      logger.atFine().log("tree ID of merge commit: %s", mergeCommit.getTree().getId().name());
      return mergeCommit;
    } catch (NoMergeBaseException e) {
      throw new ResourceConflictException(
          String.format("Cannot create merge commit: %s", e.getMessage()), e);
    }
  }

  private static String messageForNewChange(PatchSet.Id patchSetId, CodeReviewCommit commit) {
    StringBuilder stringBuilder =
        new StringBuilder(String.format("Uploaded patch set %s.", patchSetId.get()));

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

    return stringBuilder.toString();
  }
}
