parse_pathspec: add special flag for max_depth feature

match_pathspec_depth() and tree_entry_interesting() check max_depth field in order to support "git grep --max-depth". The feature activation is tied to "recursive" field, which led to some unwanted activation, e.g. 5c8eeb8 (diff-index: enable recursive pathspec matching in unpack_trees - 2012-01-15). This patch decouples the activation from "recursive" field, puts it in "magic" field instead. This makes sure that only "git grep" can activate this feature. And because parse_pathspec knows when the feature is not used, it does not need to sort pathspec (required for max_depth to work correctly). A small win for non-grep cases. Even though a new magic flag is introduced, no magic syntax is. The magic can be only enabled by parse_pathspec() caller. We might someday want to support ":(maxdepth:10)src." It all depends on actual use cases. max_depth feature cannot be enabled via init_pathspec() anymore. But that's ok because init_pathspec() is on its way to /dev/null. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Jul 14, 2013 at 15:35 UTC 6330a171996abbec7dac48788de851aea7d0a18f
7 files changed +25 -10
builtin/grep.c
+2 -1
@@ -858,7 +858,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
858 }
859
860 parse_pathspec(&pathspec, 0,
861 - PATHSPEC_PREFER_CWD,
861 + PATHSPEC_PREFER_CWD |
862 + (opt.max_depth != -1 ? PATHSPEC_MAXDEPTH_VALID : 0),
863 prefix, argv + i);
864 pathspec.max_depth = opt.max_depth;
865 pathspec.recursive = 1;
diff-lib.c
-1
@@ -476,7 +476,6 @@ static int diff_cache(struct rev_info *revs,
476 opts.dst_index = NULL;
477 opts.pathspec = &revs->diffopt.pathspec;
478 opts.pathspec->recursive = 1;
479 - opts.pathspec->max_depth = -1;
479
480 init_tree_desc(&t, tree->buffer, tree->size);
481 return unpack_trees(1, &t, &opts);
dir.c
+6 -2
@@ -341,7 +341,9 @@ int match_pathspec_depth(const struct pathspec *ps,
341 int i, retval = 0;
342
343 if (!ps->nr) {
344 - if (!ps->recursive || ps->max_depth == -1)
344 + if (!ps->recursive ||
345 + !(ps->magic & PATHSPEC_MAXDEPTH) ||
346 + ps->max_depth == -1)
347 return MATCHED_RECURSIVELY;
348
349 if (within_depth(name, namelen, 0, ps->max_depth))
@@ -358,7 +360,9 @@ int match_pathspec_depth(const struct pathspec *ps,
360 if (seen && seen[i] == MATCHED_EXACTLY)
361 continue;
362 how = match_pathspec_item(ps->items+i, prefix, name, namelen);
361 - if (ps->recursive && ps->max_depth != -1 &&
363 + if (ps->recursive &&
364 + (ps->magic & PATHSPEC_MAXDEPTH) &&
365 + ps->max_depth != -1 &&
366 how && how != MATCHED_FNMATCH) {
367 int len = ps->items[i].len;
368 if (name[len] == '/')
pathspec.c
+6 -2
@@ -267,6 +267,9 @@ void parse_pathspec(struct pathspec *pathspec,
267
268 memset(pathspec, 0, sizeof(*pathspec));
269
270 + if (flags & PATHSPEC_MAXDEPTH_VALID)
271 + pathspec->magic |= PATHSPEC_MAXDEPTH;
272 +
273 /* No arguments, no prefix -> no pathspec */
274 if (!entry && !prefix)
275 return;
@@ -322,8 +325,9 @@ void parse_pathspec(struct pathspec *pathspec,
325 pathspec->magic |= item[i].magic;
326 }
327
325 - qsort(pathspec->items, pathspec->nr,
326 - sizeof(struct pathspec_item), pathspec_item_cmp);
328 + if (pathspec->magic & PATHSPEC_MAXDEPTH)
329 + qsort(pathspec->items, pathspec->nr,
330 + sizeof(struct pathspec_item), pathspec_item_cmp);
331 }
332
333 /*
pathspec.h
+5 -1
@@ -3,7 +3,10 @@
3
4 /* Pathspec magic */
5 #define PATHSPEC_FROMTOP (1<<0)
6 -#define PATHSPEC_ALL_MAGIC PATHSPEC_FROMTOP
6 +#define PATHSPEC_MAXDEPTH (1<<1)
7 +#define PATHSPEC_ALL_MAGIC \
8 + (PATHSPEC_FROMTOP | \
9 + PATHSPEC_MAXDEPTH)
10
11 #define PATHSPEC_ONESTAR 1 /* the pathspec pattern sastisfies GFNM_ONESTAR */
12
@@ -27,6 +30,7 @@ struct pathspec {
30 /* parse_pathspec flags */
31 #define PATHSPEC_PREFER_CWD (1<<0) /* No args means match cwd */
32 #define PATHSPEC_PREFER_FULL (1<<1) /* No args means match everything */
33 +#define PATHSPEC_MAXDEPTH_VALID (1<<2) /* max_depth field is valid */
34
35 extern int init_pathspec(struct pathspec *, const char **);
36 extern void parse_pathspec(struct pathspec *pathspec,
tree-diff.c
-1
@@ -138,7 +138,6 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
138
139 /* Enable recursion indefinitely */
140 opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
141 - opt->pathspec.max_depth = -1;
141
142 strbuf_init(&base, PATH_MAX);
143 strbuf_add(&base, base_str, baselen);
tree-walk.c
+6 -2
@@ -637,7 +637,9 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
637 entry_not_interesting : all_entries_not_interesting;
638
639 if (!ps->nr) {
640 - if (!ps->recursive || ps->max_depth == -1)
640 + if (!ps->recursive ||
641 + !(ps->magic & PATHSPEC_MAXDEPTH) ||
642 + ps->max_depth == -1)
643 return all_entries_interesting;
644 return within_depth(base->buf + base_offset, baselen,
645 !!S_ISDIR(entry->mode),
@@ -658,7 +660,9 @@ enum interesting tree_entry_interesting(const struct name_entry *entry,
660 if (!match_dir_prefix(base_str, match, matchlen))
661 goto match_wildcards;
662
661 - if (!ps->recursive || ps->max_depth == -1)
663 + if (!ps->recursive ||
664 + !(ps->magic & PATHSPEC_MAXDEPTH) ||
665 + ps->max_depth == -1)
666 return all_entries_interesting;
667
668 return within_depth(base_str + matchlen + 1,