@matheusbsbs / matheus-bagliano / commits / 1376e50723
Fork 0

grep: drop pathspec_matches() in favor of tree_entry_interesting()

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 Dec 17, 2010 at 19:45 UTC 1376e50723228fc21b7183fe86d71ee484a70dd7
4 files changed +30 -125
builtin/grep.c
+14 -111
@@ -329,106 +329,6 @@ static int grep_config(const char *var, const char *value, void *cb)
329 return 0;
330 }
331
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 -
332 static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)
333 {
334 void *data;
@@ -621,25 +521,24 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
521 static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
522 struct tree_desc *tree, struct strbuf *base, int tn_len)
523 {
624 - int hit = 0;
524 + int hit = 0, matched = 0;
525 struct name_entry entry;
526 int old_baselen = base->len;
527
528 while (tree_entry(tree, &entry)) {
529 int te_len = tree_entry_len(entry.path, entry.sha1);
530
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 + }
538
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);
540
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)) {
542 hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len);
543 }
544 else if (S_ISDIR(entry.mode)) {
@@ -652,6 +551,8 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
551 if (!data)
552 die("unable to read tree (%s)",
553 sha1_to_hex(entry.sha1));
554 +
555 + strbuf_addch(base, '/');
556 init_tree_desc(&sub, data, size);
557 hit |= grep_tree(opt, pathspec, &sub, base, tn_len);
558 free(data);
@@ -1058,6 +959,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
959 paths[1] = NULL;
960 }
961 init_pathspec(&pathspec, paths);
962 + pathspec.max_depth = opt.max_depth;
963 + pathspec.recursive = 1;
964
965 if (show_in_pager && (cached || list.nr))
966 die("--open-files-in-pager only works on the worktree");
tree-diff.c
+2 -2
@@ -72,7 +72,7 @@ static void show_tree(struct diff_options *opt, const char *prefix,
72 if (all_interesting)
73 show = 1;
74 else {
75 - show = tree_entry_interesting(&desc->entry, base,
75 + show = tree_entry_interesting(&desc->entry, base, 0,
76 &opt->pathspec);
77 if (show == 2)
78 all_interesting = 1;
@@ -124,7 +124,7 @@ static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
124 struct diff_options *opt, int *all_interesting)
125 {
126 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);
128 if (show == 2)
129 *all_interesting = 1;
130 if (!show) {
tree-walk.c
+13 -11
@@ -544,7 +544,8 @@ static int match_dir_prefix(const char *base, int baselen,
544 /*
545 * Is a tree entry interesting given the pathspec we have?
546 *
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).
549 *
550 * Return:
551 * - 2 for "yes, and all subsequent entries will be"
@@ -553,44 +554,45 @@ static int match_dir_prefix(const char *base, int baselen,
554 * - negative for "no, and no subsequent entries will be either"
555 */
556 int tree_entry_interesting(const struct name_entry *entry,
556 - struct strbuf *base,
557 + struct strbuf *base, int base_offset,
558 const struct pathspec *ps)
559 {
560 int i;
560 - int pathlen, baselen = base->len;
561 + int pathlen, baselen = base->len - base_offset;
562 int never_interesting = ps->has_wildcard ? 0 : -1;
563
564 if (!ps->nr) {
565 if (!ps->recursive || ps->max_depth == -1)
566 return 2;
566 - return !!within_depth(base->buf, baselen,
567 + return !!within_depth(base->buf + base_offset, baselen,
568 !!S_ISDIR(entry->mode),
569 ps->max_depth);
570 }
571
572 pathlen = tree_entry_len(entry->path, entry->sha1);
573
573 - for (i = ps->nr-1; i >= 0; i--) {
574 + for (i = ps->nr - 1; i >= 0; i--) {
575 const struct pathspec_item *item = ps->items+i;
576 const char *match = item->match;
577 + const char *base_str = base->buf + base_offset;
578 int matchlen = item->len;
579
580 if (baselen >= matchlen) {
581 /* 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))
583 goto match_wildcards;
584
585 if (!ps->recursive || ps->max_depth == -1)
586 return 2;
587
586 - return !!within_depth(base->buf + matchlen + 1,
588 + return !!within_depth(base_str + matchlen + 1,
589 baselen - matchlen - 1,
590 !!S_ISDIR(entry->mode),
591 ps->max_depth);
592 }
593
594 /* Does the base match? */
593 - if (!strncmp(base->buf, match, baselen)) {
595 + if (!strncmp(base_str, match, baselen)) {
596 if (match_entry(entry, pathlen,
597 match + baselen, matchlen - baselen,
598 &never_interesting))
@@ -622,11 +624,11 @@ match_wildcards:
624
625 strbuf_add(base, entry->path, pathlen);
626
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);
629 return 1;
630 }
629 - strbuf_setlen(base, baselen);
631 + strbuf_setlen(base, base_offset + baselen);
632
633 /*
634 * Match all directories. We'll try to match files
tree-walk.h
+1 -1
@@ -60,6 +60,6 @@ static inline int traverse_path_len(const struct traverse_info *info, const stru
60 return info->pathlen + tree_entry_len(n->path, n->sha1);
61 }
62
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);
64
65 #endif