diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2013-01-01 09:44:07 +0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2013-01-01 15:32:37 -0800 |
commit | c41244e702fd4fc1039f39a3915ae1e5f165bbf3 (patch) | |
tree | 2556fe7cadc647a95290472a832e32a784985090 | |
parent | 0c528168dadd4209de0213a16ff811a89ee3f206 (diff) | |
download | git-c41244e702fd4fc1039f39a3915ae1e5f165bbf3.tar.gz |
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>
-rw-r--r-- | dir.c | 2 | ||||
-rwxr-xr-x | t/t3070-wildmatch.sh | 27 | ||||
-rw-r--r-- | test-wildmatch.c | 6 | ||||
-rw-r--r-- | wildmatch.c | 13 | ||||
-rw-r--r-- | wildmatch.h | 1 |
5 files changed, 42 insertions, 7 deletions
@@ -595,7 +595,7 @@ int match_pathname(const char *pathname, int pathlen, } return wildmatch(pattern, name, - ignore_case ? WM_CASEFOLD : 0, + WM_PATHNAME | (ignore_case ? WM_CASEFOLD : 0), NULL) == 0; } diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh index af54c83111..5c9601a0c8 100755 --- a/t/t3070-wildmatch.sh +++ b/t/t3070-wildmatch.sh @@ -29,6 +29,18 @@ match() { fi } +pathmatch() { + if [ $1 = 1 ]; then + test_expect_success "pathmatch: match '$2' '$3'" " + test-wildmatch pathmatch '$2' '$3' + " + else + test_expect_success "pathmatch: no match '$2' '$3'" " + ! test-wildmatch pathmatch '$2' '$3' + " + fi +} + # Basic wildmat features match 1 1 foo foo 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/*/ match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t' match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t' +pathmatch 1 foo foo +pathmatch 0 foo fo +pathmatch 1 foo/bar foo/bar +pathmatch 1 foo/bar 'foo/*' +pathmatch 1 foo/bba/arr 'foo/*' +pathmatch 1 foo/bba/arr 'foo/**' +pathmatch 1 foo/bba/arr 'foo*' +pathmatch 1 foo/bba/arr 'foo**' +pathmatch 1 foo/bba/arr 'foo/*arr' +pathmatch 1 foo/bba/arr 'foo/**arr' +pathmatch 0 foo/bba/arr 'foo/*z' +pathmatch 0 foo/bba/arr 'foo/**z' +pathmatch 1 foo/bar 'foo?bar' +pathmatch 1 foo/bar 'foo[/]bar' + test_done diff --git a/test-wildmatch.c b/test-wildmatch.c index 4bb23b4c92..a5f4833770 100644 --- a/test-wildmatch.c +++ b/test-wildmatch.c @@ -12,9 +12,11 @@ int main(int argc, char **argv) argv[i] += 3; } if (!strcmp(argv[1], "wildmatch")) - return !!wildmatch(argv[3], argv[2], 0, NULL); + return !!wildmatch(argv[3], argv[2], WM_PATHNAME, NULL); else if (!strcmp(argv[1], "iwildmatch")) - return !!wildmatch(argv[3], argv[2], WM_CASEFOLD, NULL); + return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD, NULL); + else if (!strcmp(argv[1], "pathmatch")) + return !!wildmatch(argv[3], argv[2], 0, NULL); else if (!strcmp(argv[1], "fnmatch")) return !!fnmatch(argv[3], argv[2], FNM_PATHNAME); else diff --git a/wildmatch.c b/wildmatch.c index 1b5bbacf1a..536470b794 100644 --- a/wildmatch.c +++ b/wildmatch.c @@ -78,14 +78,17 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) continue; case '?': /* Match anything but '/'. */ - if (t_ch == '/') + if ((flags & WM_PATHNAME) && t_ch == '/') return WM_NOMATCH; continue; case '*': if (*++p == '*') { const uchar *prev_p = p - 2; while (*++p == '*') {} - if ((prev_p < pattern || *prev_p == '/') && + if (!(flags & WM_PATHNAME)) + /* without WM_PATHNAME, '*' == '**' */ + match_slash = 1; + else if ((prev_p < pattern || *prev_p == '/') && (*p == '\0' || *p == '/' || (p[0] == '\\' && p[1] == '/'))) { /* @@ -104,7 +107,8 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) } else return WM_ABORT_MALFORMED; } else - match_slash = 0; + /* without WM_PATHNAME, '*' == '**' */ + match_slash = flags & WM_PATHNAME ? 0 : 1; if (*p == '\0') { /* Trailing "**" matches everything. Trailing "*" matches * only if there are no more slash characters. */ @@ -215,7 +219,8 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags) } else if (t_ch == p_ch) matched = 1; } while (prev_ch = p_ch, (p_ch = *++p) != ']'); - if (matched == negated || t_ch == '/') + if (matched == negated || + ((flags & WM_PATHNAME) && t_ch == '/')) return WM_NOMATCH; continue; } diff --git a/wildmatch.h b/wildmatch.h index 1c814fd5ff..4090c8f4bb 100644 --- a/wildmatch.h +++ b/wildmatch.h @@ -2,6 +2,7 @@ #define WILDMATCH_H #define WM_CASEFOLD 1 +#define WM_PATHNAME 2 #define WM_ABORT_MALFORMED 2 #define WM_NOMATCH 1 |