libgit2/libgit2 — pull request #516 by arrbee (2011-12-21 01:11:00+00:00)
Title: Add APIs for git attributes

This adds APIs for querying git attributes. In addition to the new API in include/git2/attr.h, most of the action is in src/attr_file.[hc] which contains utilities for dealing with a single attributes file, and src/attr.[hc] which contains the implementation of the APIs that merge all applicable attributes files.

### public api

int git_attr_get(
git_repository *repo, const char *path, const char *name,
const char **value);

int git_attr_get_many(
git_repository *repo, const char *path,
size_t num_attr, const char **names,
const char **values);

int git_attr_foreach(
git_repository *repo, const char *path,
int (*callback)(const char *name, const char *value, void *payload),
void *payload);

The first API is an easy way to look up a single attribute value. It will return either a known value of GIT_ATTR_TRUE, GIT_ATTR_FALSE, or GIT_ATTR_UNSPECIFIED, or it will return a string of the value assigned to the attribute. GIT_ATTR_UNSPECIFIED is NULL, by the way.

The second API gets several attributes at once. I decided it was worth it as a fast way to look up several attributes on a single file. Using this API, the library does not have to call the fnmatch utility multiple times which could be a significant cost savings if being run over a large number of files.

The last API is mostly around as a way to implement `git check-attr -a` and find all the attributes set on a given file.

The contents of the gitattributes files are cached in a hashtable in the git_repository and will only be freed when the git_repository is freed. At this point, there is no way to flush the cache and no checking of cache freshness. I don't know how important that is.

### missing stuff

* Need API to flush gitattribute cache
* Loading "system" gitattributes file (/etc/gitattributes) is simplistic and should copy `git_config` (really needs a shared reimplementation)
* Macros (i.e. `[attr]binary -diff -text`) are not implemented
* Could have more tests

This implementation should be a good foundation for implementing gitignore support. However, because it tries to implement gitignore matching rules as documented, it does diverge in some minor ways from the core git implementation of gitattributes. I don't think it will matter.

This PR is for issue #508