Sadly this wasn't quite what I had in mind with the ignore stuff.  But I was too distracted by my other refactoring work to review it in time and it got submitted anyway.

We're ripping through the checkout directory now *twice*.  Once to find .gitignore files and build a table of what needs to be ignored, and again as you traverse it.

What I wanted to do was to have the WorkingTreeIterator keep the IgnoreNode for that level within itself.  Then you can just ask:

  tw.getTree(1, WorkingTreeIterator.class).isIgnored())

to determine if the current item is ignored, or not.  By keeping the IgnoreNode inside of the WorkingTreeIterator we already have the full path up to the root through the parent pointers.  And we have fast efficient knowledge of whether or not there is even a .gitignore in this directory.