mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-30 11:15:04 +00:00
ignore: fix directory limits when searching for star-star
In order to match the star-star, we disable the flag that's looking for a single path element, but that leads to searching for the pattern in the middle of elements in the input string. Mark when we're handing a star-star so we jump over the elements in our attempt to match the part of the pattern that comes after the star-star. While here, tighten up the check so we don't allow invalid rules through.
This commit is contained in:
parent
0f36271646
commit
1c3018eb12
@ -69,7 +69,8 @@ p_fnmatchx(const char *pattern, const char *string, int flags, size_t recurs)
|
|||||||
if (recurs-- == 0)
|
if (recurs-- == 0)
|
||||||
return FNM_NORES;
|
return FNM_NORES;
|
||||||
|
|
||||||
for (stringstart = string;;)
|
for (stringstart = string;;) {
|
||||||
|
bool match_slash = false;
|
||||||
switch (c = *pattern++) {
|
switch (c = *pattern++) {
|
||||||
case EOS:
|
case EOS:
|
||||||
if ((flags & FNM_LEADING_DIR) && *string == '/')
|
if ((flags & FNM_LEADING_DIR) && *string == '/')
|
||||||
@ -93,11 +94,17 @@ p_fnmatchx(const char *pattern, const char *string, int flags, size_t recurs)
|
|||||||
* It will be restored if/when we recurse below.
|
* It will be restored if/when we recurse below.
|
||||||
*/
|
*/
|
||||||
if (c == '*') {
|
if (c == '*') {
|
||||||
|
c = *++pattern;
|
||||||
|
/* star-star-slash is at the end, match by default */
|
||||||
|
if (c == EOS)
|
||||||
|
return 0;
|
||||||
|
/* Double-star must be at end or between slashes */
|
||||||
|
if (c != '/')
|
||||||
|
return (FNM_NOMATCH);
|
||||||
|
|
||||||
|
c = *++pattern;
|
||||||
flags &= ~FNM_PATHNAME;
|
flags &= ~FNM_PATHNAME;
|
||||||
while (c == '*')
|
match_slash = true;
|
||||||
c = *++pattern;
|
|
||||||
if (c == '/')
|
|
||||||
c = *++pattern;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||||
@ -128,8 +135,18 @@ p_fnmatchx(const char *pattern, const char *string, int flags, size_t recurs)
|
|||||||
return e;
|
return e;
|
||||||
if (test == '/' && (flags & FNM_PATHNAME))
|
if (test == '/' && (flags & FNM_PATHNAME))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* searching for star-star, so we jump over entire dirs */
|
||||||
|
if (match_slash) {
|
||||||
|
const char *slash;
|
||||||
|
if (!(slash = strchr(string, '/')))
|
||||||
|
break;
|
||||||
|
|
||||||
|
string = slash + 1;
|
||||||
|
} else {
|
||||||
++string;
|
++string;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return (FNM_NOMATCH);
|
return (FNM_NOMATCH);
|
||||||
case '[':
|
case '[':
|
||||||
if (*string == EOS)
|
if (*string == EOS)
|
||||||
@ -170,6 +187,7 @@ p_fnmatchx(const char *pattern, const char *string, int flags, size_t recurs)
|
|||||||
++string;
|
++string;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,13 +134,25 @@ void test_attr_ignore__leading_stars(void)
|
|||||||
|
|
||||||
void test_attr_ignore__globs_and_path_delimiters(void)
|
void test_attr_ignore__globs_and_path_delimiters(void)
|
||||||
{
|
{
|
||||||
|
cl_git_rewritefile("attr/.gitignore", "foo/bar/**");
|
||||||
|
assert_is_ignored(true, "foo/bar/baz");
|
||||||
|
assert_is_ignored(true, "foo/bar/baz/quux");
|
||||||
|
|
||||||
|
cl_git_rewritefile("attr/.gitignore", "_*/");
|
||||||
|
assert_is_ignored(true, "sub/_test/a/file");
|
||||||
|
assert_is_ignored(false, "test_folder/file");
|
||||||
|
assert_is_ignored(true, "_test/file");
|
||||||
|
assert_is_ignored(true, "_test/a/file");
|
||||||
|
|
||||||
cl_git_rewritefile("attr/.gitignore", "**/_*/");
|
cl_git_rewritefile("attr/.gitignore", "**/_*/");
|
||||||
|
assert_is_ignored(true, "sub/_test/a/file");
|
||||||
assert_is_ignored(false, "test_folder/file");
|
assert_is_ignored(false, "test_folder/file");
|
||||||
assert_is_ignored(true, "_test/file");
|
assert_is_ignored(true, "_test/file");
|
||||||
assert_is_ignored(true, "_test/a/file");
|
assert_is_ignored(true, "_test/a/file");
|
||||||
|
|
||||||
cl_git_rewritefile("attr/.gitignore", "**/_*/foo/bar/*ux");
|
cl_git_rewritefile("attr/.gitignore", "**/_*/foo/bar/*ux");
|
||||||
|
|
||||||
|
assert_is_ignored(true, "sub/_test/foo/bar/qux/file");
|
||||||
assert_is_ignored(true, "_test/foo/bar/qux/file");
|
assert_is_ignored(true, "_test/foo/bar/qux/file");
|
||||||
assert_is_ignored(true, "_test/foo/bar/crux/file");
|
assert_is_ignored(true, "_test/foo/bar/crux/file");
|
||||||
assert_is_ignored(false, "_test/foo/bar/code/file");
|
assert_is_ignored(false, "_test/foo/bar/code/file");
|
||||||
|
Loading…
Reference in New Issue
Block a user