diff options
author | Ben Straub <bs@github.com> | 2013-08-11 17:28:33 -0700 |
---|---|---|
committer | Ben Straub <bs@github.com> | 2013-08-11 17:28:33 -0700 |
commit | 8ca093991d3105e62a6f509e9763c1f72040e1c7 (patch) | |
tree | 8e0ff080d9b7239d0ac3aa5a49fa10b83e699ab9 /src | |
parent | a25519acc106acf6e1f376c81a078c78778015ed (diff) | |
parent | 3bc3ed80f476bcef24a508cadd45d4c341ef60c7 (diff) | |
download | libgit2-8ca093991d3105e62a6f509e9763c1f72040e1c7.tar.gz |
Merge pull request #1768 from arrbee/issue-1766-gitignore-weirdness
Fix issue 1766 - bugs in managing ignore file lists
Diffstat (limited to 'src')
-rw-r--r-- | src/ignore.c | 40 | ||||
-rw-r--r-- | src/ignore.h | 5 | ||||
-rw-r--r-- | src/iterator.c | 2 | ||||
-rw-r--r-- | src/path.c | 2 |
4 files changed, 35 insertions, 14 deletions
diff --git a/src/ignore.c b/src/ignore.c index 3c23158c2..0c35d0431 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -159,17 +159,36 @@ 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_file( - ign->repo, ign, &ign->ign_path, ign->dir.ptr, GIT_IGNORE_FILE); + + return push_ignore_file( + ign->repo, ign, &ign->ign_path, ign->dir.ptr, GIT_IGNORE_FILE); } 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->key + 2) == 0) + const char *start, *end, *scan; + size_t keylen; + + /* - ign->dir looks something like "a/b" (or "a/b/c/d") + * - file->key looks something like "0#a/b/.gitignore + * + * We are popping the last directory off ign->dir. We also want to + * remove the file from the vector if the directory part of the key + * matches the ign->dir path. We need to test if the "a/b" part of + * the file key matches the path we are about to pop. + */ + + for (start = end = scan = &file->key[2]; *scan; ++scan) + if (*scan == '/') + end = scan; /* point 'end' to last '/' in key */ + keylen = (end - start) + 1; + + if (ign->dir.size >= keylen && + !memcmp(ign->dir.ptr + ign->dir.size - keylen, start, keylen)) git_vector_pop(&ign->ign_path); + git_buf_rtruncate_at_char(&ign->dir, '/'); } return 0; @@ -298,12 +317,9 @@ int git_ignore_path_is_ignored( path.full.size = (tail - path.full.ptr); path.is_dir = (tail == end) ? full_is_dir : true; - /* update ignores for new path fragment */ - if (path.basename == path.path) - error = git_ignore__for_path(repo, path.path, &ignores); - else - error = git_ignore__push_dir(&ignores, path.basename); - if (error < 0) + /* initialize ignores the first time through */ + if (path.basename == path.path && + (error = git_ignore__for_path(repo, path.path, &ignores)) < 0) break; /* first process builtins - success means path was found */ @@ -327,6 +343,10 @@ int git_ignore_path_is_ignored( if (tail == end) break; + /* now add this directory to list of ignores */ + if ((error = git_ignore__push_dir(&ignores, path.path)) < 0) + break; + /* reinstate divider in path */ *tail = '/'; while (*tail == '/') tail++; diff --git a/src/ignore.h b/src/ignore.h index cc114b001..851c824bf 100644 --- a/src/ignore.h +++ b/src/ignore.h @@ -24,14 +24,15 @@ */ typedef struct { git_repository *repo; - git_buf dir; + git_buf dir; /* current directory reflected in ign_path */ git_attr_file *ign_internal; git_vector ign_path; git_vector ign_global; int ignore_case; } git_ignores; -extern int git_ignore__for_path(git_repository *repo, const char *path, git_ignores *ign); +extern int git_ignore__for_path( + git_repository *repo, const char *path, git_ignores *ign); extern int git_ignore__push_dir(git_ignores *ign, const char *dir); diff --git a/src/iterator.c b/src/iterator.c index 5917f63fd..bdc98d22b 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -1350,7 +1350,7 @@ int git_iterator_for_workdir_ext( wi->fi.update_entry_cb = workdir_iterator__update_entry; if ((error = iterator__update_ignore_case((git_iterator *)wi, flags)) < 0 || - (error = git_ignore__for_path(repo, "", &wi->ignores)) < 0) + (error = git_ignore__for_path(repo, ".gitignore", &wi->ignores)) < 0) { git_iterator_free((git_iterator *)wi); return error; diff --git a/src/path.c b/src/path.c index 6437979d5..b81675b49 100644 --- a/src/path.c +++ b/src/path.c @@ -603,7 +603,7 @@ int git_path_find_dir(git_buf *dir, const char *path, const char *base) } /* call dirname if this is not a directory */ - if (!error && git_path_isdir(dir->ptr) == false) + if (!error) /* && git_path_isdir(dir->ptr) == false) */ error = git_path_dirname_r(dir, dir->ptr); if (!error) |