Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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>
  • Loading branch information...
commit c41244e702fd4fc1039f39a3915ae1e5f165bbf3 1 parent 0c52816
Nguyễn Thái Ngọc Duy authored January 01, 2013 gitster committed January 01, 2013
2  dir.c
@@ -595,7 +595,7 @@ int match_pathname(const char *pathname, int pathlen,
595 595
 	}
596 596
 
597 597
 	return wildmatch(pattern, name,
598  
-			 ignore_case ? WM_CASEFOLD : 0,
  598
+			 WM_PATHNAME | (ignore_case ? WM_CASEFOLD : 0),
599 599
 			 NULL) == 0;
600 600
 }
601 601
 
27  t/t3070-wildmatch.sh
@@ -29,6 +29,18 @@ match() {
29 29
     fi
30 30
 }
31 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
+
32 44
 # Basic wildmat features
33 45
 match 1 1 foo foo
34 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/*/
192 204
 match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
193 205
 match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
194 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
+
195 222
 test_done
6  test-wildmatch.c
@@ -12,9 +12,11 @@ int main(int argc, char **argv)
12 12
 			argv[i] += 3;
13 13
 	}
14 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 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);
18 20
 	else if (!strcmp(argv[1], "fnmatch"))
19 21
 		return !!fnmatch(argv[3], argv[2], FNM_PATHNAME);
20 22
 	else
13  wildmatch.c
@@ -78,14 +78,17 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
78 78
 			continue;
79 79
 		case '?':
80 80
 			/* Match anything but '/'. */
81  
-			if (t_ch == '/')
  81
+			if ((flags & WM_PATHNAME) && t_ch == '/')
82 82
 				return WM_NOMATCH;
83 83
 			continue;
84 84
 		case '*':
85 85
 			if (*++p == '*') {
86 86
 				const uchar *prev_p = p - 2;
87 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 == '/') &&
89 92
 				    (*p == '\0' || *p == '/' ||
90 93
 				     (p[0] == '\\' && p[1] == '/'))) {
91 94
 					/*
@@ -104,7 +107,8 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
104 107
 				} else
105 108
 					return WM_ABORT_MALFORMED;
106 109
 			} else
107  
-				match_slash = 0;
  110
+				/* without WM_PATHNAME, '*' == '**' */
  111
+				match_slash = flags & WM_PATHNAME ? 0 : 1;
108 112
 			if (*p == '\0') {
109 113
 				/* Trailing "**" matches everything.  Trailing "*" matches
110 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)
215 219
 				} else if (t_ch == p_ch)
216 220
 					matched = 1;
217 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 == '/'))
219 224
 				return WM_NOMATCH;
220 225
 			continue;
221 226
 		}
1  wildmatch.h
@@ -2,6 +2,7 @@
2 2
 #define WILDMATCH_H
3 3
 
4 4
 #define WM_CASEFOLD 1
  5
+#define WM_PATHNAME 2
5 6
 
6 7
 #define WM_ABORT_MALFORMED 2
7 8
 #define WM_NOMATCH 1

0 notes on commit c41244e

Please sign in to comment.
Something went wrong with that request. Please try again.