summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce <sop@google.com>2009-07-18 18:32:00 -0700
committerShawn O. Pearce <sop@google.com>2009-07-18 18:32:00 -0700
commit101794c63ef553c19ea03f407792e6f1656a28f8 (patch)
tree1c285702729a67438bb6a903fbf30a3898a9d202
parentde24c39e6c709cd3753dcbc47eff4978313234d8 (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.java5
-rw-r--r--src/main/java/com/google/gerrit/git/MergeOp.java50
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 {