diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2013-07-14 15:36:08 +0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2013-07-15 10:56:10 -0700 |
commit | bd30c2e48432c692f9e77d3529c9cf25117066bb (patch) | |
tree | 9b5601d17196c49356adc686ce3c5ae7e62d94cf /dir.c | |
parent | a16bf9dd745a9e43e46d745d850db49358430e46 (diff) | |
download | git-bd30c2e48432c692f9e77d3529c9cf25117066bb.tar.gz |
pathspec: support :(glob) syntax
:(glob)path differs from plain pathspec that it uses wildmatch with
WM_PATHNAME while the other uses fnmatch without FNM_PATHNAME. The
difference lies in how '*' (and '**') is processed.
With the introduction of :(glob) and :(literal) and their global
options --[no]glob-pathspecs, the user can:
- make everything literal by default via --noglob-pathspecs
--literal-pathspecs cannot be used for this purpose as it
disables _all_ pathspec magic.
- individually turn on globbing with :(glob)
- make everything globbing by default via --glob-pathspecs
- individually turn off globbing with :(literal)
The implication behind this is, there is no way to gain the default
matching behavior (i.e. fnmatch without FNM_PATHNAME). You either get
new globbing or literal. The old fnmatch behavior is considered
deprecated and discouraged to use.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 28 |
1 files changed, 16 insertions, 12 deletions
@@ -52,26 +52,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, WM_PATHNAME, NULL); + else + /* wildmatch has not learned no FNM_PATHNAME mode yet */ + return fnmatch(pattern, string, 0); } static int fnmatch_icase_mem(const char *pattern, int patternlen, @@ -111,7 +113,8 @@ static size_t common_prefix_len(const struct pathspec *pathspec) GUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP | PATHSPEC_MAXDEPTH | - PATHSPEC_LITERAL); + PATHSPEC_LITERAL | + PATHSPEC_GLOB); for (n = 0; n < pathspec->nr; n++) { size_t i = 0, len = 0; @@ -206,8 +209,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; @@ -238,7 +240,8 @@ int match_pathspec_depth(const struct pathspec *ps, GUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_MAXDEPTH | - PATHSPEC_LITERAL); + PATHSPEC_LITERAL | + PATHSPEC_GLOB); if (!ps->nr) { if (!ps->recursive || @@ -1297,7 +1300,8 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru GUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP | PATHSPEC_MAXDEPTH | - PATHSPEC_LITERAL); + PATHSPEC_LITERAL | + PATHSPEC_GLOB); if (has_symlink_leading_path(path, len)) return dir->nr; |