summaryrefslogtreecommitdiff
path: root/src/ignore.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2012-05-03 16:37:25 -0700
committerRussell Belfer <rb@github.com>2012-05-03 16:37:25 -0700
commitf917481ee84cbba481c1854cccdedb2d98377d43 (patch)
treeb6276158b43f8d54358df5609fd0e508928306b2 /src/ignore.c
parent3fbcac89c47cb66ea193f66da6d93d1c36ed0f5e (diff)
downloadlibgit2-f917481ee84cbba481c1854cccdedb2d98377d43.tar.gz
Support reading attributes from index
Depending on the operation, we need to consider gitattributes in both the work dir and the index. This adds a parameter to all of the gitattributes related functions that allows user control of attribute reading behavior (i.e. prefer workdir, prefer index, only use index). This fix also covers allowing us to check attributes (and hence do diff and status) on bare repositories. This was a somewhat larger change that I hoped because it had to change the cache key used for gitattributes files.
Diffstat (limited to 'src/ignore.c')
-rw-r--r--src/ignore.c69
1 files changed, 37 insertions, 32 deletions
diff --git a/src/ignore.c b/src/ignore.c
index 20b96c602..6f70b972d 100644
--- a/src/ignore.c
+++ b/src/ignore.c
@@ -5,29 +5,22 @@
#define GIT_IGNORE_FILE_INREPO "info/exclude"
#define GIT_IGNORE_FILE ".gitignore"
-static int load_ignore_file(
- git_repository *repo, const char *path, git_attr_file *ignores)
+static int parse_ignore_file(
+ git_repository *repo, const char *buffer, git_attr_file *ignores)
{
int error;
- git_buf fbuf = GIT_BUF_INIT;
git_attr_fnmatch *match = NULL;
const char *scan = NULL;
char *context = NULL;
- if (ignores->path == NULL) {
- if (git_attr_file__set_path(repo, path, ignores) < 0)
- return -1;
- }
+ GIT_UNUSED(repo);
- if (git__suffixcmp(ignores->path, GIT_IGNORE_FILE) == 0) {
- context = git__strndup(ignores->path,
- strlen(ignores->path) - strlen(GIT_IGNORE_FILE));
- GITERR_CHECK_ALLOC(context);
+ if (ignores->key && git__suffixcmp(ignores->key, "/" GIT_IGNORE_FILE) == 0) {
+ context = ignores->key + 2;
+ context[strlen(context) - strlen(GIT_IGNORE_FILE)] = '\0';
}
- error = git_futils_readbuffer(&fbuf, path);
-
- scan = fbuf.ptr;
+ scan = buffer;
while (!error && *scan) {
if (!match) {
@@ -54,23 +47,27 @@ static int load_ignore_file(
}
}
- git_buf_free(&fbuf);
git__free(match);
- git__free(context);
+ /* restore file path used for context */
+ if (context)
+ context[strlen(context)] = '.'; /* first char of GIT_IGNORE_FILE */
return error;
}
-#define push_ignore(R,S,B,F) \
- git_attr_cache__push_file((R),(S),(B),(F),load_ignore_file)
+#define push_ignore_file(R,S,B,F) \
+ git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,parse_ignore_file,(S))
static int push_one_ignore(void *ref, git_buf *path)
{
git_ignores *ign = (git_ignores *)ref;
- return push_ignore(ign->repo, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
+ return push_ignore_file(ign->repo, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
}
-int git_ignore__for_path(git_repository *repo, const char *path, git_ignores *ignores)
+int git_ignore__for_path(
+ git_repository *repo,
+ const char *path,
+ git_ignores *ignores)
{
int error = 0;
const char *workdir = git_repository_workdir(repo);
@@ -86,30 +83,37 @@ int git_ignore__for_path(git_repository *repo, const char *path, git_ignores *ig
(error = git_attr_cache__init(repo)) < 0)
goto cleanup;
- /* translate path into directory within workdir */
- if ((error = git_path_find_dir(&ignores->dir, path, workdir)) < 0)
+ /* given a unrooted path in a non-bare repo, resolve it */
+ if (workdir && git_path_root(path) < 0)
+ error = git_path_find_dir(&ignores->dir, path, workdir);
+ else
+ error = git_buf_sets(&ignores->dir, path);
+ if (error < 0)
goto cleanup;
/* set up internals */
- error = git_attr_cache__lookup_or_create_file(
- repo, GIT_IGNORE_INTERNAL, NULL, NULL, &ignores->ign_internal);
+ error = git_attr_cache__internal_file(
+ repo, GIT_IGNORE_INTERNAL, &ignores->ign_internal);
if (error < 0)
goto cleanup;
/* load .gitignore up the path */
- error = git_path_walk_up(&ignores->dir, workdir, push_one_ignore, ignores);
- if (error < 0)
- goto cleanup;
+ if (workdir != NULL) {
+ error = git_path_walk_up(
+ &ignores->dir, workdir, push_one_ignore, ignores);
+ if (error < 0)
+ goto cleanup;
+ }
/* load .git/info/exclude */
- error = push_ignore(repo, &ignores->ign_global,
+ error = push_ignore_file(repo, &ignores->ign_global,
git_repository_path(repo), GIT_IGNORE_FILE_INREPO);
if (error < 0)
goto cleanup;
/* load core.excludesfile */
if (git_repository_attr_cache(repo)->cfg_excl_file != NULL)
- error = push_ignore(repo, &ignores->ign_global, NULL,
+ error = push_ignore_file(repo, &ignores->ign_global, NULL,
git_repository_attr_cache(repo)->cfg_excl_file);
cleanup:
@@ -124,7 +128,7 @@ int git_ignore__push_dir(git_ignores *ign, const char *dir)
if (git_buf_joinpath(&ign->dir, ign->dir.ptr, dir) < 0)
return -1;
else
- return push_ignore(
+ return push_ignore_file(
ign->repo, &ign->ign_path, ign->dir.ptr, GIT_IGNORE_FILE);
}
@@ -132,7 +136,7 @@ int git_ignore__pop_dir(git_ignores *ign)
{
if (ign->ign_path.length > 0) {
git_attr_file *file = git_vector_last(&ign->ign_path);
- if (git__suffixcmp(ign->dir.ptr, file->path) == 0)
+ if (git__suffixcmp(ign->dir.ptr, file->key + 2) == 0)
git_vector_pop(&ign->ign_path);
git_buf_rtruncate_at_char(&ign->dir, '/');
}
@@ -163,7 +167,8 @@ static bool ignore_lookup_in_rules(
return false;
}
-int git_ignore__lookup(git_ignores *ignores, const char *pathname, int *ignored)
+int git_ignore__lookup(
+ git_ignores *ignores, const char *pathname, int *ignored)
{
unsigned int i;
git_attr_file *file;