:(glob)path differs from path that it uses wildmatch with
FNM_PATHNAME while plain "path" uses fnmatch without FNM_PATHNAME.

git_fnmatch() was probably ill-designed. It was intended to cover
other use of fnmatch besides pathspec. But so far it's only used by
pathspec code.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 builtin/add.c |  9 +++++++--
 cache.h       |  1 +
 dir.c         | 34 ++++++++++++++++++++++------------
 dir.h         |  8 +++-----
 setup.c       |  1 +
 tree-walk.c   | 11 ++++++-----
 6 files changed, 40 insertions(+), 24 deletions(-)

diff --git a/builtin/add.c b/builtin/add.c
index d09a07a..1b99e2b 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -416,11 +416,16 @@ int cmd_add(int argc, const char **argv, const char 
*prefix)
                /*
                 * file_exists() assumes exact match
                 */
-               GUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);
+               GUARD_PATHSPEC(&pathspec,
+                              PATHSPEC_FROMTOP |
+                              PATHSPEC_LITERAL |
+                              PATHSPEC_GLOB);
 
                for (i = 0; i < pathspec.nr; i++) {
                        const char *path = pathspec.items[i].match;
-                       if (!seen[i] && !file_exists(path)) {
+                       if (!seen[i] &&
+                           ((pathspec.items[i].magic & PATHSPEC_GLOB) ||
+                            !file_exists(path))) {
                                if (ignore_missing) {
                                        int dtype = DT_UNKNOWN;
                                        if (is_path_excluded(&check, path, -1, 
&dtype))
diff --git a/cache.h b/cache.h
index fb54876..9c27f18 100644
--- a/cache.h
+++ b/cache.h
@@ -479,6 +479,7 @@ extern int ie_modified(const struct index_state *, struct 
cache_entry *, struct
 /* Pathspec magic */
 #define PATHSPEC_FROMTOP    (1<<0)
 #define PATHSPEC_LITERAL    (1<<1)
+#define PATHSPEC_GLOB       (1<<2)
 
 #define PATHSPEC_ONESTAR 1     /* the pathspec pattern sastisfies GFNM_ONESTAR 
*/
 
diff --git a/dir.c b/dir.c
index 63d07cd..760b776 100644
--- a/dir.c
+++ b/dir.c
@@ -37,26 +37,28 @@ 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)
+inline int git_fnmatch(const struct pathspec_item *item,
+                      const char *pattern, const char *string,
+                      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;
        }
-       if (flags & GFNM_ONESTAR) {
+       if (item->flags & PATHSPEC_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);
+       if (item->magic & PATHSPEC_GLOB)
+               return wildmatch(pattern, string, 0);
+       else
+               /* wildmatch has not learned no FNM_PATHNAME mode yet */
+               return fnmatch(pattern, string, 0);
 }
 
 static size_t common_prefix_len(const struct pathspec *pathspec)
@@ -64,7 +66,10 @@ static size_t common_prefix_len(const struct pathspec 
*pathspec)
        int n;
        size_t max = 0;
 
-       GUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);
+       GUARD_PATHSPEC(pathspec,
+                      PATHSPEC_FROMTOP |
+                      PATHSPEC_LITERAL |
+                      PATHSPEC_GLOB);
 
        for (n = 0; n < pathspec->nr; n++) {
                size_t i = 0, len = 0;
@@ -159,8 +164,7 @@ static int match_pathspec_item(const struct pathspec_item 
*item, int prefix,
        }
 
        if (item->nowildcard_len < item->len &&
-           !git_fnmatch(match, name,
-                        item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR : 0,
+           !git_fnmatch(item, match, name,
                         item->nowildcard_len - prefix))
                return MATCHED_FNMATCH;
 
@@ -181,7 +185,10 @@ int match_pathspec_depth(const struct pathspec *ps,
 {
        int i, retval = 0;
 
-       GUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);
+       GUARD_PATHSPEC(ps,
+                      PATHSPEC_FROMTOP |
+                      PATHSPEC_LITERAL |
+                      PATHSPEC_GLOB);
 
        if (!ps->nr) {
                if (!ps->recursive || ps->max_depth == -1)
@@ -1230,7 +1237,10 @@ int read_directory(struct dir_struct *dir, const char 
*path, int len, const stru
         * Check out create_simplify()
         */
        if (pathspec)
-               GUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);
+               GUARD_PATHSPEC(pathspec,
+                              PATHSPEC_FROMTOP |
+                              PATHSPEC_LITERAL |
+                              PATHSPEC_GLOB);
 
        if (has_symlink_leading_path(path, len))
                return dir->nr;
diff --git a/dir.h b/dir.h
index a03af80..b6da4b7 100644
--- a/dir.h
+++ b/dir.h
@@ -168,10 +168,8 @@ 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 */
-#define GFNM_ONESTAR  2                /* there is only _one_ wildcard, a star 
*/
-
-extern int git_fnmatch(const char *pattern, const char *string,
-                      int flags, int prefix);
+extern int git_fnmatch(const struct pathspec_item *item,
+                      const char *pattern, const char *string,
+                      int prefix);
 
 #endif
diff --git a/setup.c b/setup.c
index c4af05e..b3e146d 100644
--- a/setup.c
+++ b/setup.c
@@ -170,6 +170,7 @@ static struct pathspec_magic {
 } pathspec_magic[] = {
        { PATHSPEC_FROMTOP, '/', "top" },
        { PATHSPEC_LITERAL,   0, "literal" },
+       { PATHSPEC_GLOB,   '\0', "glob" },
 };
 
 /*
diff --git a/tree-walk.c b/tree-walk.c
index d4ed51f..1679ce7 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -635,7 +635,10 @@ enum interesting tree_entry_interesting(const struct 
name_entry *entry,
        enum interesting never_interesting = ps->has_wildcard ?
                entry_not_interesting : all_entries_not_interesting;
 
-       GUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);
+       GUARD_PATHSPEC(ps,
+                      PATHSPEC_FROMTOP |
+                      PATHSPEC_LITERAL |
+                      PATHSPEC_GLOB);
 
        if (!ps->nr) {
                if (!ps->recursive || ps->max_depth == -1)
@@ -677,8 +680,7 @@ enum interesting tree_entry_interesting(const struct 
name_entry *entry,
                                return entry_interesting;
 
                        if (item->nowildcard_len < item->len) {
-                               if (!git_fnmatch(match + baselen, entry->path,
-                                                item->flags & PATHSPEC_ONESTAR 
? GFNM_ONESTAR : 0,
+                               if (!git_fnmatch(item, match + baselen, 
entry->path,
                                                 item->nowildcard_len - 
baselen))
                                        return entry_interesting;
 
@@ -719,8 +721,7 @@ match_wildcards:
 
                strbuf_add(base, entry->path, pathlen);
 
-               if (!git_fnmatch(match, base->buf + base_offset,
-                                item->flags & PATHSPEC_ONESTAR ? GFNM_ONESTAR 
: 0,
+               if (!git_fnmatch(item, match, base->buf + base_offset,
                                 item->nowildcard_len)) {
                        strbuf_setlen(base, base_offset + baselen);
                        return entry_interesting;
-- 
1.8.0.rc2.23.g1fb49df

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to