"foo/**/bar" matches "foo/x/bar", "foo/x/y/bar"... but not "foo/bar". We make a special case, when foo/**/ is detected (and "foo/" part is already matched), try matching "bar" with the rest of the string. "Match one or more directories" semantics can be easily achieved using "foo/*/**/bar". This also makes "**/foo" match "foo" in addition to "x/foo", "x/y/foo".. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- t/t3070-wildmatch.sh | 8 +++++++- wildmatch.c | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh index d320f84..a247a36 100755 --- a/t/t3070-wildmatch.sh +++ b/t/t3070-wildmatch.sh @@ -52,11 +52,17 @@ match 1 1 ']' ']' # Extended slash-matching features match 0 0 'foo/baz/bar' 'foo*bar' match 0 0 'foo/baz/bar' 'foo**bar' +match 1 1 'foo/baz/bar' 'foo/**/bar' +match 1 0 'foo/baz/bar' 'foo/**/**/bar' +match 1 0 'foo/b/a/z/bar' 'foo/**/bar' +match 1 0 'foo/b/a/z/bar' 'foo/**/**/bar' +match 1 0 'foo/bar' 'foo/**/bar' +match 1 0 'foo/bar' 'foo/**/**/bar' match 0 0 'foo/bar' 'foo?bar' match 0 0 'foo/bar' 'foo[/]bar' match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r' match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r' -match 0 0 'foo' '**/foo' +match 1 0 'foo' '**/foo' match 1 1 '/foo' '**/foo' match 1 0 'bar/baz/foo' '**/foo' match 0 0 'bar/baz/foo' '*/foo' diff --git a/wildmatch.c b/wildmatch.c index 1b39346..4069b2d 100644 --- a/wildmatch.c +++ b/wildmatch.c @@ -96,6 +96,23 @@ static int dowild(const uchar *p, const uchar *text, int force_lower_case) if ((prev_p == text || *prev_p == '/') || (*p == '\0' || *p == '/' || (p[0] == '\\' && p[1] == '/'))) { + /* + * Assuming we already match 'foo/' and are at + * <star star slash>, just assume it matches + * nothing and go ahead match the rest of the + * pattern with the remaining string. This + * helps make foo/<*><*>/bar (<> because + * otherwise it breaks C comment syntax) match + * both foo/bar and foo/a/bar. + * + * Crazy patterns like /<*><*>/<*><*>/ are + * treated like /<*><*>/. But undefined + * behavior is even appropriate for people + * writing such a pattern. + */ + if (p[0] == '/' && + dowild(p + 1, text, force_lower_case) == TRUE) + return TRUE; special = TRUE; } else special = FALSE; -- 1.8.0.rc0.29.g1fdd78f -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html