diff options
| author | Bernard Leach | 2011-04-29 09:37:00 +0000 |
|---|---|---|
| committer | Chris Aniszczyk | 2011-05-03 17:11:52 +0000 |
| commit | 98b019f4bdc45bd122e4d81009c4e814350e051c (patch) | |
| tree | a6b3198d29e4a5557f1757ce21fb53517fd762fd | |
| parent | 04df086d3e2564b06d2a462449942fcf6e71421b (diff) | |
| download | jgit-98b019f4bdc45bd122e4d81009c4e814350e051c.tar.gz jgit-98b019f4bdc45bd122e4d81009c4e814350e051c.tar.xz jgit-98b019f4bdc45bd122e4d81009c4e814350e051c.zip | |
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>
3 files changed, 87 insertions, 1 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java index d5c00257bb..9e75882349 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java @@ -588,6 +588,69 @@ public class MergeCommandTest extends RepositoryTestCase { } @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); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java index 160eb653b5..9fb4b3e17d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java +++ b/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); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java index cf969107d8..8758427583 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java +++ b/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; } |
