Unverified Commit e3d7bccb by Steve King Jr Committed by Steven King Jr

ignore: Do not match on prefix of negated patterns

Matching on the prefix of a negated pattern was triggering false
negatives on siblings of that pattern. e.g.

Given the .gitignore:
dir/*
!dir/sub1/sub2/**

The path `dir/a.text` would not be ignored.
parent bc74c53a
...@@ -429,18 +429,6 @@ bool git_attr_fnmatch__match( ...@@ -429,18 +429,6 @@ bool git_attr_fnmatch__match(
return (p_fnmatch(match->pattern, relpath, flags) != FNM_NOMATCH); return (p_fnmatch(match->pattern, relpath, flags) != FNM_NOMATCH);
} }
/* if path is a directory prefix of a negated pattern, then match */
if ((match->flags & GIT_ATTR_FNMATCH_NEGATIVE) && path->is_dir) {
size_t pathlen = strlen(relpath);
bool prefixed = (pathlen <= match->length) &&
((match->flags & GIT_ATTR_FNMATCH_ICASE) ?
!strncasecmp(match->pattern, relpath, pathlen) :
!strncmp(match->pattern, relpath, pathlen));
if (prefixed && git_path_at_end_of_segment(&match->pattern[pathlen]))
return true;
}
return (p_fnmatch(match->pattern, filename, flags) != FNM_NOMATCH); return (p_fnmatch(match->pattern, filename, flags) != FNM_NOMATCH);
} }
......
...@@ -1218,16 +1218,36 @@ void test_status_ignore__ignored_subdirfiles_with_subdir_rule(void) ...@@ -1218,16 +1218,36 @@ void test_status_ignore__ignored_subdirfiles_with_subdir_rule(void)
{ {
static const char *test_files[] = { static const char *test_files[] = {
"empty_standard_repo/dir/a.test", "empty_standard_repo/dir/a.test",
"empty_standard_repo/dir/sub1/b.test", "empty_standard_repo/dir/sub1/sub2/b.test",
NULL NULL
}; };
make_test_data("empty_standard_repo", test_files); make_test_data("empty_standard_repo", test_files);
cl_git_mkfile( cl_git_mkfile(
"empty_standard_repo/.gitignore", "empty_standard_repo/.gitignore",
"/dir/*\n" "dir/*\n"
"!/dir/sub1/sub2/**/*\n"); "!dir/sub1/sub2/**\n");
assert_is_ignored("dir/a.test"); assert_is_ignored("dir/a.test");
assert_is_ignored("dir/sub1/a.test"); assert_is_ignored("dir/sub1/a.test");
} }
void test_status_ignore__ignored_subdirfiles_with_negations(void)
{
static const char *test_files[] = {
"empty_standard_repo/dir/a.test",
"empty_standard_repo/dir/b.test",
"empty_standard_repo/dir/sub1/c.test",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
"dir/*\n"
"!dir/a.test\n");
refute_is_ignored("dir/a.test");
assert_is_ignored("dir/b.test");
assert_is_ignored("dir/sub1/c.test");
}
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