summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorBernard Leach2011-04-29 05:37:00 (EDT)
committer Chris Aniszczyk2011-05-03 13:11:52 (EDT)
commit98b019f4bdc45bd122e4d81009c4e814350e051c (patch)
treea6b3198d29e4a5557f1757ce21fb53517fd762fd
parent04df086d3e2564b06d2a462449942fcf6e71421b (diff)
downloadjgit-98b019f4bdc45bd122e4d81009c4e814350e051c.zip
jgit-98b019f4bdc45bd122e4d81009c4e814350e051c.tar.gz
jgit-98b019f4bdc45bd122e4d81009c4e814350e051c.tar.bz2
Implemented merge for parallel delete/modificationrefs/changes/94/3294/2
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>
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java63
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutTest.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java23
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 d5c0025..9e75882 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 160eb65..9fb4b3e 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 cf96910..8758427 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;
}