diff options
author | Shawn O. Pearce <sop@google.com> | 2009-07-18 18:32:00 -0700 |
---|---|---|
committer | Shawn O. Pearce <sop@google.com> | 2009-07-18 18:32:00 -0700 |
commit | 101794c63ef553c19ea03f407792e6f1656a28f8 (patch) | |
tree | 1c285702729a67438bb6a903fbf30a3898a9d202 | |
parent | de24c39e6c709cd3753dcbc47eff4978313234d8 (diff) |
Don't crash the submit queue when a change is a criss-cross merge
A criss-cross merge occurs when two branches have merged in both
directions and there are now multiple candidate merge bases for
the merge between the change and the branch head. (For more on
this see http://revctrl.org/CrissCrossMerge.)
If JGit finds multiple merge bases, it throws an IOException. If
we catch this and mark a special status code, we can unsubmit the
change and let the user know about the problem by reporting it as
a message on the change, just like we do with path conflicts.
Bug: GERRIT-171
Signed-off-by: Shawn O. Pearce <sop@google.com>
-rw-r--r-- | src/main/java/com/google/gerrit/git/CommitMergeStatus.java | 5 | ||||
-rw-r--r-- | src/main/java/com/google/gerrit/git/MergeOp.java | 50 |
2 files changed, 41 insertions, 14 deletions
diff --git a/src/main/java/com/google/gerrit/git/CommitMergeStatus.java b/src/main/java/com/google/gerrit/git/CommitMergeStatus.java index e1ca173308..4fa71de5cb 100644 --- a/src/main/java/com/google/gerrit/git/CommitMergeStatus.java +++ b/src/main/java/com/google/gerrit/git/CommitMergeStatus.java @@ -34,5 +34,8 @@ enum CommitMergeStatus { NO_PATCH_SET, /** */ - REVISION_GONE; + REVISION_GONE, + + /** */ + CRISS_CROSS_MERGE; } diff --git a/src/main/java/com/google/gerrit/git/MergeOp.java b/src/main/java/com/google/gerrit/git/MergeOp.java index 53694d850a..81869b9fa2 100644 --- a/src/main/java/com/google/gerrit/git/MergeOp.java +++ b/src/main/java/com/google/gerrit/git/MergeOp.java @@ -342,23 +342,38 @@ public class MergeOp { writeMergeCommit(m, n); } else { - rw.reset(); - rw.markStart(n); - rw.markUninteresting(mergeTip); - CodeReviewCommit failed; - while ((failed = (CodeReviewCommit) rw.next()) != null) { - if (failed.patchsetId == null) { - continue; - } - - failed.statusCode = CommitMergeStatus.PATH_CONFLICT; - status.put(failed.patchsetId.getParentKey(), failed.statusCode); - } + failed(n, CommitMergeStatus.PATH_CONFLICT); } } catch (IOException e) { - throw new MergeException("Cannot merge " + n.name(), e); + if (e.getMessage().startsWith("Multiple merge bases for")) { + try { + failed(n, CommitMergeStatus.CRISS_CROSS_MERGE); + } catch (IOException e2) { + throw new MergeException("Cannot merge " + n.name(), e); + } + } else { + throw new MergeException("Cannot merge " + n.name(), e); + } + } + } + } + + private CodeReviewCommit failed(final CodeReviewCommit n, + final CommitMergeStatus failure) throws MissingObjectException, + IncorrectObjectTypeException, IOException { + rw.reset(); + rw.markStart(n); + rw.markUninteresting(mergeTip); + CodeReviewCommit failed; + while ((failed = (CodeReviewCommit) rw.next()) != null) { + if (failed.patchsetId == null) { + continue; } + + failed.statusCode = failure; + status.put(failed.patchsetId.getParentKey(), failed.statusCode); } + return failed; } private void writeMergeCommit(final Merger m, final CodeReviewCommit n) @@ -749,6 +764,15 @@ public class MergeOp { break; } + case CRISS_CROSS_MERGE: { + final String txt = + "Your change requires a recursive merge to resolve.\n" + + "\n" + + "Please merge (or rebase) the change locally and upload the resolution for review."; + setNew(c, message(c, txt)); + break; + } + case MISSING_DEPENDENCY: { ChangeMessage msg = null; try { |