Commit 84ce9746ae0699d61fc1c57ccec4887d98e1dfc1

Edward Thomson 2021-07-14T08:39:24

Merge pull request #5824 from palmin/fix-ignore-negate fix check for ignoring of negate rules

diff --git a/src/ignore.c b/src/ignore.c
index 700a672..948c58d 100644
--- a/src/ignore.c
+++ b/src/ignore.c
@@ -101,7 +101,7 @@ static int does_negate_pattern(git_attr_fnmatch *rule, git_attr_fnmatch *neg)
  */
 static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match)
 {
-	int error = 0, wildmatch_flags;
+	int error = 0, wildmatch_flags, effective_flags;
 	size_t i;
 	git_attr_fnmatch *rule;
 	char *path;
@@ -141,8 +141,17 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
 		if (git_buf_oom(&buf))
 			goto out;
 
+		/*
+		 * if rule isn't for full path we match without PATHNAME flag
+		 * as lines like *.txt should match something like dir/test.txt
+		 * requiring * to also match /
+		 */
+		effective_flags = wildmatch_flags;
+		if (!(rule->flags & GIT_ATTR_FNMATCH_FULLPATH))
+			effective_flags &= ~WM_PATHNAME;
+
 		/* if we found a match, we want to keep this rule */
-		if ((wildmatch(git_buf_cstr(&buf), path, wildmatch_flags)) == WM_MATCH) {
+		if ((wildmatch(git_buf_cstr(&buf), path, effective_flags)) == WM_MATCH) {
 			*out = 1;
 			error = 0;
 			goto out;
@@ -639,4 +648,3 @@ int git_ignore__check_pathspec_for_exact_ignores(
 
 	return error;
 }
-
diff --git a/tests/ignore/path.c b/tests/ignore/path.c
index 5d53c9d..d55bdc5 100644
--- a/tests/ignore/path.c
+++ b/tests/ignore/path.c
@@ -575,3 +575,11 @@ void test_ignore_path__negative_prefix_rule(void)
 	assert_is_ignored(true, "ff");
 	assert_is_ignored(false, "f");
 }
+
+void test_ignore_path__negative_more_specific(void)
+{
+	cl_git_rewritefile("attr/.gitignore", "*.txt\n!/dir/test.txt\n");
+	assert_is_ignored(true, "test.txt");
+	assert_is_ignored(false, "dir/test.txt");
+	assert_is_ignored(true, "outer/dir/test.txt");
+}