Skip to content

Commit 4c251e5

Browse files
pcloudsgitster
authored andcommitted
wildmatch: make /**/ match zero or more directories
"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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 40bbee0 commit 4c251e5

File tree

2 files changed

+19
-1
lines changed

2 files changed

+19
-1
lines changed

t/t3070-wildmatch.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,17 @@ match 1 1 ']' ']'
6363
match 0 0 'foo/baz/bar' 'foo*bar'
6464
match 0 0 'foo/baz/bar' 'foo**bar'
6565
match 0 1 'foobazbar' 'foo**bar'
66+
match 1 1 'foo/baz/bar' 'foo/**/bar'
67+
match 1 0 'foo/baz/bar' 'foo/**/**/bar'
68+
match 1 0 'foo/b/a/z/bar' 'foo/**/bar'
69+
match 1 0 'foo/b/a/z/bar' 'foo/**/**/bar'
70+
match 1 0 'foo/bar' 'foo/**/bar'
71+
match 1 0 'foo/bar' 'foo/**/**/bar'
6672
match 0 0 'foo/bar' 'foo?bar'
6773
match 0 0 'foo/bar' 'foo[/]bar'
6874
match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
6975
match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
70-
match 0 0 'foo' '**/foo'
76+
match 1 0 'foo' '**/foo'
7177
match 1 x '/foo' '**/foo'
7278
match 1 0 'bar/baz/foo' '**/foo'
7379
match 0 0 'bar/baz/foo' '*/foo'

wildmatch.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ static int dowild(const uchar *p, const uchar *text, int force_lower_case)
9090
if ((prev_p == text || *prev_p == '/') ||
9191
(*p == '\0' || *p == '/' ||
9292
(p[0] == '\\' && p[1] == '/'))) {
93+
/*
94+
* Assuming we already match 'foo/' and are at
95+
* <star star slash>, just assume it matches
96+
* nothing and go ahead match the rest of the
97+
* pattern with the remaining string. This
98+
* helps make foo/<*><*>/bar (<> because
99+
* otherwise it breaks C comment syntax) match
100+
* both foo/bar and foo/a/bar.
101+
*/
102+
if (p[0] == '/' &&
103+
dowild(p + 1, text, force_lower_case) == MATCH)
104+
return MATCH;
93105
special = TRUE;
94106
} else
95107
return ABORT_MALFORMED;

0 commit comments

Comments
 (0)