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;
assertEquals(0, diff.getChanged().size());
assertEquals(0, diff.getModified().size());
assertEquals(0, diff.getRemoved().size());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
assertEquals(0, diff.getChanged().size());
assertEquals(0, diff.getModified().size());
assertEquals(0, diff.getAdded().size());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
assertEquals(0, diff.getAdded().size());
assertEquals(0, diff.getRemoved().size());
assertEquals(0, diff.getMissing().size());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
assertEquals("[]", diff.getMissing().toString());
assertEquals("[]", diff.getModified().toString());
assertEquals("[a]", diff.getConflicting().toString());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
assertEquals("[]", diff.getMissing().toString());
assertEquals("[]", diff.getModified().toString());
assertEquals("[a]", diff.getConflicting().toString());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
assertEquals("[]", diff.getMissing().toString());
assertEquals("[]", diff.getModified().toString());
assertEquals("[b]", diff.getConflicting().toString());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
@Test
assertEquals(0, diff.getRemoved().size());
assertEquals(0, diff.getMissing().size());
assertEquals(0, diff.getModified().size());
+ assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
}
/**
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 {
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
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 {
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;
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.
@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) {
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);
}
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;
+ }
}