diff options
author | Patrick Steinhardt <ps@pks.im> | 2019-07-12 09:03:33 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2019-07-12 09:26:22 +0200 |
commit | f83469059b73c21dfa5d7861cb883de5fa2c1872 (patch) | |
tree | 58bbcf637b4eef970169c1f98cc898a95851d1fb /src/ignore.c | |
parent | 97968529f960d8f3e7baf3e242c286b948ec409b (diff) | |
download | libgit2-f83469059b73c21dfa5d7861cb883de5fa2c1872.tar.gz |
attr_file: ignore macros defined in subdirectories
Right now, we are unconditionally applying all macros found in a
gitatttributes file. But quoting gitattributes(5):
Custom macro attributes can be defined only in top-level
gitattributes files ($GIT_DIR/info/attributes, the .gitattributes
file at the top level of the working tree, or the global or
system-wide gitattributes files), not in .gitattributes files in
working tree subdirectories. The built-in macro attribute "binary"
is equivalent to:
So gitattribute files in subdirectories of the working tree may
explicitly _not_ contain macro definitions, but we do not currently
enforce this limitation.
This patch introduces a new parameter to the gitattributes parser that
tells whether macros are allowed in the current file or not. If set to
`false`, we will still parse macros, but silently ignore them instead of
adding them to the list of defined macros. Update all callers to
correctly determine whether the to-be-parsed file may contain macros or
not. Most importantly, when walking up the directory hierarchy, we will
only set it to `true` once it reaches the root directory of the repo
itself.
Add a test that verifies that we are indeed not applying macros from
subdirectories. Previous to these changes, the test would've failed.
Diffstat (limited to 'src/ignore.c')
-rw-r--r-- | src/ignore.c | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/src/ignore.c b/src/ignore.c index b17714b2c..0fdadfb13 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -163,13 +163,15 @@ out: } static int parse_ignore_file( - git_repository *repo, git_attr_file *attrs, const char *data) + git_repository *repo, git_attr_file *attrs, const char *data, bool allow_macros) { int error = 0; int ignore_case = false; const char *scan = data, *context = NULL; git_attr_fnmatch *match = NULL; + GIT_UNUSED(allow_macros); + if (git_repository__cvar(&ignore_case, repo, GIT_CVAR_IGNORECASE) < 0) git_error_clear(); @@ -244,9 +246,8 @@ static int push_ignore_file( int error = 0; git_attr_file *file = NULL; - error = git_attr_cache__get( - &file, ignores->repo, NULL, GIT_ATTR_FILE__FROM_FILE, - base, filename, parse_ignore_file); + error = git_attr_cache__get(&file, ignores->repo, NULL, GIT_ATTR_FILE__FROM_FILE, + base, filename, parse_ignore_file, false); if (error < 0) return error; @@ -272,12 +273,12 @@ static int get_internal_ignores(git_attr_file **out, git_repository *repo) if ((error = git_attr_cache__init(repo)) < 0) return error; - error = git_attr_cache__get( - out, repo, NULL, GIT_ATTR_FILE__IN_MEMORY, NULL, GIT_IGNORE_INTERNAL, NULL); + error = git_attr_cache__get(out, repo, NULL, GIT_ATTR_FILE__IN_MEMORY, NULL, + GIT_IGNORE_INTERNAL, NULL, false); /* if internal rules list is empty, insert default rules */ if (!error && !(*out)->rules.length) - error = parse_ignore_file(repo, *out, GIT_IGNORE_DEFAULT_RULES); + error = parse_ignore_file(repo, *out, GIT_IGNORE_DEFAULT_RULES, false); return error; } @@ -487,7 +488,7 @@ int git_ignore_add_rule(git_repository *repo, const char *rules) if ((error = get_internal_ignores(&ign_internal, repo)) < 0) return error; - error = parse_ignore_file(repo, ign_internal, rules); + error = parse_ignore_file(repo, ign_internal, rules, false); git_attr_file__free(ign_internal); return error; @@ -503,7 +504,7 @@ int git_ignore_clear_internal_rules(git_repository *repo) if (!(error = git_attr_file__clear_rules(ign_internal, true))) error = parse_ignore_file( - repo, ign_internal, GIT_IGNORE_DEFAULT_RULES); + repo, ign_internal, GIT_IGNORE_DEFAULT_RULES, false); git_attr_file__free(ign_internal); return error; |