Subject: [PATCH 15/19] pathspec: add match_pathspec_depth()

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Mon, 13 Dec 2010 16:46:52 +0700

match_pathspec_depth() is similar to match_pathspec() except that it
can take depth limit.

In long term, match_pathspec() should be removed in favor of this
function.

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 dir.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 dir.h |    3 +++
 2 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/dir.c b/dir.c
index bb5076c..e12dbdd 100644
--- a/dir.c
+++ b/dir.c
@@ -169,6 +169,51 @@ int match_pathspec(const char **pathspec, const char *name, int namelen,
 	return retval;
 }
 
+int match_pathspec_depth(const char **pathspec, int max_depth,
+			 const char *name, int namelen,
+			 int prefix, char *seen)
+{
+	int i, retval = 0;
+
+	if (!pathspec) {
+		if (max_depth == -1)
+			return MATCHED_RECURSIVELY;
+
+		if (within_depth(name, namelen, 0, max_depth))
+			return MATCHED_EXACTLY;
+		else
+			return 0;
+	}
+
+	name += prefix;
+	namelen -= prefix;
+
+	for (i = 0; pathspec[i] != NULL; i++) {
+		int how;
+		const char *match = pathspec[i] + prefix;
+		if (seen && seen[i] == MATCHED_EXACTLY)
+			continue;
+		how = match_one(match, name, namelen);
+		if (max_depth != -1 &&
+		    how && how != MATCHED_FNMATCH) {
+			int len = strlen(match);
+			if (name[len] == '/')
+				len++;
+			if (within_depth(name+len, namelen-len, 0, max_depth))
+				how = MATCHED_EXACTLY;
+			else
+				how = 0;
+		}
+		if (how) {
+			if (retval < how)
+				retval = how;
+			if (seen && seen[i] < how)
+				seen[i] = how;
+		}
+	}
+	return retval;
+}
+
 static int no_wildcard(const char *string)
 {
 	return string[strcspn(string, "*?[{\\")] == '\0';
diff --git a/dir.h b/dir.h
index c71de08..9dc9592 100644
--- a/dir.h
+++ b/dir.h
@@ -65,6 +65,9 @@ struct dir_struct {
 #define MATCHED_FNMATCH 2
 #define MATCHED_EXACTLY 3
 extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
+extern int match_pathspec_depth(const char **pathspec, int max_depth,
+				const char *name, int namelen,
+				int prefix, char *seen);
 extern int within_depth(const char *name, int namelen, int depth, int max_depth);
 
 extern int fill_directory(struct dir_struct *dir, const char **pathspec);
-- 
1.7.3.3.476.g10a82