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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
diff --git a/src/attr_file.c b/src/attr_file.c
index 40c72ea..8619647 100644
--- a/src/attr_file.c
+++ b/src/attr_file.c
@@ -429,18 +429,6 @@ bool git_attr_fnmatch__match(
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);
}
diff --git a/tests/status/ignore.c b/tests/status/ignore.c
index f6c72c2..7256fb7 100644
--- a/tests/status/ignore.c
+++ b/tests/status/ignore.c
@@ -1218,16 +1218,36 @@ void test_status_ignore__ignored_subdirfiles_with_subdir_rule(void)
{
static const char *test_files[] = {
"empty_standard_repo/dir/a.test",
- "empty_standard_repo/dir/sub1/b.test",
+ "empty_standard_repo/dir/sub1/sub2/b.test",
NULL
};
make_test_data("empty_standard_repo", test_files);
cl_git_mkfile(
"empty_standard_repo/.gitignore",
- "/dir/*\n"
- "!/dir/sub1/sub2/**/*\n");
+ "dir/*\n"
+ "!dir/sub1/sub2/**\n");
assert_is_ignored("dir/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");
+}