Ejemplo n.º 1
0
  public CodeReviewCommit createCherryPickFromCommit(
      Repository repo,
      ObjectInserter inserter,
      RevCommit mergeTip,
      RevCommit originalCommit,
      PersonIdent cherryPickCommitterIdent,
      String commitMsg,
      CodeReviewRevWalk rw)
      throws MissingObjectException, IncorrectObjectTypeException, IOException,
          MergeIdenticalTreeException, MergeConflictException {

    final ThreeWayMerger m = newThreeWayMerger(repo, inserter);

    m.setBase(originalCommit.getParent(0));
    if (m.merge(mergeTip, originalCommit)) {
      ObjectId tree = m.getResultTreeId();
      if (tree.equals(mergeTip.getTree())) {
        throw new MergeIdenticalTreeException("identical tree");
      }

      CommitBuilder mergeCommit = new CommitBuilder();
      mergeCommit.setTreeId(tree);
      mergeCommit.setParentId(mergeTip);
      mergeCommit.setAuthor(originalCommit.getAuthorIdent());
      mergeCommit.setCommitter(cherryPickCommitterIdent);
      mergeCommit.setMessage(commitMsg);
      return rw.parseCommit(commit(inserter, mergeCommit));
    } else {
      throw new MergeConflictException("merge conflict");
    }
  }
    @Override
    public ChangeKind load(Key key) throws IOException {
      if (Objects.equal(key.prior, key.next)) {
        return ChangeKind.NO_CODE_CHANGE;
      }

      RevWalk walk = new RevWalk(key.repo);
      try {
        RevCommit prior = walk.parseCommit(key.prior);
        walk.parseBody(prior);
        RevCommit next = walk.parseCommit(key.next);
        walk.parseBody(next);

        if (!next.getFullMessage().equals(prior.getFullMessage())) {
          if (next.getTree() == prior.getTree() && isSameParents(prior, next)) {
            return ChangeKind.NO_CODE_CHANGE;
          } else {
            return ChangeKind.REWORK;
          }
        }

        if (prior.getParentCount() != 1 || next.getParentCount() != 1) {
          // Trivial rebases done by machine only work well on 1 parent.
          return ChangeKind.REWORK;
        }

        if (next.getTree() == prior.getTree() && isSameParents(prior, next)) {
          return ChangeKind.TRIVIAL_REBASE;
        }

        // A trivial rebase can be detected by looking for the next commit
        // having the same tree as would exist when the prior commit is
        // cherry-picked onto the next commit's new first parent.
        ThreeWayMerger merger =
            MergeUtil.newThreeWayMerger(
                key.repo, MergeUtil.createDryRunInserter(), key.strategyName);
        merger.setBase(prior.getParent(0));
        if (merger.merge(next.getParent(0), prior)
            && merger.getResultTreeId().equals(next.getTree())) {
          return ChangeKind.TRIVIAL_REBASE;
        } else {
          return ChangeKind.REWORK;
        }
      } finally {
        key.repo = null;
        walk.release();
      }
    }
Ejemplo n.º 3
0
  public boolean canCherryPick(
      MergeSorter mergeSorter,
      Repository repo,
      CodeReviewCommit mergeTip,
      CodeReviewRevWalk rw,
      CodeReviewCommit toMerge)
      throws IntegrationException {
    if (mergeTip == null) {
      // The branch is unborn. Fast-forward is possible.
      //
      return true;
    }

    if (toMerge.getParentCount() == 0) {
      // Refuse to merge a root commit into an existing branch,
      // we cannot obtain a delta for the cherry-pick to apply.
      //
      return false;
    }

    if (toMerge.getParentCount() == 1) {
      // If there is only one parent, a cherry-pick can be done by
      // taking the delta relative to that one parent and redoing
      // that on the current merge tip.
      //
      try {
        ThreeWayMerger m = newThreeWayMerger(repo, createDryRunInserter(repo));
        m.setBase(toMerge.getParent(0));
        return m.merge(mergeTip, toMerge);
      } catch (IOException e) {
        throw new IntegrationException("Cannot merge " + toMerge.name(), e);
      }
    }

    // There are multiple parents, so this is a merge commit. We
    // don't want to cherry-pick the merge as clients can't easily
    // rebase their history with that merge present and replaced
    // by an equivalent merge with a different first parent. So
    // instead behave as though MERGE_IF_NECESSARY was configured.
    //
    return canFastForward(mergeSorter, mergeTip, rw, toMerge)
        || canMerge(mergeSorter, repo, mergeTip, toMerge);
  }