Beispiel #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();
      }
    }
Beispiel #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);
  }
Beispiel #4
0
  public boolean canMerge(
      final MergeSorter mergeSorter,
      final Repository repo,
      final CodeReviewCommit mergeTip,
      final CodeReviewCommit toMerge)
      throws IntegrationException {
    if (hasMissingDependencies(mergeSorter, toMerge)) {
      return false;
    }

    ThreeWayMerger m = newThreeWayMerger(repo, createDryRunInserter(repo));
    try {
      return m.merge(new AnyObjectId[] {mergeTip, toMerge});
    } catch (LargeObjectException e) {
      log.warn("Cannot merge due to LargeObjectException: " + toMerge.name());
      return false;
    } catch (NoMergeBaseException e) {
      return false;
    } catch (IOException e) {
      throw new IntegrationException("Cannot merge " + toMerge.name(), e);
    }
  }
Beispiel #5
0
 public CodeReviewCommit mergeOneCommit(
     PersonIdent author,
     PersonIdent committer,
     Repository repo,
     CodeReviewRevWalk rw,
     ObjectInserter inserter,
     RevFlag canMergeFlag,
     Branch.NameKey destBranch,
     CodeReviewCommit mergeTip,
     CodeReviewCommit n)
     throws IntegrationException {
   final ThreeWayMerger m = newThreeWayMerger(repo, inserter);
   try {
     if (m.merge(new AnyObjectId[] {mergeTip, n})) {
       return writeMergeCommit(
           author,
           committer,
           rw,
           inserter,
           canMergeFlag,
           destBranch,
           mergeTip,
           m.getResultTreeId(),
           n);
     } else {
       failed(rw, canMergeFlag, mergeTip, n, CommitMergeStatus.PATH_CONFLICT);
     }
   } catch (NoMergeBaseException e) {
     try {
       failed(rw, canMergeFlag, mergeTip, n, getCommitMergeStatus(e.getReason()));
     } catch (IOException e2) {
       throw new IntegrationException("Cannot merge " + n.name(), e);
     }
   } catch (IOException e) {
     throw new IntegrationException("Cannot merge " + n.name(), e);
   }
   return mergeTip;
 }