Skip to content

Commit

Permalink
wildmatch: support "no FNM_PATHNAME" mode
Browse files Browse the repository at this point in the history
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
Nguyễn Thái Ngọc Duy authored and Junio C Hamano committed Jan 1, 2013
1 parent 0c52816 commit c41244e
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 7 deletions.
2 changes: 1 addition & 1 deletion dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
27 changes: 27 additions & 0 deletions t/t3070-wildmatch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
6 changes: 4 additions & 2 deletions test-wildmatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 9 additions & 4 deletions wildmatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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] == '/'))) {
/*
Expand All @@ -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. */
Expand Down Expand Up @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions wildmatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define WILDMATCH_H

#define WM_CASEFOLD 1
#define WM_PATHNAME 2

#define WM_ABORT_MALFORMED 2
#define WM_NOMATCH 1
Expand Down

0 comments on commit c41244e

Please sign in to comment.