diff options
author | Christian Halstrick <christian.halstrick@sap.com> | 2016-06-17 16:41:14 +0200 |
---|---|---|
committer | Christian Halstrick <christian.halstrick@sap.com> | 2016-06-23 09:34:22 +0200 |
commit | 5fe44ed3ee025404dc34966ec996641f47f8490b (patch) | |
tree | 38cded9b222b7a4c832484d0a7ab3a123a811164 /org.eclipse.jgit | |
parent | 2ec3accb3bcc0bd45dfb1333511c72489ab835cb (diff) | |
download | jgit-5fe44ed3ee025404dc34966ec996641f47f8490b.tar.gz jgit-5fe44ed3ee025404dc34966ec996641f47f8490b.zip |
Fix DirCacheCheckout to return CheckoutConflictException
Problem occurs when the checkout wants to create a file 'd/f' but
the workingtree contains a dirty file 'd'. In order to create d/f the
file 'd' would have to be deleted and since the file is dirty that
content would be lost. This should lead to a CheckoutConflictException
for d/f when failOnConflict was set to true.
This fix also changes jgit checkout semantics to be more like native
gits checkout semantics. If during a checkout jgit wants to delete a
folder but finds that the working tree contains a dirty file at this
path then JGit will now throw an exception instead of silently keeping
the dirty file. Like in this example:
git init
touch b
git add b
git commit -m addB
mkdir a
touch a/c
git add a/c
git commit -m addAC
rm -fr a
touch a
git checkout HEAD~
Change-Id: I9089123179e09dd565285d50b0caa308d290cccd
Signed-off-by: RĂ¼diger Herrmann <ruediger.herrmann@gmx.de>
Also-by: RĂ¼diger Herrmann <ruediger.herrmann@gmx.de>
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java | 32 |
1 files changed, 28 insertions, 4 deletions
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 12ceb74abb..ab61c59378 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java @@ -718,10 +718,23 @@ public class DirCacheCheckout { return; } - // if we have no file at all then there is nothing to do - if ((ffMask & 0x222) == 0 - && (f == null || FileMode.TREE.equals(f.getEntryFileMode()))) - return; + if ((ffMask & 0x222) == 0) { + // HEAD, MERGE and index don't contain a file (e.g. all contain a + // folder) + if (f == null || FileMode.TREE.equals(f.getEntryFileMode())) { + // the workingtree entry doesn't exist or also contains a folder + // -> no problem + return; + } else { + // the workingtree entry exists and is not a folder + if (!idEqual(h, m)) { + // Because HEAD and MERGE differ we will try to update the + // workingtree with a folder -> return a conflict + conflict(name, null, null, null); + } + return; + } + } if ((ffMask == 0x00F) && f != null && FileMode.TREE.equals(f.getEntryFileMode())) { // File/Directory conflict case #20 @@ -1004,6 +1017,17 @@ public class DirCacheCheckout { } } + private static boolean idEqual(AbstractTreeIterator a, + AbstractTreeIterator b) { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + return a.getEntryObjectId().equals(b.getEntryObjectId()); + } + /** * A conflict is detected - add the three different stages to the index * @param path the path of the conflicting entry |