Commit 6069042f by Carlos Martín Nieto

ignore: don't leak rules into higher directories

A rule "src" in src/.gitignore must only match subdirectories of
src/. The current code does not include this context in the match rule
and would thus consider this rule to match the top-level src/ directory
instead of the intended src/src/.

Keep track fo the context in which the rule was defined so we can
perform a prefix match.
parent 0798b014
...@@ -347,6 +347,21 @@ bool git_attr_fnmatch__match( ...@@ -347,6 +347,21 @@ bool git_attr_fnmatch__match(
const char *filename; const char *filename;
int flags = 0; int flags = 0;
/*
* If the rule was generated in a subdirectory, we must only
* use it for paths inside that directory. We can thus return
* a non-match if the prefixes don't match.
*/
if (match->containing_dir) {
if (match->flags & GIT_ATTR_FNMATCH_ICASE) {
if (git__strncasecmp(path->path, match->containing_dir, match->containing_dir_length))
return 0;
} else {
if (git__prefixcmp(path->path, match->containing_dir))
return 0;
}
}
if (match->flags & GIT_ATTR_FNMATCH_ICASE) if (match->flags & GIT_ATTR_FNMATCH_ICASE)
flags |= FNM_CASEFOLD; flags |= FNM_CASEFOLD;
if (match->flags & GIT_ATTR_FNMATCH_LEADINGDIR) if (match->flags & GIT_ATTR_FNMATCH_LEADINGDIR)
...@@ -588,6 +603,17 @@ int git_attr_fnmatch__parse( ...@@ -588,6 +603,17 @@ int git_attr_fnmatch__parse(
/* leave FULLPATH match on, however */ /* leave FULLPATH match on, however */
} }
if (context) {
char *slash = strchr(context, '/');
size_t len;
if (slash) {
/* include the slash for easier matching */
len = slash - context + 1;
spec->containing_dir = git_pool_strndup(pool, context, len);
spec->containing_dir_length = len;
}
}
if ((spec->flags & GIT_ATTR_FNMATCH_FULLPATH) != 0 && if ((spec->flags & GIT_ATTR_FNMATCH_FULLPATH) != 0 &&
context != NULL && git_path_root(pattern) < 0) context != NULL && git_path_root(pattern) < 0)
{ {
......
...@@ -52,6 +52,8 @@ extern const char *git_attr__unset; ...@@ -52,6 +52,8 @@ extern const char *git_attr__unset;
typedef struct { typedef struct {
char *pattern; char *pattern;
size_t length; size_t length;
char *containing_dir;
size_t containing_dir_length;
unsigned int flags; unsigned int flags;
} git_attr_fnmatch; } git_attr_fnmatch;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment