[PATCH 13/21] pathspec: add match_pathspec_depth()

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?=
Date: Wednesday, December 15, 2010 - 8:02 am

match_pathspec_depth() is a clone of match_pathspec() except that it
can take depth limit. Computation is a bit lighter compared to
match_pathspec() because it's usually precomputed and stored in struct
pathspec.

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

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 dir.c |   89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 dir.h |    3 ++
 2 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/dir.c b/dir.c
index 66c163f..b1407a5 100644
--- a/dir.c
+++ b/dir.c
@@ -169,6 +169,95 @@ int match_pathspec(const char **pathspec, const char *name, int namelen,
 	return retval;
 }
 
+/*
+ * Does 'match' match the given name?
+ * A match is found if
+ *
+ * (1) the 'match' string is leading directory of 'name', or
+ * (2) the 'match' string is a wildcard and matches 'name', or
+ * (3) the 'match' string is exactly the same as 'name'.
+ *
+ * and the return value tells which case it was.
+ *
+ * It returns 0 when there is no match.
+ */
+static int match_pathspec_item(const struct pathspec_item *item, int prefix,
+			       const char *name, int namelen)
+{
+	/* name/namelen has prefix cut off by caller */
+	const char *match = item->match + prefix;
+	int matchlen = item->len - prefix;
+
+	/* If the match was just the prefix, we matched */
+	if (!*match)
+		return MATCHED_RECURSIVELY;
+
+	if (matchlen <= namelen && !strncmp(match, name, matchlen)) {
+		if (matchlen == namelen)
+			return MATCHED_EXACTLY;
+
+		if (match[matchlen-1] == '/' || name[matchlen] == '/')
+			return MATCHED_RECURSIVELY;
+	}
+
+	if (item->has_wildcard && !fnmatch(match, name, 0))
+		return MATCHED_FNMATCH;
+
+	return 0;
+}
+
+/*
+ * Given a name and a list of pathspecs, see if the name matches
+ * any of the pathspecs.  The caller is also interested in seeing
+ * all pathspec matches some names it calls this function with
+ * (otherwise the user could have mistyped the unmatched pathspec),
+ * and a mark is left in seen[] array for pathspec element that
+ * actually matched anything.
+ */
+int match_pathspec_depth(const struct pathspec *ps,
+			 const char *name, int namelen,
+			 int prefix, char *seen)
+{
+	int i, retval = 0;
+
+	if (!ps->nr) {
+		if (!ps->recursive || ps->max_depth == -1)
+			return MATCHED_RECURSIVELY;
+
+		if (within_depth(name, namelen, 0, ps->max_depth))
+			return MATCHED_EXACTLY;
+		else
+			return 0;
+	}
+
+	name += prefix;
+	namelen -= prefix;
+
+	for (i = ps->nr - 1; i >= 0; i--) {
+		int how;
+		if (seen && seen[i] == MATCHED_EXACTLY)
+			continue;
+		how = match_pathspec_item(ps->items+i, prefix, name, namelen);
+		if (ps->recursive && ps->max_depth != -1 &&
+		    how && how != MATCHED_FNMATCH) {
+			int len = ps->items[i].len;
+			if (name[len] == '/')
+				len++;
+			if (within_depth(name+len, namelen-len, 0, ps->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..ddb4147 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 struct pathspec *pathspec,
+				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

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[PATCH 00/21] nd/struct-pathspec v2, =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 01/21] Add struct pathspec, =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 02/21] diff-no-index: use diff_tree_setup_paths(), =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 03/21] Convert struct diff_options to use struct pa ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 04/21] tree_entry_interesting(): remove dependency ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 05/21] Move tree_entry_interesting() to tree-walk.c ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 06/21] glossary: define pathspec, =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 07/21] diff-tree: convert base+baselen to writable ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 08/21] tree_entry_interesting(): refactor into sepa ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 09/21] tree_entry_interesting(): support depth limit, =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 10/21] tree_entry_interesting(): fix depth limit wi ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 11/21] tree_entry_interesting(): support wildcard m ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 12/21] tree_entry_interesting(): optimize wildcard ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 13/21] pathspec: add match_pathspec_depth(), =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 14/21] Convert ce_path_match() to use struct pathspec, =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 15/21] Convert ce_path_match() to use match_pathspe ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 16/21] grep: convert to use struct pathspec, =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 17/21] grep: use match_pathspec_depth() for cache/w ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 18/21] strbuf: allow &quot;buf&quot; to point to the middle o ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 19/21] grep: use writable strbuf from caller in gre ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 20/21] grep: drop pathspec_matches() in favor of tr ..., =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
[PATCH 21/21] t7810: overlapping pathspecs and depth limit, =?UTF-8?q?Nguy=E1=BB ..., (Wed Dec 15, 8:02 am)
Re: [PATCH 19/21] grep: use writable strbuf from caller in ..., Nguyen Thai Ngoc Duy, (Fri Dec 17, 2:56 am)
Re: [PATCH 14/21] Convert ce_path_match() to use struct pa ..., Nguyen Thai Ngoc Duy, (Fri Dec 17, 2:59 am)
Re: [PATCH 10/21] tree_entry_interesting(): fix depth limi ..., Nguyen Thai Ngoc Duy, (Fri Dec 17, 3:05 am)
[PATCH 14/21] struct rev_info: convert prune_data to struc ..., =?UTF-8?q?Nguy=E1=BB ..., (Fri Dec 17, 5:43 am)
[PATCH 15/21] Convert ce_path_match() to use struct pathspec, =?UTF-8?q?Nguy=E1=BB ..., (Fri Dec 17, 5:43 am)
[PATCH 19/21] grep: use writable strbuf from caller for gr ..., =?UTF-8?q?Nguy=E1=BB ..., (Fri Dec 17, 5:44 am)
[PATCH 20/21] grep: drop pathspec_matches() in favor of tr ..., =?UTF-8?q?Nguy=E1=BB ..., (Fri Dec 17, 5:45 am)
Re: [PATCH 14/21] Convert ce_path_match() to use struct pa ..., Nguyen Thai Ngoc Duy, (Fri Dec 17, 8:11 am)
Re: [PATCH 10/21] tree_entry_interesting(): fix depth limi ..., Nguyen Thai Ngoc Duy, (Fri Dec 17, 8:37 pm)