summaryrefslogtreecommitdiff
path: root/src/attr_file.c
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2019-07-12 09:03:33 +0200
committerPatrick Steinhardt <ps@pks.im>2019-07-12 09:26:22 +0200
commitf83469059b73c21dfa5d7861cb883de5fa2c1872 (patch)
tree58bbcf637b4eef970169c1f98cc898a95851d1fb /src/attr_file.c
parent97968529f960d8f3e7baf3e242c286b948ec409b (diff)
downloadlibgit2-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/attr_file.c')
-rw-r--r--src/attr_file.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/src/attr_file.c b/src/attr_file.c
index 0209117b6..f8769c6e7 100644
--- a/src/attr_file.c
+++ b/src/attr_file.c
@@ -105,7 +105,8 @@ int git_attr_file__load(
git_attr_session *attr_session,
git_attr_file_entry *entry,
git_attr_file_source source,
- git_attr_file_parser parser)
+ git_attr_file_parser parser,
+ bool allow_macros)
{
int error = 0;
git_blob *blob = NULL;
@@ -177,7 +178,7 @@ int git_attr_file__load(
if (attr_session)
file->session_key = attr_session->key;
- if (parser && (error = parser(repo, file, content_str)) < 0) {
+ if (parser && (error = parser(repo, file, content_str, allow_macros)) < 0) {
git_attr_file__free(file);
goto cleanup;
}
@@ -249,7 +250,7 @@ static bool parse_optimized_patterns(
const char *pattern);
int git_attr_file__parse_buffer(
- git_repository *repo, git_attr_file *attrs, const char *data)
+ git_repository *repo, git_attr_file *attrs, const char *data, bool allow_macros)
{
const char *scan = data, *context = NULL;
git_attr_rule *rule = NULL;
@@ -287,6 +288,8 @@ int git_attr_file__parse_buffer(
if (rule->match.flags & GIT_ATTR_FNMATCH_MACRO) {
/* TODO: warning if macro found in file below repo root */
+ if (!allow_macros)
+ continue;
if ((error = git_attr_cache__insert_macro(repo, rule)) < 0)
goto out;
} else if ((error = git_vector_insert(&attrs->rules, rule)) < 0)
@@ -355,7 +358,7 @@ int git_attr_file__load_standalone(git_attr_file **out, const char *path)
*/
if ((error = git_attr_file__new(&file, NULL, GIT_ATTR_FILE__FROM_FILE)) < 0 ||
- (error = git_attr_file__parse_buffer(NULL, file, content.ptr)) < 0 ||
+ (error = git_attr_file__parse_buffer(NULL, file, content.ptr, true)) < 0 ||
(error = git_attr_cache__alloc_file_entry(&file->entry, NULL, path, &file->pool)) < 0)
goto out;