Skip to content

Commit 1376e50

Browse files
pcloudsgitster
authored andcommitted
grep: drop pathspec_matches() in favor of tree_entry_interesting()
Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e5e062b commit 1376e50

File tree

4 files changed

+30
-125
lines changed

4 files changed

+30
-125
lines changed

builtin/grep.c

Lines changed: 14 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -329,106 +329,6 @@ static int grep_config(const char *var, const char *value, void *cb)
329329
return 0;
330330
}
331331

332-
/*
333-
* Return non-zero if max_depth is negative or path has no more then max_depth
334-
* slashes.
335-
*/
336-
static int accept_subdir(const char *path, int max_depth)
337-
{
338-
if (max_depth < 0)
339-
return 1;
340-
341-
while ((path = strchr(path, '/')) != NULL) {
342-
max_depth--;
343-
if (max_depth < 0)
344-
return 0;
345-
path++;
346-
}
347-
return 1;
348-
}
349-
350-
/*
351-
* Return non-zero if name is a subdirectory of match and is not too deep.
352-
*/
353-
static int is_subdir(const char *name, int namelen,
354-
const char *match, int matchlen, int max_depth)
355-
{
356-
if (matchlen > namelen || strncmp(name, match, matchlen))
357-
return 0;
358-
359-
if (name[matchlen] == '\0') /* exact match */
360-
return 1;
361-
362-
if (!matchlen || match[matchlen-1] == '/' || name[matchlen] == '/')
363-
return accept_subdir(name + matchlen + 1, max_depth);
364-
365-
return 0;
366-
}
367-
368-
/*
369-
* git grep pathspecs are somewhat different from diff-tree pathspecs;
370-
* pathname wildcards are allowed.
371-
*/
372-
static int pathspec_matches(const char **paths, const char *name, int max_depth)
373-
{
374-
int namelen, i;
375-
if (!paths || !*paths)
376-
return accept_subdir(name, max_depth);
377-
namelen = strlen(name);
378-
for (i = 0; paths[i]; i++) {
379-
const char *match = paths[i];
380-
int matchlen = strlen(match);
381-
const char *cp, *meta;
382-
383-
if (is_subdir(name, namelen, match, matchlen, max_depth))
384-
return 1;
385-
if (!fnmatch(match, name, 0))
386-
return 1;
387-
if (name[namelen-1] != '/')
388-
continue;
389-
390-
/* We are being asked if the directory ("name") is worth
391-
* descending into.
392-
*
393-
* Find the longest leading directory name that does
394-
* not have metacharacter in the pathspec; the name
395-
* we are looking at must overlap with that directory.
396-
*/
397-
for (cp = match, meta = NULL; cp - match < matchlen; cp++) {
398-
char ch = *cp;
399-
if (ch == '*' || ch == '[' || ch == '?') {
400-
meta = cp;
401-
break;
402-
}
403-
}
404-
if (!meta)
405-
meta = cp; /* fully literal */
406-
407-
if (namelen <= meta - match) {
408-
/* Looking at "Documentation/" and
409-
* the pattern says "Documentation/howto/", or
410-
* "Documentation/diff*.txt". The name we
411-
* have should match prefix.
412-
*/
413-
if (!memcmp(match, name, namelen))
414-
return 1;
415-
continue;
416-
}
417-
418-
if (meta - match < namelen) {
419-
/* Looking at "Documentation/howto/" and
420-
* the pattern says "Documentation/h*";
421-
* match up to "Do.../h"; this avoids descending
422-
* into "Documentation/technical/".
423-
*/
424-
if (!memcmp(match, name, meta - match))
425-
return 1;
426-
continue;
427-
}
428-
}
429-
return 0;
430-
}
431-
432332
static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)
433333
{
434334
void *data;
@@ -621,25 +521,24 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
621521
static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
622522
struct tree_desc *tree, struct strbuf *base, int tn_len)
623523
{
624-
int hit = 0;
524+
int hit = 0, matched = 0;
625525
struct name_entry entry;
626526
int old_baselen = base->len;
627527

628528
while (tree_entry(tree, &entry)) {
629529
int te_len = tree_entry_len(entry.path, entry.sha1);
630530

631-
strbuf_add(base, entry.path, te_len);
531+
if (matched != 2) {
532+
matched = tree_entry_interesting(&entry, base, tn_len, pathspec);
533+
if (matched == -1)
534+
break; /* no more matches */
535+
if (!matched)
536+
continue;
537+
}
632538

633-
if (S_ISDIR(entry.mode))
634-
/* Match "abc/" against pathspec to
635-
* decide if we want to descend into "abc"
636-
* directory.
637-
*/
638-
strbuf_addch(base, '/');
539+
strbuf_add(base, entry.path, te_len);
639540

640-
if (!pathspec_matches(pathspec->raw, base->buf + tn_len, opt->max_depth))
641-
;
642-
else if (S_ISREG(entry.mode)) {
541+
if (S_ISREG(entry.mode)) {
643542
hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len);
644543
}
645544
else if (S_ISDIR(entry.mode)) {
@@ -652,6 +551,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
652551
if (!data)
653552
die("unable to read tree (%s)",
654553
sha1_to_hex(entry.sha1));
554+
555+
strbuf_addch(base, '/');
655556
init_tree_desc(&sub, data, size);
656557
hit |= grep_tree(opt, pathspec, &sub, base, tn_len);
657558
free(data);
@@ -1058,6 +959,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
1058959
paths[1] = NULL;
1059960
}
1060961
init_pathspec(&pathspec, paths);
962+
pathspec.max_depth = opt.max_depth;
963+
pathspec.recursive = 1;
1061964

1062965
if (show_in_pager && (cached || list.nr))
1063966
die("--open-files-in-pager only works on the worktree");

tree-diff.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static void show_tree(struct diff_options *opt, const char *prefix,
7272
if (all_interesting)
7373
show = 1;
7474
else {
75-
show = tree_entry_interesting(&desc->entry, base,
75+
show = tree_entry_interesting(&desc->entry, base, 0,
7676
&opt->pathspec);
7777
if (show == 2)
7878
all_interesting = 1;
@@ -124,7 +124,7 @@ static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
124124
struct diff_options *opt, int *all_interesting)
125125
{
126126
while (t->size) {
127-
int show = tree_entry_interesting(&t->entry, base, &opt->pathspec);
127+
int show = tree_entry_interesting(&t->entry, base, 0, &opt->pathspec);
128128
if (show == 2)
129129
*all_interesting = 1;
130130
if (!show) {

tree-walk.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,8 @@ static int match_dir_prefix(const char *base, int baselen,
544544
/*
545545
* Is a tree entry interesting given the pathspec we have?
546546
*
547-
* Pre-condition: baselen == 0 || base[baselen-1] == '/'
547+
* Pre-condition: either baselen == base_offset (i.e. empty path)
548+
* or base[baselen-1] == '/' (i.e. with trailing slash).
548549
*
549550
* Return:
550551
* - 2 for "yes, and all subsequent entries will be"
@@ -553,44 +554,45 @@ static int match_dir_prefix(const char *base, int baselen,
553554
* - negative for "no, and no subsequent entries will be either"
554555
*/
555556
int tree_entry_interesting(const struct name_entry *entry,
556-
struct strbuf *base,
557+
struct strbuf *base, int base_offset,
557558
const struct pathspec *ps)
558559
{
559560
int i;
560-
int pathlen, baselen = base->len;
561+
int pathlen, baselen = base->len - base_offset;
561562
int never_interesting = ps->has_wildcard ? 0 : -1;
562563

563564
if (!ps->nr) {
564565
if (!ps->recursive || ps->max_depth == -1)
565566
return 2;
566-
return !!within_depth(base->buf, baselen,
567+
return !!within_depth(base->buf + base_offset, baselen,
567568
!!S_ISDIR(entry->mode),
568569
ps->max_depth);
569570
}
570571

571572
pathlen = tree_entry_len(entry->path, entry->sha1);
572573

573-
for (i = ps->nr-1; i >= 0; i--) {
574+
for (i = ps->nr - 1; i >= 0; i--) {
574575
const struct pathspec_item *item = ps->items+i;
575576
const char *match = item->match;
577+
const char *base_str = base->buf + base_offset;
576578
int matchlen = item->len;
577579

578580
if (baselen >= matchlen) {
579581
/* If it doesn't match, move along... */
580-
if (!match_dir_prefix(base->buf, baselen, match, matchlen))
582+
if (!match_dir_prefix(base_str, baselen, match, matchlen))
581583
goto match_wildcards;
582584

583585
if (!ps->recursive || ps->max_depth == -1)
584586
return 2;
585587

586-
return !!within_depth(base->buf + matchlen + 1,
588+
return !!within_depth(base_str + matchlen + 1,
587589
baselen - matchlen - 1,
588590
!!S_ISDIR(entry->mode),
589591
ps->max_depth);
590592
}
591593

592594
/* Does the base match? */
593-
if (!strncmp(base->buf, match, baselen)) {
595+
if (!strncmp(base_str, match, baselen)) {
594596
if (match_entry(entry, pathlen,
595597
match + baselen, matchlen - baselen,
596598
&never_interesting))
@@ -622,11 +624,11 @@ int tree_entry_interesting(const struct name_entry *entry,
622624

623625
strbuf_add(base, entry->path, pathlen);
624626

625-
if (!fnmatch(match, base->buf, 0)) {
626-
strbuf_setlen(base, baselen);
627+
if (!fnmatch(match, base->buf + base_offset, 0)) {
628+
strbuf_setlen(base, base_offset + baselen);
627629
return 1;
628630
}
629-
strbuf_setlen(base, baselen);
631+
strbuf_setlen(base, base_offset + baselen);
630632

631633
/*
632634
* Match all directories. We'll try to match files

tree-walk.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,6 @@ static inline int traverse_path_len(const struct traverse_info *info, const stru
6060
return info->pathlen + tree_entry_len(n->path, n->sha1);
6161
}
6262

63-
extern int tree_entry_interesting(const struct name_entry *, struct strbuf *, const struct pathspec *ps);
63+
extern int tree_entry_interesting(const struct name_entry *, struct strbuf *, int, const struct pathspec *ps);
6464

6565
#endif

0 commit comments

Comments
 (0)