A NameConflictTreeWalk should have dived into the working tree and told you about these conflicts.

If the tree wants to put a blob at "foo", but the working directory has "foo/bar.c" and "foo/other.c", so "foo" is a directory, you should get:

  Path "foo":  Index blob;  working directory tree
  Path "foo/bar.c":  Index none; working directory file
  Path "foo/other.c":  Index none; working directory file

This means that you don't need to implement this recursion logic, you just need to keep track of D/F conflicts by storing the prefix path and then on each subsequent step of the walker check to see if the path is covered by one of those prefix paths.  If it is, you are inside of a D/F conflict and the working tree is conflicting with the blob record.

Actually, this is all something that the NameConflictTreeWalk should be able to tell you.  Just add a isDirectoryFileConflict() method to NameConflictTreeWalk that can export this, and keeps track of the current state for you.

The basic logic might be:

* in combineDF() store the treeMatch iterator into a new dfConflict field, inside of the "if (treeMatch != null) {" condition near the end of the method.  Only set the field if it is currently null.
* implement isDirectoryFileConflict to return true if dfConflict != null
* modify popEntriesEqual to clear dfConflict if dfConflict is any of the current iterators, before popping.