summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.test
diff options
context:
space:
mode:
authorChristian Halstrick <christian.halstrick@sap.com>2015-03-25 10:48:03 +0100
committerChristian Halstrick <christian.halstrick@sap.com>2015-03-25 10:49:58 +0100
commit2bd3556e7e1f07c4bb06282ead95a936758e388e (patch)
treee989b058ea85e7df88cc5c80b460fe5d9247d672 /org.eclipse.jgit.test
parentf1a15f7eb09183124ea645a8bfc16a03d58fd385 (diff)
downloadjgit-2bd3556e7e1f07c4bb06282ead95a936758e388e.tar.gz
jgit-2bd3556e7e1f07c4bb06282ead95a936758e388e.zip
Fix RecursiveMerger in case of multiple, independent base commits
When RecursiveMerger found that there are multiple base-commits for the commits to be merged it tries to temporarily merge the base commits. But if these base commits have no common predecessor there was a bug in JGit leading to a NPE. This commit fixes this by enforcing that an empty tree is used as base when merging two unrelated base commits. This logic was already there when merging two commits which have no common predecessor (ThreeWayMerger.mergeBase()). But the code which was computing a new temporary base commit in case of criss-cross merges didn't take care to pick an empty tree when no common predecessor can be found. Bug: 462671 Change-Id: Ibd96302f5f81383f36d3b1e3edcbf5822147b1a4
Diffstat (limited to 'org.eclipse.jgit.test')
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/RecursiveMergerTest.java63
1 files changed, 63 insertions, 0 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/RecursiveMergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/RecursiveMergerTest.java
index 37cc88be11..19e495b408 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/RecursiveMergerTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/RecursiveMergerTest.java
@@ -177,6 +177,69 @@ public class RecursiveMergerTest extends RepositoryTestCase {
@Theory
/**
+ * Merging m2,s2 from the following topology. m1 and s1 are the two root
+ * commits of the repo. In master and side different files are touched.
+ * No need to do a real content merge.
+ *
+ * <pre>
+ * m1--m2
+ * \/
+ * /\
+ * s1--s2
+ * </pre>
+ */
+ public void crissCrossMerge_twoRoots(MergeStrategy strategy,
+ IndexState indexState, WorktreeState worktreeState)
+ throws Exception {
+ if (!validateStates(indexState, worktreeState))
+ return;
+ // fill the repo
+ BranchBuilder master = db_t.branch("master");
+ BranchBuilder side = db_t.branch("side");
+ RevCommit m1 = master.commit().add("m", "m1").message("m1").create();
+ db_t.getRevWalk().parseCommit(m1);
+
+ RevCommit s1 = side.commit().add("s", "s1").message("s1").create();
+ RevCommit s2 = side.commit().parent(m1).add("m", "m1")
+ .message("s2(merge)").create();
+ RevCommit m2 = master.commit().parent(s1).add("s", "s1")
+ .message("m2(merge)").create();
+
+ Git git = Git.wrap(db);
+ git.checkout().setName("master").call();
+ modifyWorktree(worktreeState, "m", "side");
+ modifyWorktree(worktreeState, "s", "side");
+ modifyIndex(indexState, "m", "side");
+ modifyIndex(indexState, "s", "side");
+
+ ResolveMerger merger = (ResolveMerger) strategy.newMerger(db,
+ worktreeState == WorktreeState.Bare);
+ if (worktreeState != WorktreeState.Bare)
+ merger.setWorkingTreeIterator(new FileTreeIterator(db));
+ try {
+ boolean expectSuccess = true;
+ if (!(indexState == IndexState.Bare
+ || indexState == IndexState.Missing
+ || indexState == IndexState.SameAsHead || indexState == IndexState.SameAsOther))
+ // index is dirty
+ expectSuccess = false;
+
+ assertEquals(Boolean.valueOf(expectSuccess),
+ Boolean.valueOf(merger.merge(new RevCommit[] { m2, s2 })));
+ assertEquals(MergeStrategy.RECURSIVE, strategy);
+ assertEquals("m1",
+ contentAsString(db, merger.getResultTreeId(), "m"));
+ assertEquals("s1",
+ contentAsString(db, merger.getResultTreeId(), "s"));
+ } catch (NoMergeBaseException e) {
+ assertEquals(MergeStrategy.RESOLVE, strategy);
+ assertEquals(e.getReason(),
+ MergeBaseFailureReason.MULTIPLE_MERGE_BASES_NOT_SUPPORTED);
+ }
+ }
+
+ @Theory
+ /**
* Merging m2,s2 from the following topology. The same file is modified
* in both branches. The modifications should be mergeable. m2 and s2
* contain branch specific conflict resolutions. Therefore m2 and s2 don't contain the same content.