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 <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Nguyễn Thái Ngọc Duy committed
Jan 1, 2013 at 09:44 UTC
c41244e702fd4fc1039f39a3915ae1e5f165bbf3
5 files changed
+42
-7
dir.c
+1
-1
@@ -595,7 +595,7 @@ int match_pathname(const char *pathname, int pathlen,
595
}
596
597
return wildmatch(pattern, name,
598
- ignore_case ? WM_CASEFOLD : 0,
598
+ WM_PATHNAME | (ignore_case ? WM_CASEFOLD : 0),
599
NULL) == 0;
600
}
601
t/t3070-wildmatch.sh
+27
@@ -29,6 +29,18 @@ match() {
29
fi
30
}
31
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
+
44
# Basic wildmat features
45
match 1 1 foo foo
46
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/*/
204
match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
205
match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
206
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
+
222
test_done
test-wildmatch.c
+4
-2
@@ -12,9 +12,11 @@ int main(int argc, char **argv)
12
argv[i] += 3;
13
}
14
if (!strcmp(argv[1], "wildmatch"))
15
- return !!wildmatch(argv[3], argv[2], 0, NULL);
15
+ return !!wildmatch(argv[3], argv[2], WM_PATHNAME, NULL);
16
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);
20
else if (!strcmp(argv[1], "fnmatch"))
21
return !!fnmatch(argv[3], argv[2], FNM_PATHNAME);
22
else
wildmatch.c
+9
-4
@@ -78,14 +78,17 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
78
continue;
79
case '?':
80
/* Match anything but '/'. */
81
- if (t_ch == '/')
81
+ if ((flags & WM_PATHNAME) && t_ch == '/')
82
return WM_NOMATCH;
83
continue;
84
case '*':
85
if (*++p == '*') {
86
const uchar *prev_p = p - 2;
87
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 == '/') &&
92
(*p == '\0' || *p == '/' ||
93
(p[0] == '\\' && p[1] == '/'))) {
94
/*
@@ -104,7 +107,8 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
107
} else
108
return WM_ABORT_MALFORMED;
109
} else
107
- match_slash = 0;
110
+ /* without WM_PATHNAME, '*' == '**' */
111
+ match_slash = flags & WM_PATHNAME ? 0 : 1;
112
if (*p == '\0') {
113
/* Trailing "**" matches everything. Trailing "*" matches
114
* only if there are no more slash characters. */
@@ -215,7 +219,8 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
219
} else if (t_ch == p_ch)
220
matched = 1;
221
} while (prev_ch = p_ch, (p_ch = *++p) != ']');
218
- if (matched == negated || t_ch == '/')
222
+ if (matched == negated ||
223
+ ((flags & WM_PATHNAME) && t_ch == '/'))
224
return WM_NOMATCH;
225
continue;
226
}
wildmatch.h
+1
@@ -2,6 +2,7 @@
2
#define WILDMATCH_H
3
4
#define WM_CASEFOLD 1
5
+#define WM_PATHNAME 2
6
7
#define WM_ABORT_MALFORMED 2
8
#define WM_NOMATCH 1