Skip to content

Commit 4698344

Browse files
pcloudsgitster
authored andcommitted
wildmatch: make a special case for "*/" with FNM_PATHNAME
Normally we need recursion for "*". In this case we know that it matches everything until "/" so we can skip the recursion. glibc, '*/*/*' on linux-2.6.git file list 2000 times before: wildmatch 8s 74513us fnmatch 1s 97042us or 13.59% faster after: wildmatch 3s 521862us fnmatch 3s 488616us or 99.06% slower Same test with compat/fnmatch: wildmatch 8s 110763us fnmatch 2s 980845us or 36.75% faster wildmatch 3s 522156us fnmatch 1s 544487us or 43.85% slower Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1b25892 commit 4698344

File tree

2 files changed

+20
-0
lines changed

2 files changed

+20
-0
lines changed

t/t3070-wildmatch.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ match 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/
203203
match 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
204204
match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
205205
match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
206+
match 0 x foo '*/*/*'
207+
match 0 x foo/bar '*/*/*'
208+
match 1 x foo/bba/arr '*/*/*'
209+
match 0 x foo/bb/aa/rr '*/*/*'
206210

207211
pathmatch 1 foo foo
208212
pathmatch 0 foo fo
@@ -218,5 +222,9 @@ pathmatch 0 foo/bba/arr 'foo/*z'
218222
pathmatch 0 foo/bba/arr 'foo/**z'
219223
pathmatch 1 foo/bar 'foo?bar'
220224
pathmatch 1 foo/bar 'foo[/]bar'
225+
pathmatch 0 foo '*/*/*'
226+
pathmatch 0 foo/bar '*/*/*'
227+
pathmatch 1 foo/bba/arr '*/*/*'
228+
pathmatch 1 foo/bb/aa/rr '*/*/*'
221229

222230
test_done

wildmatch.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,18 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
117117
return WM_NOMATCH;
118118
}
119119
return WM_MATCH;
120+
} else if (!match_slash && *p == '/') {
121+
/*
122+
* _one_ asterisk followed by a slash
123+
* with WM_PATHNAME matches the next
124+
* directory
125+
*/
126+
const char *slash = strchr((char*)text, '/');
127+
if (!slash)
128+
return WM_NOMATCH;
129+
text = (const uchar*)slash;
130+
/* the slash is consumed by the top-level for loop */
131+
break;
120132
}
121133
while (1) {
122134
if (t_ch == '\0')

0 commit comments

Comments
 (0)