Browse Source

Implemented merge for parallel delete/modification

Duplicates cgit behaviour for merging the case where
OURS is deleted and THEIRS is modified as well as
OURS is modified and THEIRS id deleted.

Change-Id: Ia2ab4f8dc95020f2914ff01c2bf3b1bc62a9d45d
Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
stable-1.0
Bernard Leach 14 years ago committed by Chris Aniszczyk
parent
commit
98b019f4bd
  1. 63
      org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
  2. 2
      org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java
  3. 23
      org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java

63
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java

@ -587,6 +587,69 @@ public class MergeCommandTest extends RepositoryTestCase {
assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
}
@Test
public void testDeletionOnMasterConflict() throws Exception {
Git git = new Git(db);
writeTrashFile("a", "1\na\n3\n");
writeTrashFile("b", "1\nb\n3\n");
git.add().addFilepattern("a").addFilepattern("b").call();
RevCommit initialCommit = git.commit().setMessage("initial").call();
// create side branch and modify "a"
createBranch(initialCommit, "refs/heads/side");
checkoutBranch("refs/heads/side");
writeTrashFile("a", "1\na(side)\n3\n");
git.add().addFilepattern("a").call();
RevCommit secondCommit = git.commit().setMessage("side").call();
// delete a on master to generate conflict
checkoutBranch("refs/heads/master");
git.rm().addFilepattern("a").call();
git.commit().setMessage("main").call();
// merge side with master
MergeResult result = git.merge().include(secondCommit.getId())
.setStrategy(MergeStrategy.RESOLVE).call();
assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
// result should be 'a' conflicting with workspace content from side
assertTrue(new File(db.getWorkTree(), "a").exists());
assertEquals("1\na(side)\n3\n", read(new File(db.getWorkTree(), "a")));
assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
}
@Test
public void testDeletionOnSideConflict() throws Exception {
Git git = new Git(db);
writeTrashFile("a", "1\na\n3\n");
writeTrashFile("b", "1\nb\n3\n");
git.add().addFilepattern("a").addFilepattern("b").call();
RevCommit initialCommit = git.commit().setMessage("initial").call();
// create side branch and delete "a"
createBranch(initialCommit, "refs/heads/side");
checkoutBranch("refs/heads/side");
git.rm().addFilepattern("a").call();
RevCommit secondCommit = git.commit().setMessage("side").call();
// update a on master to generate conflict
checkoutBranch("refs/heads/master");
writeTrashFile("a", "1\na(main)\n3\n");
git.add().addFilepattern("a").call();
git.commit().setMessage("main").call();
// merge side with master
MergeResult result = git.merge().include(secondCommit.getId())
.setStrategy(MergeStrategy.RESOLVE).call();
assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
assertTrue(new File(db.getWorkTree(), "a").exists());
assertEquals("1\na(main)\n3\n", read(new File(db.getWorkTree(), "a")));
assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
}
@Test
public void testMergeFailingWithDirtyWorkingTree() throws Exception {
Git git = new Git(db);

2
org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java

@ -138,7 +138,7 @@ public class DirCacheCheckoutTest extends ReadTreeTest {
assertEquals(MergeStatus.CONFLICTING, git.merge().include(master)
.call().getMergeStatus());
assertEquals(
"[E/h, mode:100644][G/i, mode:100644][f, mode:100644, stage:1][f, mode:100644, stage:2][f, mode:100644, stage:3]",
"[D/g, mode:100644, stage:1][D/g, mode:100644, stage:3][E/h, mode:100644][G/i, mode:100644][f, mode:100644, stage:1][f, mode:100644, stage:2][f, mode:100644, stage:3]",
indexState(0));
resetHard(master);

23
org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java

@ -452,6 +452,29 @@ public class ResolveMerger extends ThreeWayMerger {
unmergedPaths.add(tw.getPathString());
}
modifiedFiles.add(tw.getPathString());
} else if (modeO != modeT) {
// OURS or THEIRS has been deleted
if (((modeO != 0 && !tw.idEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw
.idEqual(T_BASE, T_THEIRS)))) {
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1);
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2);
DirCacheEntry e = add(tw.getRawPath(), theirs,
DirCacheEntry.STAGE_3);
// OURS was deleted checkout THEIRS
if (modeO == 0) {
// Check worktree before checking out THEIRS
if (isWorktreeDirty())
return false;
if (nonTree(modeT)) {
if (e != null)
toBeCheckedOut.put(tw.getPathString(), e);
}
}
unmergedPaths.add(tw.getPathString());
}
}
return true;
}

Loading…
Cancel
Save