52
return git_color_default_config(var, value, cb);
53
}
54
55
+/*
56
+ * Return non-zero if max_depth is negative or path has no more then max_depth
57
+ * slashes.
58
+ */
59
+static int accept_subdir(const char *path, int max_depth)
60
+{
61
+ if (max_depth < 0)
62
+ return 1;
63
+
64
+ while ((path = strchr(path, '/')) != NULL) {
65
+ max_depth--;
66
+ if (max_depth < 0)
67
+ return 0;
68
+ path++;
69
+ }
70
+ return 1;
71
+}
72
+
73
+/*
74
+ * Return non-zero if name is a subdirectory of match and is not too deep.
75
+ */
76
+static int is_subdir(const char *name, int namelen,
77
+ const char *match, int matchlen, int max_depth)
78
+{
79
+ if (matchlen > namelen || strncmp(name, match, matchlen))
80
+ return 0;
81
+
82
+ if (name[matchlen] == '\0') /* exact match */
83
+ return 1;
84
+
85
+ if (!matchlen || match[matchlen-1] == '/' || name[matchlen] == '/')
86
+ return accept_subdir(name + matchlen + 1, max_depth);
87
+
88
+ return 0;
89
+}
90
+
91
/*
92
* git grep pathspecs are somewhat different from diff-tree pathspecs;
93
* pathname wildcards are allowed.
94
*/
59
-static int pathspec_matches(const char **paths, const char *name)
95
+static int pathspec_matches(const char **paths, const char *name, int max_depth)
96
{
97
int namelen, i;
98
if (!paths || !*paths)
63
- return 1;
99
+ return accept_subdir(name, max_depth);
100
namelen = strlen(name);
101
for (i = 0; paths[i]; i++) {
102
const char *match = paths[i];
103
int matchlen = strlen(match);
104
const char *cp, *meta;
105
70
- if (!matchlen ||
71
- ((matchlen <= namelen) &&
72
- !strncmp(name, match, matchlen) &&
73
- (match[matchlen-1] == '/' ||
74
- name[matchlen] == '\0' || name[matchlen] == '/')))
106
+ if (is_subdir(name, namelen, match, matchlen, max_depth))
107
return 1;
108
if (!fnmatch(match, name, 0))
109
return 1;
453
int kept;
454
if (!S_ISREG(ce->ce_mode))
455
continue;
424
- if (!pathspec_matches(paths, ce->name))
456
+ if (!pathspec_matches(paths, ce->name, opt->max_depth))
457
continue;
458
name = ce->name;
459
if (name[0] == '-') {
510
struct cache_entry *ce = active_cache[nr];
511
if (!S_ISREG(ce->ce_mode))
512
continue;
481
- if (!pathspec_matches(paths, ce->name))
513
+ if (!pathspec_matches(paths, ce->name, opt->max_depth))
514
continue;
515
/*
516
* If CE_VALID is on, we assume worktree file and its cache entry
570
strbuf_addch(&pathbuf, '/');
571
572
down = pathbuf.buf + tn_len;
541
- if (!pathspec_matches(paths, down))
573
+ if (!pathspec_matches(paths, down, opt->max_depth))
574
;
575
else if (S_ISREG(entry.mode))
576
hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len);
724
OPT_SET_INT('I', NULL, &opt.binary,
725
"don't match patterns in binary files",
726
GREP_BINARY_NOMATCH),
727
+ { OPTION_INTEGER, 0, "max-depth", &opt.max_depth, "depth",
728
+ "descend at most <depth> levels", PARSE_OPT_NONEG,
729
+ NULL, 1 },
730
OPT_GROUP(""),
731
OPT_BIT('E', "extended-regexp", &opt.regflags,
732
"use extended POSIX regular expressions", REG_EXTENDED),
803
opt.pathname = 1;
804
opt.pattern_tail = &opt.pattern_list;
805
opt.regflags = REG_NEWLINE;
806
+ opt.max_depth = -1;
807
808
strcpy(opt.color_match, GIT_COLOR_RED GIT_COLOR_BOLD);
809
opt.color = -1;