[PATCH 09/21] tree_entry_interesting(): support depth limit
flat view
STALE2811d
From: Nguyễn Thái Ngọc Duy <hidden>
Date: 2016-06-15 22:50:15
Subsystem:
the rest · Maintainer:
Linus Torvalds
This is needed to replace pathspec_matches() in builtin/grep.c.
max_depth == -1 means infinite depth. Depth limit is only effective
when pathspec.recursive == 1. When pathspec.recursive == 0, the
behavior depends on match functions: non-recursive for
tree_entry_interesting() and recursive for match_pathspec{,_depth}
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
cache.h | 2 ++
dir.c | 15 +++++++++++++++
dir.h | 1 +
tree-diff.c | 4 ++++
tree-walk.c | 19 ++++++++++++++++---
5 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/cache.h b/cache.h
index 9eeecc2..b110775 100644
--- a/cache.h
+++ b/cache.h@@ -496,6 +496,8 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct struct pathspec { const char **raw; /* get_pathspec() result, not freed by free_pathspec() */ int nr; + int recursive:1; + int max_depth; struct pathspec_item { const char *match; int len;
diff --git a/dir.c b/dir.c
index a88f2ef..79e88f6 100644
--- a/dir.c
+++ b/dir.c@@ -71,6 +71,21 @@ int fill_directory(struct dir_struct *dir, const char **pathspec) return len; } +int within_depth(const char *name, int namelen, + int depth, int max_depth) +{ + const char *cp = name, *cpe = name + namelen; + + while (cp < cpe) { + if (*cp++ != '/') + continue; + depth++; + if (depth > max_depth) + return 0; + } + return 1; +} + /* * Does 'match' match the given name? * A match is found if
diff --git a/dir.h b/dir.h
index 278d84c..c71de08 100644
--- a/dir.h
+++ b/dir.h@@ -65,6 +65,7 @@ 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 within_depth(const char *name, int namelen, int depth, int max_depth); extern int fill_directory(struct dir_struct *dir, const char **pathspec); extern int read_directory(struct dir_struct *, const char *path, int len, const char **pathspec);
diff --git a/tree-diff.c b/tree-diff.c
index 67fa6c4..bde2c52 100644
--- a/tree-diff.c
+++ b/tree-diff.c@@ -152,6 +152,10 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2, struct strbuf base; int baselen = strlen(base_str); + /* Enable recursion indefinitely */ + opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE); + opt->pathspec.max_depth = -1; + strbuf_init(&base, PATH_MAX); strbuf_add(&base, base_str, baselen);
diff --git a/tree-walk.c b/tree-walk.c
index 5012705..91d7b36 100644
--- a/tree-walk.c
+++ b/tree-walk.c@@ -1,6 +1,7 @@ #include "cache.h" #include "tree-walk.h" #include "unpack-trees.h" +#include "dir.h" #include "tree.h" static const char *get_mode(const char *str, unsigned int *modep)
@@ -557,8 +558,13 @@ int tree_entry_interesting(const struct name_entry *entry, int pathlen, baselen = base->len; int never_interesting = -1; - if (!ps || !ps->nr) - return 1; + if (!ps->nr) { + if (!ps->recursive || ps->max_depth == -1) + return 1; + return !!within_depth(base->buf, baselen, + !!S_ISDIR(entry->mode), + ps->max_depth); + } pathlen = tree_entry_len(entry->path, entry->sha1);
@@ -571,7 +577,14 @@ int tree_entry_interesting(const struct name_entry *entry, /* If it doesn't match, move along... */ if (!match_dir_prefix(base->buf, baselen, match, matchlen)) continue; - return 2; + + if (!ps->recursive || ps->max_depth == -1) + return 2; + + return !!within_depth(base->buf + matchlen + 1, + baselen - matchlen - 1, + !!S_ISDIR(entry->mode), + ps->max_depth); } /* Does the base match? */
--
1.7.3.3.476.g10a82