diff options
author | Junio C Hamano <gitster@pobox.com> | 2013-04-07 08:45:03 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2013-04-07 08:45:03 -0700 |
commit | 4bbb830a35c5134b612a990f04ee16678ec0c674 (patch) | |
tree | 5857a31360481265078ae10c2989471137596cd7 /dir.c | |
parent | 0e9b327227fb8f7c1e3a5bbaef19e25b4dfd6764 (diff) | |
parent | efa5f82540ac0ea75ac185324a78fa230befa050 (diff) | |
download | git-4bbb830a35c5134b612a990f04ee16678ec0c674.tar.gz |
Merge branch 'jc/directory-attrs-regression-fix' into maint-1.8.1
A pattern "dir" (without trailing slash) in the attributes file
stopped matching a directory "dir" by mistake with an earlier change
that wanted to allow pattern "dir/" to also match.
* jc/directory-attrs-regression-fix:
t: check that a pattern without trailing slash matches a directory
dir.c::match_pathname(): pay attention to the length of string parameters
dir.c::match_pathname(): adjust patternlen when shifting pattern
dir.c::match_basename(): pay attention to the length of string parameters
attr.c::path_matches(): special case paths that end with a slash
attr.c::path_matches(): the basename is part of the pathname
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 54 |
1 files changed, 49 insertions, 5 deletions
@@ -34,6 +34,33 @@ int fnmatch_icase(const char *pattern, const char *string, int flags) return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0)); } +static int fnmatch_icase_mem(const char *pattern, int patternlen, + const char *string, int stringlen, + int flags) +{ + int match_status; + struct strbuf pat_buf = STRBUF_INIT; + struct strbuf str_buf = STRBUF_INIT; + const char *use_pat = pattern; + const char *use_str = string; + + if (pattern[patternlen]) { + strbuf_add(&pat_buf, pattern, patternlen); + use_pat = pat_buf.buf; + } + if (string[stringlen]) { + strbuf_add(&str_buf, string, stringlen); + use_str = str_buf.buf; + } + + match_status = fnmatch_icase(use_pat, use_str, flags); + + strbuf_release(&pat_buf); + strbuf_release(&str_buf); + + return match_status; +} + static size_t common_prefix_len(const char **pathspec) { const char *n, *first; @@ -537,15 +564,20 @@ int match_basename(const char *basename, int basenamelen, int flags) { if (prefix == patternlen) { - if (!strcmp_icase(pattern, basename)) + if (patternlen == basenamelen && + !strncmp_icase(pattern, basename, basenamelen)) return 1; } else if (flags & EXC_FLAG_ENDSWITH) { + /* "*literal" matching against "fooliteral" */ if (patternlen - 1 <= basenamelen && - !strcmp_icase(pattern + 1, - basename + basenamelen - patternlen + 1)) + !strncmp_icase(pattern + 1, + basename + basenamelen - (patternlen - 1), + patternlen - 1)) return 1; } else { - if (fnmatch_icase(pattern, basename, 0) == 0) + if (fnmatch_icase_mem(pattern, patternlen, + basename, basenamelen, + 0) == 0) return 1; } return 0; @@ -565,6 +597,7 @@ int match_pathname(const char *pathname, int pathlen, */ if (*pattern == '/') { pattern++; + patternlen--; prefix--; } @@ -591,11 +624,22 @@ int match_pathname(const char *pathname, int pathlen, if (strncmp_icase(pattern, name, prefix)) return 0; pattern += prefix; + patternlen -= prefix; name += prefix; namelen -= prefix; + + /* + * If the whole pattern did not have a wildcard, + * then our prefix match is all we need; we + * do not need to call fnmatch at all. + */ + if (!patternlen && !namelen) + return 1; } - return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0; + return fnmatch_icase_mem(pattern, patternlen, + name, namelen, + FNM_PATHNAME) == 0; } /* Scan the list and let the last match determine the fate. |