Subject: [PATCH v3 08/13] exclude: record baselen in the pattern

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Tue, 12 Mar 2013 20:04:55 +0700

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 attr.c |  4 +++-
 dir.c  | 19 ++++++++++++++-----
 dir.h  |  6 +++++-
 3 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/attr.c b/attr.c
index 1818ba5..b89da33 100644
--- a/attr.c
+++ b/attr.c
@@ -249,12 +249,14 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
 		res->u.attr = git_attr_internal(name, namelen);
 	else {
 		char *p = (char *)&(res->state[num_attr]);
+		int pattern_baselen;
 		memcpy(p, name, namelen);
 		res->u.pat.pattern = p;
 		parse_exclude_pattern(&res->u.pat.pattern,
 				      &res->u.pat.patternlen,
 				      &res->u.pat.flags,
-				      &res->u.pat.nowildcardlen);
+				      &res->u.pat.nowildcardlen,
+				      &pattern_baselen);
 		if (res->u.pat.flags & EXC_FLAG_MUSTBEDIR)
 			res->u.pat.patternlen++;
 		if (res->u.pat.flags & EXC_FLAG_NEGATIVE) {
diff --git a/dir.c b/dir.c
index f8f7a7e..932fd2f 100644
--- a/dir.c
+++ b/dir.c
@@ -390,10 +390,11 @@ static int no_wildcard(const char *string)
 void parse_exclude_pattern(const char **pattern,
 			   int *patternlen,
 			   int *flags,
-			   int *nowildcardlen)
+			   int *nowildcardlen,
+			   int *pattern_baselen)
 {
 	const char *p = *pattern;
-	size_t i, len;
+	int i, len;
 
 	*flags = 0;
 	if (*p == '!') {
@@ -405,12 +406,15 @@ void parse_exclude_pattern(const char **pattern,
 		len--;
 		*flags |= EXC_FLAG_MUSTBEDIR;
 	}
-	for (i = 0; i < len; i++) {
+	for (i = len - 1; i >= 0; i--) {
 		if (p[i] == '/')
 			break;
 	}
-	if (i == len)
+	if (i < 0) {
 		*flags |= EXC_FLAG_NODIR;
+		*pattern_baselen = -1;
+	} else
+		*pattern_baselen = i;
 	*nowildcardlen = simple_length(p);
 	/*
 	 * we should have excluded the trailing slash from 'p' too,
@@ -421,6 +425,8 @@ void parse_exclude_pattern(const char **pattern,
 		*nowildcardlen = len;
 	if (*p == '*' && no_wildcard(p + 1))
 		*flags |= EXC_FLAG_ENDSWITH;
+	else if (*nowildcardlen != len)
+		*pattern_baselen = -1;
 	*pattern = p;
 	*patternlen = len;
 }
@@ -432,8 +438,10 @@ void add_exclude(const char *string, const char *base,
 	int patternlen;
 	int flags;
 	int nowildcardlen;
+	int pattern_baselen;
 
-	parse_exclude_pattern(&string, &patternlen, &flags, &nowildcardlen);
+	parse_exclude_pattern(&string, &patternlen, &flags,
+			      &nowildcardlen, &pattern_baselen);
 	if (flags & EXC_FLAG_MUSTBEDIR) {
 		char *s;
 		x = xmalloc(sizeof(*x) + patternlen + 1);
@@ -449,6 +457,7 @@ void add_exclude(const char *string, const char *base,
 	x->nowildcardlen = nowildcardlen;
 	x->base = base;
 	x->baselen = baselen;
+	x->pattern_baselen = pattern_baselen;
 	x->flags = flags;
 	x->srcpos = srcpos;
 	ALLOC_GROW(el->excludes, el->nr + 1, el->alloc);
diff --git a/dir.h b/dir.h
index 0748407..cb50a85 100644
--- a/dir.h
+++ b/dir.h
@@ -44,6 +44,7 @@ struct exclude_list {
 		int nowildcardlen;
 		const char *base;
 		int baselen;
+		int pattern_baselen;
 		int flags;
 
 		/*
@@ -172,7 +173,10 @@ extern struct exclude_list *add_exclude_list(struct dir_struct *dir,
 extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
 					  struct exclude_list *el, int check_index);
 extern void add_excludes_from_file(struct dir_struct *, const char *fname);
-extern void parse_exclude_pattern(const char **string, int *patternlen, int *flags, int *nowildcardlen);
+extern void parse_exclude_pattern(const char **string,
+				  int *patternlen, int *flags,
+				  int *nowildcardlen,
+				  int *pattern_baselen);
 extern void add_exclude(const char *string, const char *base,
 			int baselen, struct exclude_list *el, int srcpos);
 extern void clear_exclude_list(struct exclude_list *el);
-- 
1.8.1.2.536.gf441e6d