Merge branch 'jc/directory-attrs-regression-fix'
authorJunio C Hamano <gitster@pobox.com>
Wed, 3 Apr 2013 16:34:04 +0000 (09:34 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 3 Apr 2013 16:34:09 +0000 (09:34 -0700)
Fix 1.8.1.x regression that stopped matching "dir" (without
trailing slash) to a directory "dir".

* 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

1  2 
attr.c
dir.c
diff --cc attr.c
Simple merge
diff --cc dir.c
index 57394e452eb0de117b27f64804e529b617a6c7e0,8fea94e1853eecd18dc6d5eb36dd090bdcb3e246..1e42b2b1509e2cf154a1d9722138fbeae437daf5
--- 1/dir.c
--- 2/dir.c
+++ b/dir.c
@@@ -37,28 -34,33 +37,57 @@@ int fnmatch_icase(const char *pattern, 
        return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
  }
  
 -      match_status = fnmatch_icase(use_pat, use_str, flags);
 +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;
 +      }
 +      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);
 +}
 +
+ 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;
+       }
++      if (ignore_case)
++              flags |= WM_CASEFOLD;
++      match_status = wildmatch(use_pat, use_str, flags, NULL);
+       strbuf_release(&pat_buf);
+       strbuf_release(&str_buf);
+       return match_status;
+ }
  static size_t common_prefix_len(const char **pathspec)
  {
        const char *n, *first;
@@@ -680,26 -624,30 +715,35 @@@ int match_pathname(const char *pathname
                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 wildmatch(pattern, name,
-                        WM_PATHNAME | (ignore_case ? WM_CASEFOLD : 0),
-                        NULL) == 0;
+       return fnmatch_icase_mem(pattern, patternlen,
+                                name, namelen,
 -                               FNM_PATHNAME) == 0;
++                               WM_PATHNAME) == 0;
  }
  
 -/* Scan the list and let the last match determine the fate.
 - * Return 1 for exclude, 0 for include and -1 for undecided.
 +/*
 + * Scan the given exclude list in reverse to see whether pathname
 + * should be ignored.  The first match (i.e. the last on the list), if
 + * any, determines the fate.  Returns the exclude_list element which
 + * matched, or NULL for undecided.
   */
 -int excluded_from_list(const char *pathname,
 -                     int pathlen, const char *basename, int *dtype,
 -                     struct exclude_list *el)
 +static struct exclude *last_exclude_matching_from_list(const char *pathname,
 +                                                     int pathlen,
 +                                                     const char *basename,
 +                                                     int *dtype,
 +                                                     struct exclude_list *el)
  {
        int i;