aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Baumgart2011-10-26 08:00:48 (EDT)
committerChris Aniszczyk2011-11-10 14:15:26 (EST)
commit53ef3e51145adb4b060110e262d7c064be0d5fc5 (patch)
treee90afe8c39ca4945254aba21f3d8fe08f0464689
parent92752f6b50ba8c2a1d1946abac0064ea2e318591 (diff)
downloadjgit-53ef3e51145adb4b060110e262d7c064be0d5fc5.zip
jgit-53ef3e51145adb4b060110e262d7c064be0d5fc5.tar.gz
jgit-53ef3e51145adb4b060110e262d7c064be0d5fc5.tar.bz2
Add detection of untracked folders to IndexDiffFilterrefs/changes/85/4385/6
Decorators need to know whether folders in the working tree contain only untracked files. This change enhances IndexDiffFilter to report such folders. This works only together with treewalks which operate in default traversal mode. For treewalks which process entries in postorder mode (files are walked before their parent folder is walked) this detection doesn't work. Bug: 359264 Change-Id: I9298d1e3ccac0aec8bbd4e8ac867bc06a5c89c9f Signed-off-by: Christian Halstrick <christian.halstrick@sap.com> Signed-off-by: Jens Baumgart <jens.baumgart@sap.com> Signed-off-by: Chris Aniszczyk <zx@twitter.com>
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java66
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java81
3 files changed, 157 insertions, 3 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java
index e350fea..b7caecc 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java
@@ -51,6 +51,9 @@ import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.TreeSet;
import org.eclipse.jgit.api.Git;
@@ -105,6 +108,7 @@ public class IndexDiffTest extends RepositoryTestCase {
assertEquals(0, diff.getChanged().size());
assertEquals(0, diff.getModified().size());
assertEquals(0, diff.getRemoved().size());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
@@ -131,6 +135,7 @@ public class IndexDiffTest extends RepositoryTestCase {
assertEquals(0, diff.getChanged().size());
assertEquals(0, diff.getModified().size());
assertEquals(0, diff.getAdded().size());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
@@ -163,6 +168,7 @@ public class IndexDiffTest extends RepositoryTestCase {
assertEquals(0, diff.getAdded().size());
assertEquals(0, diff.getRemoved().size());
assertEquals(0, diff.getMissing().size());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
@@ -204,6 +210,7 @@ public class IndexDiffTest extends RepositoryTestCase {
assertEquals("[]", diff.getMissing().toString());
assertEquals("[]", diff.getModified().toString());
assertEquals("[a]", diff.getConflicting().toString());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
@@ -242,6 +249,7 @@ public class IndexDiffTest extends RepositoryTestCase {
assertEquals("[]", diff.getMissing().toString());
assertEquals("[]", diff.getModified().toString());
assertEquals("[a]", diff.getConflicting().toString());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
@@ -279,6 +287,7 @@ public class IndexDiffTest extends RepositoryTestCase {
assertEquals("[]", diff.getMissing().toString());
assertEquals("[]", diff.getModified().toString());
assertEquals("[b]", diff.getConflicting().toString());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
@@ -311,6 +320,7 @@ public class IndexDiffTest extends RepositoryTestCase {
assertEquals(0, diff.getRemoved().size());
assertEquals(0, diff.getMissing().size());
assertEquals(0, diff.getModified().size());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
/**
@@ -360,6 +370,7 @@ public class IndexDiffTest extends RepositoryTestCase {
assertEquals(0, diff.getRemoved().size());
assertEquals(0, diff.getMissing().size());
assertEquals(0, diff.getModified().size());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
private ObjectId insertTree(Tree tree) throws IOException {
@@ -392,6 +403,60 @@ public class IndexDiffTest extends RepositoryTestCase {
diff.diff();
assertTrue(diff.getRemoved().contains(path));
assertTrue(diff.getUntracked().contains(path));
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
+ }
+
+ /**
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testUntrackedFolders() throws Exception {
+ Git git = new Git(db);
+
+ IndexDiff diff = new IndexDiff(db, Constants.HEAD,
+ new FileTreeIterator(db));
+ diff.diff();
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
+
+ writeTrashFile("readme", "");
+ writeTrashFile("src/com/A.java", "");
+ writeTrashFile("src/com/B.java", "");
+ writeTrashFile("src/org/A.java", "");
+ writeTrashFile("src/org/B.java", "");
+ writeTrashFile("target/com/A.java", "");
+ writeTrashFile("target/com/B.java", "");
+ writeTrashFile("target/org/A.java", "");
+ writeTrashFile("target/org/B.java", "");
+
+ git.add().addFilepattern("src").addFilepattern("readme").call();
+ git.commit().setMessage("initial").call();
+
+ diff = new IndexDiff(db, Constants.HEAD,
+ new FileTreeIterator(db));
+ diff.diff();
+ assertEquals(new HashSet<String>(Arrays.asList("target")),
+ diff.getUntrackedFolders());
+
+ writeTrashFile("src/tst/A.java", "");
+ writeTrashFile("src/tst/B.java", "");
+
+ diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
+ diff.diff();
+ assertEquals(new HashSet<String>(Arrays.asList("target", "src/tst")),
+ diff.getUntrackedFolders());
+
+ git.rm().addFilepattern("src/com/B.java").addFilepattern("src/org")
+ .call();
+ git.commit().setMessage("second").call();
+ writeTrashFile("src/org/C.java", "");
+
+ diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
+ diff.diff();
+ assertEquals(
+ new HashSet<String>(Arrays.asList("src/org", "src/tst",
+ "target")),
+ diff.getUntrackedFolders());
}
@Test
@@ -427,6 +492,7 @@ public class IndexDiffTest extends RepositoryTestCase {
assertEquals(1, diff.getChanged().size());
assertTrue(diff.getAssumeUnchanged().contains("file2"));
assertTrue(diff.getChanged().contains("file"));
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
private void removeFromIndex(String path) throws IOException {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
index af64f20..39f732f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/IndexDiff.java
@@ -48,6 +48,7 @@ package org.eclipse.jgit.lib;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -163,6 +164,8 @@ public class IndexDiff {
private DirCache dirCache;
+ private IndexDiffFilter indexDiffFilter;
+
/**
* Construct an IndexDiff
*
@@ -278,7 +281,7 @@ public class IndexDiff {
if (filter != null)
filters.add(filter);
filters.add(new SkipWorkTreeFilter(INDEX));
- IndexDiffFilter indexDiffFilter = new IndexDiffFilter(INDEX, WORKDIR);
+ indexDiffFilter = new IndexDiffFilter(INDEX, WORKDIR);
filters.add(indexDiffFilter);
treeWalk.setFilter(AndTreeFilter.create(filters));
while (treeWalk.next()) {
@@ -427,4 +430,12 @@ public class IndexDiff {
}
return assumeUnchanged;
}
+
+ /**
+ * @return list of folders containing only untracked files/folders
+ */
+ public Set<String> getUntrackedFolders() {
+ return ((indexDiffFilter == null) ? Collections.<String> emptySet()
+ : new HashSet<String>(indexDiffFilter.getUntrackedFolders()));
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java
index 2f8608e..34e92b6 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java
@@ -44,11 +44,14 @@ package org.eclipse.jgit.treewalk.filter;
import java.io.IOException;
import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Set;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;
@@ -83,6 +86,10 @@ public class IndexDiffFilter extends TreeFilter {
private final Set<String> ignoredPaths = new HashSet<String>();
+ private final LinkedList<String> untrackedParentFolders = new LinkedList<String>();
+
+ private final LinkedList<String> untrackedFolders = new LinkedList<String>();
+
/**
* Creates a new instance of this filter. Do not use an instance of this
* filter in multiple treewalks.
@@ -122,16 +129,46 @@ public class IndexDiffFilter extends TreeFilter {
@Override
public boolean include(TreeWalk tw) throws MissingObjectException,
IncorrectObjectTypeException, IOException {
+ final int cnt = tw.getTreeCount();
+ final int wm = tw.getRawMode(workingTree);
+ String path = tw.getPathString();
+
+ if (!tw.isPostOrderTraversal()) {
+ // detect untracked Folders
+ // Whenever we enter a folder in the workingtree assume it will
+ // contain only untracked files and add it to
+ // untrackedParentFolders. If we later find tracked files we will
+ // remove it from this list
+ if (FileMode.TREE.equals(wm)) {
+ // Clean untrackedParentFolders. This potentially moves entries
+ // from untrackedParentFolders to untrackedFolders
+ copyUntrackedFolders(path);
+ // add the folder we just entered to untrackedParentFolders
+ untrackedParentFolders.addFirst(path);
+ }
+
+ // detect untracked Folders
+ // Whenever we see a tracked file we know that all of its parent
+ // folders do not belong into untrackedParentFolders anymore. Clean
+ // it.
+ for (int i = 0; i < cnt; i++) {
+ int rmode = tw.getRawMode(i);
+ if (i != workingTree && rmode != 0
+ && FileMode.TREE.equals(rmode)) {
+ untrackedParentFolders.clear();
+ break;
+ }
+ }
+ }
+
// If the working tree file doesn't exist, it does exist for at least
// one other so include this difference.
- final int wm = tw.getRawMode(workingTree);
if (wm == 0)
return true;
// If the path does not appear in the DirCache and its ignored
// we can avoid returning a result here, but only if its not in any
// other tree.
- final int cnt = tw.getTreeCount();
final int dm = tw.getRawMode(dirCache);
WorkingTreeIterator wi = workingTree(tw);
if (dm == 0) {
@@ -176,6 +213,29 @@ public class IndexDiffFilter extends TreeFilter {
return wi.isModified(di.getDirCacheEntry(), true);
}
+ /**
+ * Copy all entries which are still in untrackedParentFolders and which
+ * belong to a path this treewalk has left into untrackedFolders. It is sure
+ * that we will not find any tracked files underneath these paths. Therefore
+ * these paths definitely belong to untracked folders.
+ *
+ * @param currentPath
+ * the current path of the treewalk
+ */
+ private void copyUntrackedFolders(String currentPath) {
+ String pathToBeSaved = null;
+ while (!untrackedParentFolders.isEmpty()
+ && !currentPath.startsWith(untrackedParentFolders.getFirst()
+ + "/"))
+ pathToBeSaved = untrackedParentFolders.removeFirst();
+ if (pathToBeSaved != null) {
+ while (!untrackedFolders.isEmpty()
+ && untrackedFolders.getLast().startsWith(pathToBeSaved))
+ untrackedFolders.removeLast();
+ untrackedFolders.addLast(pathToBeSaved);
+ }
+ }
+
private WorkingTreeIterator workingTree(TreeWalk tw) {
return tw.getTree(workingTree, WorkingTreeIterator.class);
}
@@ -209,4 +269,21 @@ public class IndexDiffFilter extends TreeFilter {
public Set<String> getIgnoredPaths() {
return ignoredPaths;
}
+
+ /**
+ * @return all paths of folders which contain only untracked files/folders.
+ * If on the associated treewalk postorder traversal was turned on
+ * (see {@link TreeWalk#setPostOrderTraversal(boolean)}) then an
+ * empty list will be returned.
+ */
+ public List<String> getUntrackedFolders() {
+ LinkedList<String> ret = new LinkedList<String>(untrackedFolders);
+ if (!untrackedParentFolders.isEmpty()) {
+ String toBeAdded = untrackedParentFolders.getLast();
+ while (!ret.isEmpty() && ret.getLast().startsWith(toBeAdded))
+ ret.removeLast();
+ ret.addLast(toBeAdded);
+ }
+ return ret;
+ }
}