Commit 6f6340af by Patrick Steinhardt

ignore: fix determining whether a shorter pattern negates another

When computing whether we need to store a negative pattern, we iterate
through all previously known patterns and check whether the negative
pattern undoes any of the previous ones. In doing so we call `wildmatch`
and check it's return for any negative error values. If there was a
negative return, we will abort and bubble up that error to the caller.

In fact, this check for negative values stems from the time where we
still used `fnmatch` instead of `wildmatch`. For `fnmatch`, negative
values indicate a "real" error, while for `wildmatch` a negative value
may be returned if the matching was prematurely aborted. A premature
abort may for example also happen if the pattern matches a prefix of the
haystack if the pattern is shorter. Returning an error in that case is
the wrong thing to do.

Fix the code to compare for equality with `WM_MATCH`, only. Negative
values returned by `wildmatch` are perfectly fine and thus should be
ignored. Add a test that verifies we do not see the error.
parent 368b9795
......@@ -141,13 +141,8 @@ static int does_negate_rule(int *out, git_vector *rules, git_attr_fnmatch *match
if (git_buf_oom(&buf))
goto out;
if ((error = wildmatch(git_buf_cstr(&buf), path, wildmatch_flags)) < 0) {
git_error_set(GIT_ERROR_INVALID, "error matching pattern");
goto out;
}
/* if we found a match, we want to keep this rule */
if (error != WM_NOMATCH) {
if ((wildmatch(git_buf_cstr(&buf), path, wildmatch_flags)) == WM_MATCH) {
*out = 1;
error = 0;
goto out;
......
......@@ -560,3 +560,18 @@ void test_ignore_path__escaped_space(void)
assert_is_ignored(false, "bar\\\\\\");
assert_is_ignored(false, "bar\\\\\\ ");
}
void test_ignore_path__invalid_pattern(void)
{
cl_git_rewritefile("attr/.gitignore", "[");
assert_is_ignored(false, "[f");
assert_is_ignored(false, "f");
}
void test_ignore_path__negative_prefix_rule(void)
{
cl_git_rewritefile("attr/.gitignore", "ff*\n!f\n");
assert_is_ignored(true, "fff");
assert_is_ignored(true, "ff");
assert_is_ignored(false, "f");
}
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