pathspec: apply "*.c" optimization from exclude
[gitweb.git] / dir.c
diff --git a/dir.c b/dir.c
index f81e1d291758a462f434f555cd77f471faeecc5b..9afd388604c05b5c7f7c34cd19f1e6ff2a14fdce 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -46,6 +46,13 @@ inline int git_fnmatch(const char *pattern, const char *string,
                pattern += prefix;
                string += prefix;
        }
+       if (flags & GFNM_ONESTAR) {
+               int pattern_len = strlen(++pattern);
+               int string_len = strlen(string);
+               return string_len < pattern_len ||
+                      strcmp(pattern,
+                             string + string_len - pattern_len);
+       }
        return fnmatch(pattern, string, fnm_flags);
 }
 
@@ -246,7 +253,9 @@ static int match_pathspec_item(const struct pathspec_item *item, int prefix,
        }
 
        if (item->nowildcard_len < item->len &&
-           !git_fnmatch(match, name, 0, item->nowildcard_len - prefix))
+           !git_fnmatch(match, name,
+                        item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
+                        item->nowildcard_len - prefix))
                return MATCHED_FNMATCH;
 
        return 0;
@@ -1446,8 +1455,13 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
                item->match = path;
                item->len = strlen(path);
                item->nowildcard_len = simple_length(path);
-               if (item->nowildcard_len < item->len)
+               item->flags = 0;
+               if (item->nowildcard_len < item->len) {
                        pathspec->has_wildcard = 1;
+                       if (path[item->nowildcard_len] == '*' &&
+                           no_wildcard(path + item->nowildcard_len + 1))
+                               item->flags |= PATHSPEC_ONESTAR;
+               }
        }
 
        qsort(pathspec->items, pathspec->nr,