Use symlinks, and symlink entire subdirectories where possible instead of recursing

This greatly improves performance.

This change in the algorithm also cleans up some capitalization edge
cases. We now always throw an error when we encounter inconsistent
capitalization, which ensures consistent behavior between case-sensitive
and case-insensitive file systems.

---------------

@rjackson, I don't think the history on the symlink branch is terribly meaningful at this point, so I've squashed the symlink branch into a single commit with shared authorship. I re-read the diff and it looks fine to me.

Is there anything else we need to think about before we merge this into master? I can't think of anything off the top of my head.

Hit the merge button if you feel good about this. :)
This is an extremely large method, it is quite difficult to reason about and also optimize.

Is it possible to at least break this down in to a series of clear and concise helper methods?