pathspec: do exact comparison on the leading non-wildcard part

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 Nov 24, 2012 at 11:33 UTC 5d74762d87859d08fdf4c87ec9387e31e097acba
3 files changed +29 -3
dir.c
+17 -1
@@ -34,6 +34,21 @@ int fnmatch_icase(const char *pattern, const char *string, int flags)
34 return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
35 }
36
37 +inline int git_fnmatch(const char *pattern, const char *string,
38 + int flags, int prefix)
39 +{
40 + int fnm_flags = 0;
41 + if (flags & GFNM_PATHNAME)
42 + fnm_flags |= FNM_PATHNAME;
43 + if (prefix > 0) {
44 + if (strncmp(pattern, string, prefix))
45 + return FNM_NOMATCH;
46 + pattern += prefix;
47 + string += prefix;
48 + }
49 + return fnmatch(pattern, string, fnm_flags);
50 +}
51 +
52 static size_t common_prefix_len(const char **pathspec)
53 {
54 const char *n, *first;
@@ -230,7 +245,8 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
245 return MATCHED_RECURSIVELY;
246 }
247
233 - if (item->nowildcard_len < item->len && !fnmatch(match, name, 0))
248 + if (item->nowildcard_len < item->len &&
249 + !git_fnmatch(match, name, 0, item->nowildcard_len - prefix))
250 return MATCHED_FNMATCH;
251
252 return 0;
dir.h
+8
@@ -139,4 +139,12 @@ extern int strcmp_icase(const char *a, const char *b);
139 extern int strncmp_icase(const char *a, const char *b, size_t count);
140 extern int fnmatch_icase(const char *pattern, const char *string, int flags);
141
142 +/*
143 + * The prefix part of pattern must not contains wildcards.
144 + */
145 +#define GFNM_PATHNAME 1 /* similar to FNM_PATHNAME */
146 +
147 +extern int git_fnmatch(const char *pattern, const char *string,
148 + int flags, int prefix);
149 +
150 #endif
tree-walk.c
+4 -2
@@ -627,7 +627,8 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
627 return entry_interesting;
628
629 if (item->nowildcard_len < item->len) {
630 - if (!fnmatch(match + baselen, entry->path, 0))
630 + if (!git_fnmatch(match + baselen, entry->path,
631 + 0, item->nowildcard_len - baselen))
632 return entry_interesting;
633
634 /*
@@ -652,7 +653,8 @@ match_wildcards:
653
654 strbuf_add(base, entry->path, pathlen);
655
655 - if (!fnmatch(match, base->buf + base_offset, 0)) {
656 + if (!git_fnmatch(match, base->buf + base_offset,
657 + 0, item->nowildcard_len)) {
658 strbuf_setlen(base, base_offset + baselen);
659 return entry_interesting;
660 }