@Override
public boolean include(TreeWalk tw) throws MissingObjectException,
IncorrectObjectTypeException, IOException {
final int cnt = tw.getTreeCount();
final int wm = tw.getRawMode(workingTree);
WorkingTreeIterator wi = workingTree(tw);
String path = tw.getPathString();
DirCacheIterator di = tw.getTree(dirCache, DirCacheIterator.class);
if (di != null) {
DirCacheEntry dce = di.getDirCacheEntry();
if (dce != null) {
if (dce.isAssumeValid())
return false;
// Never filter index entries with a stage different from 0
if (dce.getStage() != 0)
return true;
}
}
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)
&& !(honorIgnores && wi.isEntryIgnored())) {
// 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 != FileMode.TYPE_MISSING
&& 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.
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 dm = tw.getRawMode(dirCache);
if (dm == FileMode.TYPE_MISSING) {
if (honorIgnores && wi.isEntryIgnored()) {
ignoredPaths.add(wi.getEntryPathString());
int i = 0;
for (; i < cnt; i++) {
if (i == dirCache || i == workingTree)
continue;
if (tw.getRawMode(i) != FileMode.TYPE_MISSING)
break;
}
// If i is cnt then the path does not appear in any other tree,
// and this working tree entry can be safely ignored.
return i == cnt ? false : true;
} else {
// In working tree and not ignored, and not in DirCache.
return true;
}
}
// Always include subtrees as WorkingTreeIterator cannot provide
// efficient elimination of unmodified subtrees.
if (tw.isSubtree())
return true;
// Try the inexpensive comparisons between index and all real trees
// first. Only if we don't find a diff here we have to bother with
// the working tree
for (int i = 0; i < cnt; i++) {
if (i == dirCache || i == workingTree)
continue;
if (tw.getRawMode(i) != dm || !tw.idEqual(i, dirCache))
return true;
}
// Only one chance left to detect a diff: between index and working
// tree. Make use of the WorkingTreeIterator#isModified() method to
// avoid computing SHA1 on filesystem content if not really needed.
return wi.isModified(di.getDirCacheEntry(), true, tw.getObjectReader());
}