From af40635aba91a78ec248503906996ca89898e888 Mon Sep 17 00:00:00 2001 From: Christian Halstrick Date: Thu, 28 Nov 2013 18:00:36 +0100 Subject: [PATCH] Fix handling of file/folder conflicts during a checkout JGit was not handling certain file/folder conflicts during a checkout correctly. This was reported by Axel Richard in http://dev.eclipse.org/mhonarc/lists/jgit-dev/msg02358.html. This commit fixes this problem. Still JGit behaves intentionally different than native git. If HEAD contains a tree, and workingtree, Index and Merge contain a file with same content ... then JGit allows a conflict free checkout of Merge. Native git always complains that it doesn't want to overwrite local changes. But there is no need to update the working tree because Index and Merge are already equal. A shell script which shows how native git behaves can be found here. https://gist.github.com/chalstrick/7694959#file-gistfile1-sh Change-Id: Ifd6a68974d61cd4fa23bc575f3a40773db66cafc Signed-off-by: Christian Halstrick --- .../jgit/lib/DirCacheCheckoutTest.java | 25 +++++++++++++++++++ .../jgit/dircache/DirCacheCheckout.java | 8 +++++- 2 files changed, 32 insertions(+), 1 deletion(-) 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 cb2ae64db..98ec706be 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 @@ -467,7 +467,9 @@ private void assertAllEmpty() { *3 D F D Y N N Keep *4 D F D N N N Conflict *5 D F F Y N N Y Keep + *5b D F F Y N N N Conflict *6 D F F N N N Y Keep + *6b D F F N N N N Conflict *7 F D F Y Y N N Update *8 F D F N Y N N Conflict *9 F D F Y N N N Update @@ -540,7 +542,17 @@ public void testDirectoryFileConflicts_5() throws Exception { // 5 doit(mk("DF/DF"), mk("DF"), mk("DF")); assertRemoved("DF/DF"); + assertEquals(0, dco.getConflicts().size()); + assertEquals(0, dco.getUpdated().size()); + } + @Test + public void testDirectoryFileConflicts_5b() throws Exception { + // 5 + doit(mk("DF/DF"), mkmap("DF", "different"), mk("DF")); + assertRemoved("DF/DF"); + assertConflict("DF"); + assertEquals(0, dco.getUpdated().size()); } @Test @@ -550,6 +562,19 @@ public void testDirectoryFileConflicts_6() throws Exception { writeTrashFile("DF", "different"); go(); assertRemoved("DF/DF"); + assertEquals(0, dco.getConflicts().size()); + assertEquals(0, dco.getUpdated().size()); + } + + @Test + public void testDirectoryFileConflicts_6b() throws Exception { + // 6 + setupCase(mk("DF/DF"), mk("DF"), mkmap("DF", "different")); + writeTrashFile("DF", "again different"); + go(); + assertRemoved("DF/DF"); + assertConflict("DF"); + assertEquals(0, dco.getUpdated().size()); } @Test diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java index bd896864d..103d6183b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -555,7 +555,9 @@ void processEntry(CanonicalTreeParser h, CanonicalTreeParser m, * 3 D F D Y N N Keep * 4 D F D N N N Conflict * 5 D F F Y N N Y Keep + * 5b D F F Y N N N Conflict * 6 D F F N N N Y Keep + * 6b D F F N N N N Conflict * 7 F D F Y Y N N Update * 8 F D F N Y N N Conflict * 9 F D F Y N N N Update @@ -620,7 +622,11 @@ void processEntry(CanonicalTreeParser h, CanonicalTreeParser m, case 0xF0D: // 18 remove(name); break; - case 0xDFF: // 5 6 + case 0xDFF: // 5 5b 6 6b + if (equalIdAndMode(iId, iMode, mId, mMode)) + keep(dce); // 5 6 + else + conflict(name, dce, h, m); // 5b 6b case 0xFDD: // 10 11 // TODO: make use of tree extension as soon as available in jgit // we would like to do something like