pathspec: do exact comparison on the leading non-wildcard part
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Sat, 24 Nov 2012 04:33:49 +0000 (11:33 +0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 26 Nov 2012 19:12:51 +0000 (11:12 -0800)
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
dir.c
dir.h
tree-walk.c

diff --git a/dir.c b/dir.c
index c391d46b2fc09bb242419513b2b6f2c422859eb9..f81e1d291758a462f434f555cd77f471faeecc5b 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -34,6 +34,21 @@ int fnmatch_icase(const char *pattern, const char *string, int flags)
        return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
 }
 
+inline int git_fnmatch(const char *pattern, const char *string,
+                      int flags, int prefix)
+{
+       int fnm_flags = 0;
+       if (flags & GFNM_PATHNAME)
+               fnm_flags |= FNM_PATHNAME;
+       if (prefix > 0) {
+               if (strncmp(pattern, string, prefix))
+                       return FNM_NOMATCH;
+               pattern += prefix;
+               string += prefix;
+       }
+       return fnmatch(pattern, string, fnm_flags);
+}
+
 static size_t common_prefix_len(const char **pathspec)
 {
        const char *n, *first;
@@ -230,7 +245,8 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
                        return MATCHED_RECURSIVELY;
        }
 
-       if (item->nowildcard_len < item->len && !fnmatch(match, name, 0))
+       if (item->nowildcard_len < item->len &&
+           !git_fnmatch(match, name, 0, item->nowildcard_len - prefix))
                return MATCHED_FNMATCH;
 
        return 0;
diff --git a/dir.h b/dir.h
index f5c89e3b80143f2508ac5b69d432aa82a4254751..0e8ae84628c2983c2bad9d636c5dec208d24c17e 100644 (file)
--- a/dir.h
+++ b/dir.h
@@ -139,4 +139,12 @@ extern int strcmp_icase(const char *a, const char *b);
 extern int strncmp_icase(const char *a, const char *b, size_t count);
 extern int fnmatch_icase(const char *pattern, const char *string, int flags);
 
+/*
+ * The prefix part of pattern must not contains wildcards.
+ */
+#define GFNM_PATHNAME 1                /* similar to FNM_PATHNAME */
+
+extern int git_fnmatch(const char *pattern, const char *string,
+                      int flags, int prefix);
+
 #endif
index af871c50d1a4a2e4311228a82d6ac4ab52a660b5..2fcf3c02da2377bd3cdf8df4bb235e852517683d 100644 (file)
@@ -627,7 +627,8 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
                                return entry_interesting;
 
                        if (item->nowildcard_len < item->len) {
-                               if (!fnmatch(match + baselen, entry->path, 0))
+                               if (!git_fnmatch(match + baselen, entry->path,
+                                                0, item->nowildcard_len - baselen))
                                        return entry_interesting;
 
                                /*
@@ -652,7 +653,8 @@ match_wildcards:
 
                strbuf_add(base, entry->path, pathlen);
 
-               if (!fnmatch(match, base->buf + base_offset, 0)) {
+               if (!git_fnmatch(match, base->buf + base_offset,
+                                0, item->nowildcard_len)) {
                        strbuf_setlen(base, base_offset + baselen);
                        return entry_interesting;
                }