diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java
index 675331baf..e59b7c18d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java
@@ -120,11 +120,15 @@ public class NameConflictTreeWalkTest extends RepositoryTestCase {
tw.addTree(new DirCacheIterator(tree1));
assertModes("a", REGULAR_FILE, TREE, tw);
+ assertTrue(tw.isDirectoryFileConflict());
assertTrue(tw.isSubtree());
tw.enterSubtree();
assertModes("a/b", MISSING, REGULAR_FILE, tw);
+ assertTrue(tw.isDirectoryFileConflict());
assertModes("a.b", EXECUTABLE_FILE, MISSING, tw);
+ assertFalse(tw.isDirectoryFileConflict());
assertModes("a0b", SYMLINK, MISSING, tw);
+ assertFalse(tw.isDirectoryFileConflict());
}
public void testDF_GapByOne() throws Exception {
@@ -153,10 +157,14 @@ public class NameConflictTreeWalkTest extends RepositoryTestCase {
assertModes("a", REGULAR_FILE, TREE, tw);
assertTrue(tw.isSubtree());
+ assertTrue(tw.isDirectoryFileConflict());
tw.enterSubtree();
assertModes("a/b", MISSING, REGULAR_FILE, tw);
+ assertTrue(tw.isDirectoryFileConflict());
assertModes("a.b", EXECUTABLE_FILE, EXECUTABLE_FILE, tw);
+ assertFalse(tw.isDirectoryFileConflict());
assertModes("a0b", SYMLINK, MISSING, tw);
+ assertFalse(tw.isDirectoryFileConflict());
}
public void testDF_SkipsSeenSubtree() throws Exception {
@@ -185,10 +193,57 @@ public class NameConflictTreeWalkTest extends RepositoryTestCase {
assertModes("a", REGULAR_FILE, TREE, tw);
assertTrue(tw.isSubtree());
+ assertTrue(tw.isDirectoryFileConflict());
tw.enterSubtree();
assertModes("a/b", MISSING, REGULAR_FILE, tw);
+ assertTrue(tw.isDirectoryFileConflict());
assertModes("a.b", MISSING, EXECUTABLE_FILE, tw);
+ assertFalse(tw.isDirectoryFileConflict());
assertModes("a0b", SYMLINK, SYMLINK, tw);
+ assertFalse(tw.isDirectoryFileConflict());
+ }
+
+ public void testDF_DetectConflict() throws Exception {
+ final DirCache tree0 = db.readDirCache();
+ final DirCache tree1 = db.readDirCache();
+ {
+ final DirCacheBuilder b0 = tree0.builder();
+ final DirCacheBuilder b1 = tree1.builder();
+
+ b0.add(makeEntry("0", REGULAR_FILE));
+ b0.add(makeEntry("a", REGULAR_FILE));
+ b1.add(makeEntry("0", REGULAR_FILE));
+ b1.add(makeEntry("a.b", REGULAR_FILE));
+ b1.add(makeEntry("a/b", REGULAR_FILE));
+ b1.add(makeEntry("a/c/e", REGULAR_FILE));
+
+ b0.finish();
+ b1.finish();
+ assertEquals(2, tree0.getEntryCount());
+ assertEquals(4, tree1.getEntryCount());
+ }
+
+ final NameConflictTreeWalk tw = new NameConflictTreeWalk(db);
+ tw.reset();
+ tw.addTree(new DirCacheIterator(tree0));
+ tw.addTree(new DirCacheIterator(tree1));
+
+ assertModes("0", REGULAR_FILE, REGULAR_FILE, tw);
+ assertFalse(tw.isDirectoryFileConflict());
+ assertModes("a", REGULAR_FILE, TREE, tw);
+ assertTrue(tw.isSubtree());
+ assertTrue(tw.isDirectoryFileConflict());
+ tw.enterSubtree();
+ assertModes("a/b", MISSING, REGULAR_FILE, tw);
+ assertTrue(tw.isDirectoryFileConflict());
+ assertModes("a/c", MISSING, TREE, tw);
+ assertTrue(tw.isDirectoryFileConflict());
+ tw.enterSubtree();
+ assertModes("a/c/e", MISSING, REGULAR_FILE, tw);
+ assertTrue(tw.isDirectoryFileConflict());
+
+ assertModes("a.b", MISSING, REGULAR_FILE, tw);
+ assertFalse(tw.isDirectoryFileConflict());
}
private DirCacheEntry makeEntry(final String path, final FileMode mode)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java
index 99126e861..2d6acbddf 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java
@@ -87,6 +87,8 @@ public class NameConflictTreeWalk extends TreeWalk {
private boolean fastMinHasMatch;
+ private AbstractTreeIterator dfConflict;
+
/**
* Create a new tree walker for a given repository.
*
@@ -141,6 +143,7 @@ public class NameConflictTreeWalk extends TreeWalk {
if (minRef.eof())
return minRef;
+ boolean hasConflict = false;
minRef.matches = minRef;
while (++i < trees.length) {
final AbstractTreeIterator t = trees[i];
@@ -156,6 +159,7 @@ public class NameConflictTreeWalk extends TreeWalk {
// tree anyway.
//
t.matches = minRef;
+ hasConflict = true;
} else {
fastMinHasMatch = false;
t.matches = t;
@@ -182,10 +186,13 @@ public class NameConflictTreeWalk extends TreeWalk {
}
t.matches = t;
minRef = t;
+ hasConflict = true;
} else
fastMinHasMatch = false;
}
+ if (hasConflict && fastMinHasMatch && dfConflict == null)
+ dfConflict = minRef;
return minRef;
}
@@ -281,6 +288,10 @@ public class NameConflictTreeWalk extends TreeWalk {
for (final AbstractTreeIterator t : trees)
if (t.matches == minRef)
t.matches = treeMatch;
+
+ if (dfConflict == null)
+ dfConflict = treeMatch;
+
return treeMatch;
}
@@ -302,6 +313,9 @@ public class NameConflictTreeWalk extends TreeWalk {
t.matches = null;
}
}
+
+ if (ch == dfConflict)
+ dfConflict = null;
}
@Override
@@ -319,5 +333,26 @@ public class NameConflictTreeWalk extends TreeWalk {
t.matches = null;
}
}
+
+ if (ch == dfConflict)
+ dfConflict = null;
+ }
+
+ /**
+ * True if the current entry is covered by a directory/file conflict.
+ *
+ * This means that for some prefix of the current entry's path, this walk
+ * has detected a directory/file conflict. Also true if the current entry
+ * itself is a directory/file conflict.
+ *
+ * Example: If this TreeWalk points to foo/bar/a.txt and this method returns
+ * true then you know that either for path foo or for path foo/bar files and
+ * folders were detected.
+ *
+ * @return true
if the current entry is covered by a
+ * directory/file conflict, false
otherwise
+ */
+ public boolean isDirectoryFileConflict() {
+ return dfConflict != null;
}
}