|
|
@@ -44,6 +44,7 @@ package org.eclipse.jgit.merge; |
|
|
|
|
|
|
|
import static org.junit.Assert.assertEquals; |
|
|
|
import static org.junit.Assert.assertFalse; |
|
|
|
import static org.junit.Assert.assertTrue; |
|
|
|
|
|
|
|
import java.io.BufferedReader; |
|
|
|
import java.io.File; |
|
|
@@ -178,7 +179,7 @@ public class RecursiveMergerTest extends RepositoryTestCase { |
|
|
|
/** |
|
|
|
* 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 don't contain the same content. |
|
|
|
* contain branch specific conflict resolutions. Therefore m2 and s2 don't contain the same content. |
|
|
|
* |
|
|
|
* <pre> |
|
|
|
* m0--m1--m2 |
|
|
@@ -257,6 +258,183 @@ public class RecursiveMergerTest extends RepositoryTestCase { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Theory |
|
|
|
/** |
|
|
|
* Merging m2,s2 from the following topology. The same file is modified |
|
|
|
* in both branches. The modifications should be mergeable but only if the automerge of m1 and s1 |
|
|
|
* is choosen as parent. Choosing m0 as parent would not be sufficient (in contrast to the merge in |
|
|
|
* crissCrossMerge_mergeable). m2 and s2 contain branch specific conflict resolutions. Therefore m2 |
|
|
|
* and s2 don't contain the same content. |
|
|
|
* |
|
|
|
* <pre> |
|
|
|
* m0--m1--m2 |
|
|
|
* \ \/ |
|
|
|
* \ /\ |
|
|
|
* s1--s2 |
|
|
|
* </pre> |
|
|
|
*/ |
|
|
|
public void crissCrossMerge_mergeable2(MergeStrategy strategy, |
|
|
|
IndexState indexState, WorktreeState worktreeState) |
|
|
|
throws Exception { |
|
|
|
if (!validateStates(indexState, worktreeState)) |
|
|
|
return; |
|
|
|
|
|
|
|
BranchBuilder master = db_t.branch("master"); |
|
|
|
RevCommit m0 = master.commit().add("f", "1\n2\n3\n") |
|
|
|
.message("m0") |
|
|
|
.create(); |
|
|
|
RevCommit m1 = master.commit().add("f", "1-master\n2\n3\n") |
|
|
|
.message("m1").create(); |
|
|
|
db_t.getRevWalk().parseCommit(m1); |
|
|
|
|
|
|
|
BranchBuilder side = db_t.branch("side"); |
|
|
|
RevCommit s1 = side.commit().parent(m0).add("f", "1\n2\n3-side\n") |
|
|
|
.message("s1").create(); |
|
|
|
RevCommit s2 = side.commit().parent(m1) |
|
|
|
.add("f", "1-master\n2\n3-side-r\n") |
|
|
|
.message("s2(merge)") |
|
|
|
.create(); |
|
|
|
RevCommit m2 = master.commit().parent(s1) |
|
|
|
.add("f", "1-master-r\n2\n3-side\n") |
|
|
|
.message("m2(merge)") |
|
|
|
.create(); |
|
|
|
|
|
|
|
Git git = Git.wrap(db); |
|
|
|
git.checkout().setName("master").call(); |
|
|
|
modifyWorktree(worktreeState, "f", "side"); |
|
|
|
modifyIndex(indexState, "f", "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)) |
|
|
|
// index is dirty |
|
|
|
expectSuccess = false; |
|
|
|
else if (worktreeState == WorktreeState.DifferentFromHeadAndOther |
|
|
|
|| worktreeState == WorktreeState.SameAsOther) |
|
|
|
expectSuccess = false; |
|
|
|
assertEquals(Boolean.valueOf(expectSuccess), |
|
|
|
Boolean.valueOf(merger.merge(new RevCommit[] { m2, s2 }))); |
|
|
|
assertEquals(MergeStrategy.RECURSIVE, strategy); |
|
|
|
if (!expectSuccess) |
|
|
|
// if the merge was not successful skip testing the state of |
|
|
|
// index and workingtree |
|
|
|
return; |
|
|
|
assertEquals( |
|
|
|
"1-master-r\n2\n3-side-r", |
|
|
|
contentAsString(db, merger.getResultTreeId(), "f")); |
|
|
|
if (indexState != IndexState.Bare) |
|
|
|
assertEquals( |
|
|
|
"[f, mode:100644, content:1-master-r\n2\n3-side-r\n]", |
|
|
|
indexState(RepositoryTestCase.CONTENT)); |
|
|
|
if (worktreeState != WorktreeState.Bare |
|
|
|
&& worktreeState != WorktreeState.Missing) |
|
|
|
assertEquals( |
|
|
|
"1-master-r\n2\n3-side-r\n", |
|
|
|
read("f")); |
|
|
|
} 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 but only if the automerge of m1 and s1 |
|
|
|
* is choosen as parent. On both branches delete and modify files untouched on the other branch. |
|
|
|
* On both branches create new files. Make sure these files are correctly merged and |
|
|
|
* exist in the workingtree. |
|
|
|
* |
|
|
|
* <pre> |
|
|
|
* m0--m1--m2 |
|
|
|
* \ \/ |
|
|
|
* \ /\ |
|
|
|
* s1--s2 |
|
|
|
* </pre> |
|
|
|
*/ |
|
|
|
public void crissCrossMerge_checkOtherFiles(MergeStrategy strategy, |
|
|
|
IndexState indexState, WorktreeState worktreeState) |
|
|
|
throws Exception { |
|
|
|
if (!validateStates(indexState, worktreeState)) |
|
|
|
return; |
|
|
|
|
|
|
|
BranchBuilder master = db_t.branch("master"); |
|
|
|
RevCommit m0 = master.commit().add("f", "1\n2\n3\n").add("m.m", "0") |
|
|
|
.add("m.d", "0").add("s.m", "0").add("s.d", "0").message("m0") |
|
|
|
.create(); |
|
|
|
RevCommit m1 = master.commit().add("f", "1-master\n2\n3\n") |
|
|
|
.add("m.c", "0").add("m.m", "1").rm("m.d").message("m1") |
|
|
|
.create(); |
|
|
|
db_t.getRevWalk().parseCommit(m1); |
|
|
|
|
|
|
|
BranchBuilder side = db_t.branch("side"); |
|
|
|
RevCommit s1 = side.commit().parent(m0).add("f", "1\n2\n3-side\n") |
|
|
|
.add("s.c", "0").add("s.m", "1").rm("s.d").message("s1") |
|
|
|
.create(); |
|
|
|
RevCommit s2 = side.commit().parent(m1) |
|
|
|
.add("f", "1-master\n2\n3-side-r\n").add("m.m", "1") |
|
|
|
.add("m.c", "0").rm("m.d").message("s2(merge)").create(); |
|
|
|
RevCommit m2 = master.commit().parent(s1) |
|
|
|
.add("f", "1-master-r\n2\n3-side\n").add("s.m", "1") |
|
|
|
.add("s.c", "0").rm("s.d").message("m2(merge)").create(); |
|
|
|
|
|
|
|
Git git = Git.wrap(db); |
|
|
|
git.checkout().setName("master").call(); |
|
|
|
modifyWorktree(worktreeState, "f", "side"); |
|
|
|
modifyIndex(indexState, "f", "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)) |
|
|
|
// index is dirty |
|
|
|
expectSuccess = false; |
|
|
|
else if (worktreeState == WorktreeState.DifferentFromHeadAndOther |
|
|
|
|| worktreeState == WorktreeState.SameAsOther) |
|
|
|
expectSuccess = false; |
|
|
|
assertEquals(Boolean.valueOf(expectSuccess), |
|
|
|
Boolean.valueOf(merger.merge(new RevCommit[] { m2, s2 }))); |
|
|
|
assertEquals(MergeStrategy.RECURSIVE, strategy); |
|
|
|
if (!expectSuccess) |
|
|
|
// if the merge was not successful skip testing the state of |
|
|
|
// index and workingtree |
|
|
|
return; |
|
|
|
assertEquals( |
|
|
|
"1-master-r\n2\n3-side-r", |
|
|
|
contentAsString(db, merger.getResultTreeId(), "f")); |
|
|
|
if (indexState != IndexState.Bare) |
|
|
|
assertEquals( |
|
|
|
"[f, mode:100644, content:1-master-r\n2\n3-side-r\n][m.c, mode:100644, content:0][m.m, mode:100644, content:1][s.c, mode:100644, content:0][s.m, mode:100644, content:1]", |
|
|
|
indexState(RepositoryTestCase.CONTENT)); |
|
|
|
if (worktreeState != WorktreeState.Bare |
|
|
|
&& worktreeState != WorktreeState.Missing) { |
|
|
|
assertEquals( |
|
|
|
"1-master-r\n2\n3-side-r\n", |
|
|
|
read("f")); |
|
|
|
assertTrue(check("s.c")); |
|
|
|
assertFalse(check("s.d")); |
|
|
|
assertTrue(check("s.m")); |
|
|
|
assertTrue(check("m.c")); |
|
|
|
assertFalse(check("m.d")); |
|
|
|
assertTrue(check("m.m")); |
|
|
|
} |
|
|
|
} 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 |