]> source.dussan.org Git - jgit.git/commitdiff
Implemented merge for parallel delete/modification 94/3294/2
authorBernard Leach <leachbj@bouncycastle.org>
Fri, 29 Apr 2011 09:37:00 +0000 (19:37 +1000)
committerChris Aniszczyk <caniszczyk@gmail.com>
Tue, 3 May 2011 17:11:52 +0000 (12:11 -0500)
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>
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java
org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java

index d5c00257bbc1abbabe88362a816d9afe589530d5..9e75882349343deef2bf87b136636b7cfef3f688 100644 (file)
@@ -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);
index 160eb653b5b0346ca7c08705816f0c3a8ba4476b..9fb4b3e17df89dbe839b17e3b0ba331c665833f7 100644 (file)
@@ -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);
index cf969107d88a0762eceee03532b72a10d56a5b88..8758427583947b26c00f083f3eb87f8ca92e0a27 100644 (file)
@@ -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;
        }