Skip to content

Commit c41244e

Browse files
pcloudsgitster
authored andcommitted
wildmatch: support "no FNM_PATHNAME" mode
So far, wildmatch() has always honoured directory boundary and there was no way to turn it off. Make it behave more like fnmatch() by requiring all callers that want the FNM_PATHNAME behaviour to pass that in the equivalent flag WM_PATHNAME. Callers that do not specify WM_PATHNAME will get wildcards like ? and * in their patterns matched against '/', just like not passing FNM_PATHNAME to fnmatch(). Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0c52816 commit c41244e

File tree

5 files changed

+42
-7
lines changed

5 files changed

+42
-7
lines changed

dir.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ int match_pathname(const char *pathname, int pathlen,
595595
}
596596

597597
return wildmatch(pattern, name,
598-
ignore_case ? WM_CASEFOLD : 0,
598+
WM_PATHNAME | (ignore_case ? WM_CASEFOLD : 0),
599599
NULL) == 0;
600600
}
601601

t/t3070-wildmatch.sh

+27
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,18 @@ match() {
2929
fi
3030
}
3131

32+
pathmatch() {
33+
if [ $1 = 1 ]; then
34+
test_expect_success "pathmatch: match '$2' '$3'" "
35+
test-wildmatch pathmatch '$2' '$3'
36+
"
37+
else
38+
test_expect_success "pathmatch: no match '$2' '$3'" "
39+
! test-wildmatch pathmatch '$2' '$3'
40+
"
41+
fi
42+
}
43+
3244
# Basic wildmat features
3345
match 1 1 foo foo
3446
match 0 0 foo bar
@@ -192,4 +204,19 @@ match 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/
192204
match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
193205
match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
194206

207+
pathmatch 1 foo foo
208+
pathmatch 0 foo fo
209+
pathmatch 1 foo/bar foo/bar
210+
pathmatch 1 foo/bar 'foo/*'
211+
pathmatch 1 foo/bba/arr 'foo/*'
212+
pathmatch 1 foo/bba/arr 'foo/**'
213+
pathmatch 1 foo/bba/arr 'foo*'
214+
pathmatch 1 foo/bba/arr 'foo**'
215+
pathmatch 1 foo/bba/arr 'foo/*arr'
216+
pathmatch 1 foo/bba/arr 'foo/**arr'
217+
pathmatch 0 foo/bba/arr 'foo/*z'
218+
pathmatch 0 foo/bba/arr 'foo/**z'
219+
pathmatch 1 foo/bar 'foo?bar'
220+
pathmatch 1 foo/bar 'foo[/]bar'
221+
195222
test_done

test-wildmatch.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ int main(int argc, char **argv)
1212
argv[i] += 3;
1313
}
1414
if (!strcmp(argv[1], "wildmatch"))
15-
return !!wildmatch(argv[3], argv[2], 0, NULL);
15+
return !!wildmatch(argv[3], argv[2], WM_PATHNAME, NULL);
1616
else if (!strcmp(argv[1], "iwildmatch"))
17-
return !!wildmatch(argv[3], argv[2], WM_CASEFOLD, NULL);
17+
return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD, NULL);
18+
else if (!strcmp(argv[1], "pathmatch"))
19+
return !!wildmatch(argv[3], argv[2], 0, NULL);
1820
else if (!strcmp(argv[1], "fnmatch"))
1921
return !!fnmatch(argv[3], argv[2], FNM_PATHNAME);
2022
else

wildmatch.c

+9-4
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,17 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
7878
continue;
7979
case '?':
8080
/* Match anything but '/'. */
81-
if (t_ch == '/')
81+
if ((flags & WM_PATHNAME) && t_ch == '/')
8282
return WM_NOMATCH;
8383
continue;
8484
case '*':
8585
if (*++p == '*') {
8686
const uchar *prev_p = p - 2;
8787
while (*++p == '*') {}
88-
if ((prev_p < pattern || *prev_p == '/') &&
88+
if (!(flags & WM_PATHNAME))
89+
/* without WM_PATHNAME, '*' == '**' */
90+
match_slash = 1;
91+
else if ((prev_p < pattern || *prev_p == '/') &&
8992
(*p == '\0' || *p == '/' ||
9093
(p[0] == '\\' && p[1] == '/'))) {
9194
/*
@@ -104,7 +107,8 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
104107
} else
105108
return WM_ABORT_MALFORMED;
106109
} else
107-
match_slash = 0;
110+
/* without WM_PATHNAME, '*' == '**' */
111+
match_slash = flags & WM_PATHNAME ? 0 : 1;
108112
if (*p == '\0') {
109113
/* Trailing "**" matches everything. Trailing "*" matches
110114
* only if there are no more slash characters. */
@@ -215,7 +219,8 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
215219
} else if (t_ch == p_ch)
216220
matched = 1;
217221
} while (prev_ch = p_ch, (p_ch = *++p) != ']');
218-
if (matched == negated || t_ch == '/')
222+
if (matched == negated ||
223+
((flags & WM_PATHNAME) && t_ch == '/'))
219224
return WM_NOMATCH;
220225
continue;
221226
}

wildmatch.h

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define WILDMATCH_H
33

44
#define WM_CASEFOLD 1
5+
#define WM_PATHNAME 2
56

67
#define WM_ABORT_MALFORMED 2
78
#define WM_NOMATCH 1

0 commit comments

Comments
 (0)