attr.c::path_matches(): special case paths that end with a slash

The function is given a string that ends with a slash to signal that the path is a directory to make sure that a pattern that ends with a slash (i.e. MUSTBEDIR) can tell directories and non-directories apart. However, the pattern itself (pat->pattern and pat->patternlen) that came from such a MUSTBEDIR pattern is represented as a string that ends with a slash, but patternlen does not count that trailing slash. A MUSTBEDIR pattern "element/" is represented as a counted string <"element/", 7> and this must match match pathname "element/". Because match_basename() and match_pathname() want to see pathname "element" to match against the pattern <"element/", 7>, reduce the length of the path to exclude the trailing slash when calling these functions. Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Mar 28, 2013 at 17:49 UTC dc09e9ec43c09cdf803cc4f39f1fcb8ebcf80eb1
1 file changed +4 -4
attr.c
+4 -4
@@ -661,18 +661,18 @@ static int path_matches(const char *pathname, int pathlen,
661 {
662 const char *pattern = pat->pattern;
663 int prefix = pat->nowildcardlen;
664 + int isdir = (pathlen && pathname[pathlen - 1] == '/');
665
665 - if ((pat->flags & EXC_FLAG_MUSTBEDIR) &&
666 - ((!pathlen) || (pathname[pathlen-1] != '/')))
666 + if ((pat->flags & EXC_FLAG_MUSTBEDIR) && !isdir)
667 return 0;
668
669 if (pat->flags & EXC_FLAG_NODIR) {
670 return match_basename(pathname + basename_offset,
671 - pathlen - basename_offset,
671 + pathlen - basename_offset - isdir,
672 pattern, prefix,
673 pat->patternlen, pat->flags);
674 }
675 - return match_pathname(pathname, pathlen,
675 + return match_pathname(pathname, pathlen - isdir,
676 base, baselen,
677 pattern, prefix, pat->patternlen, pat->flags);
678 }