Instead of taking the java.io.File, I'd prefer to take a String that is the path from the root of the repository.

The reason is, we should be processing ignore information at the same time that we are walking through trees with a TreeWalk.  That does this parallel walk thing, and we should be able to have the ignore rules run as part of it and tell us if the current path is considered to be ignored, or not.

Because TreeWalk does this sorted-name, depth-first traversal of the repository structure, you can have the cache keep track of where you are as you enter/exit directories and apply only the correct set of .gitignore as you go.

Further, if the ignore code can be given a WorkingTreeIterator, it can ask that iterator at each level whether or not a .gitignore name even exists.  That avoids a stat hit at each level to see if the file even exists (and it usually doesn't).  Where it does exist, you can also use the WorkingTreeIterator to tell you the last modified time and length of the file, so you can decide if its worth reading the file again, or keeping the cached copy you might have in memory.

So, this is a nice start, but its not quite the way I had hoped we could build the ignore support.