libgit2/libgit2 — pull request #531 by arrbee (2012-01-11 23:14:15+00:00)
Title: Initial implementation of gitignore support

Adds support for .gitignore files to `git_status_foreach()` and `git_status_file()`. This includes refactoring the gitattributes code to share logic where possible. The GIT_STATUS_IGNORED flag will now be passed in for files that are ignored (provided they are not already in the index or the head of repo).

@tanoku please take a look. I had started to do a larger reworking of code, then I felt like it was starting to get too complicated, so this is my attempt as a simpler addition of gitignore support. The only observable behavior change should be that an ignored file that previously would have returned GIT_STATUS_WT_NEW will now return GIT_STATUS_IGNORED. If the file would have been something other than GIT_STATUS_WT_NEW (i.e. it is already being tracked by git in some way), then I don't bother to check ignores.

In the long run, this code can be made more efficient because I am currently rebuilding the vector of ignore info for each directory that is visited (although the contents of the gitignore files are loaded from cache so the reading and parsing is not repeated). But the current implementation is less code and should not be all that inefficient.

Two minor code bits that I'd like your opinion on:

* I added `git_futils_dir_for_path()` to get a starting path for gitignore searches. Given a directory, it just returns the (prettified) version of the directory. Given a file, it returns the dirname. Initially I added this function as a variant on `git_path_prettify_dir()`, but that involved making path.c use fileops.c (which it currently does not). I didn't want to add a circular dependency between path.c and fileops.c, so I moved this into fileops. I try to avoid circular dependencies between source files if I can, but maybe this really belongs in path.c (as `git_path_prettify_dirname`).
* I added `git_path_walk_up()` as a macro to path.h. This is an efficient way to walk up a path invoking a callback on each directory up to the repository root. I added it as a macro instead of a function because setting up callback functions was getting extremely messy, but I also feel this is a bit too much to put in a macro. Let me know if you think it's too ugly to do it this way.