From bd2f371d34b495ebbc4689604cfc34a825c47d2b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 26 Mar 2013 10:28:07 -0700 Subject: attr.c::path_matches(): the basename is part of the pathname The function takes two strings (pathname and basename) as if they are independent strings, but in reality, the latter is always pointing into a substring in the former. Clarify this relationship by expressing the latter as an offset into the former. Signed-off-by: Junio C Hamano --- attr.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'attr.c') diff --git a/attr.c b/attr.c index ab2aab28d..4cfe0ee0f 100644 --- a/attr.c +++ b/attr.c @@ -655,7 +655,7 @@ static void prepare_attr_stack(const char *path, int dirlen) } static int path_matches(const char *pathname, int pathlen, - const char *basename, + int basename_offset, const struct pattern *pat, const char *base, int baselen) { @@ -667,8 +667,8 @@ static int path_matches(const char *pathname, int pathlen, return 0; if (pat->flags & EXC_FLAG_NODIR) { - return match_basename(basename, - pathlen - (basename - pathname), + return match_basename(pathname + basename_offset, + pathlen - basename_offset, pattern, prefix, pat->patternlen, pat->flags); } @@ -701,7 +701,7 @@ static int fill_one(const char *what, struct match_attr *a, int rem) return rem; } -static int fill(const char *path, int pathlen, const char *basename, +static int fill(const char *path, int pathlen, int basename_offset, struct attr_stack *stk, int rem) { int i; @@ -711,7 +711,7 @@ static int fill(const char *path, int pathlen, const char *basename, struct match_attr *a = stk->attrs[i]; if (a->is_macro) continue; - if (path_matches(path, pathlen, basename, + if (path_matches(path, pathlen, basename_offset, &a->u.pat, base, stk->originlen)) rem = fill_one("fill", a, rem); } @@ -750,7 +750,8 @@ static void collect_all_attrs(const char *path) { struct attr_stack *stk; int i, pathlen, rem, dirlen; - const char *basename, *cp, *last_slash = NULL; + const char *cp, *last_slash = NULL; + int basename_offset; for (cp = path; *cp; cp++) { if (*cp == '/' && cp[1]) @@ -758,10 +759,10 @@ static void collect_all_attrs(const char *path) } pathlen = cp - path; if (last_slash) { - basename = last_slash + 1; + basename_offset = last_slash + 1 - path; dirlen = last_slash - path; } else { - basename = path; + basename_offset = 0; dirlen = 0; } @@ -771,7 +772,7 @@ static void collect_all_attrs(const char *path) rem = attr_nr; for (stk = attr_stack; 0 < rem && stk; stk = stk->prev) - rem = fill(path, pathlen, basename, stk, rem); + rem = fill(path, pathlen, basename_offset, stk, rem); } int git_check_attr(const char *path, int num, struct git_attr_check *check) -- cgit v1.2.1 From dc09e9ec43c09cdf803cc4f39f1fcb8ebcf80eb1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 28 Mar 2013 17:49:13 -0400 Subject: 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 Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- attr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'attr.c') diff --git a/attr.c b/attr.c index 4cfe0ee0f..4d620bc52 100644 --- a/attr.c +++ b/attr.c @@ -661,18 +661,18 @@ static int path_matches(const char *pathname, int pathlen, { const char *pattern = pat->pattern; int prefix = pat->nowildcardlen; + int isdir = (pathlen && pathname[pathlen - 1] == '/'); - if ((pat->flags & EXC_FLAG_MUSTBEDIR) && - ((!pathlen) || (pathname[pathlen-1] != '/'))) + if ((pat->flags & EXC_FLAG_MUSTBEDIR) && !isdir) return 0; if (pat->flags & EXC_FLAG_NODIR) { return match_basename(pathname + basename_offset, - pathlen - basename_offset, + pathlen - basename_offset - isdir, pattern, prefix, pat->patternlen, pat->flags); } - return match_pathname(pathname, pathlen, + return match_pathname(pathname, pathlen - isdir, base, baselen, pattern, prefix, pat->patternlen, pat->flags); } -- cgit v1.2.1