@matheusbsbs / matheus-bagliano / commits / d38f28093e
Fork 0

tree_entry_interesting(): support wildcard matching

never_interesting optimization is disabled if there is any wildcard pathspec, even if it only matches exactly on trees. 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 15, 2010 at 22:02 UTC d38f28093ef795bef13d2fda6621b4952afb42db
5 files changed +47 -4
cache.h
+2
@@ -503,11 +503,13 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct
503 struct pathspec {
504 const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
505 int nr;
506 + int has_wildcard:1;
507 int recursive:1;
508 int max_depth;
509 struct pathspec_item {
510 const char *match;
511 int len;
512 + int has_wildcard:1;
513 } *items;
514 };
515
dir.c
+3
@@ -1197,6 +1197,9 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
1197
1198 item->match = path;
1199 item->len = strlen(path);
1200 + item->has_wildcard = !no_wildcard(path);
1201 + if (item->has_wildcard)
1202 + pathspec->has_wildcard = 1;
1203 }
1204
1205 qsort(pathspec->items, pathspec->nr,
t/t4010-diff-pathspec.sh
+14
@@ -70,4 +70,18 @@ test_expect_success 'diff-tree pathspec' '
70 test_cmp expected current
71 '
72
73 +EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904
74 +
75 +test_expect_success 'diff-tree with wildcard shows dir also matches' '
76 + git diff-tree --name-only $EMPTY_TREE $tree -- "f*" >result &&
77 + echo file0 >expected &&
78 + test_cmp expected result
79 +'
80 +
81 +test_expect_success 'diff-tree -r with wildcard' '
82 + git diff-tree -r --name-only $EMPTY_TREE $tree -- "*file1" >result &&
83 + echo path1/file1 >expected &&
84 + test_cmp expected result
85 +'
86 +
87 test_done
tree-walk.c
+27 -3
@@ -553,12 +553,12 @@ static int match_dir_prefix(const char *base, int baselen,
553 * - negative for "no, and no subsequent entries will be either"
554 */
555 int tree_entry_interesting(const struct name_entry *entry,
556 - const struct strbuf *base,
556 + struct strbuf *base,
557 const struct pathspec *ps)
558 {
559 int i;
560 int pathlen, baselen = base->len;
561 - int never_interesting = -1;
561 + int never_interesting = ps->has_wildcard ? 0 : -1;
562
563 if (!ps->nr) {
564 if (!ps->recursive || ps->max_depth == -1)
@@ -578,7 +578,7 @@ int tree_entry_interesting(const struct name_entry *entry,
578 if (baselen >= matchlen) {
579 /* If it doesn't match, move along... */
580 if (!match_dir_prefix(base->buf, baselen, match, matchlen))
581 - continue;
581 + goto match_wildcards;
582
583 if (!ps->recursive || ps->max_depth == -1)
584 return 2;
@@ -596,6 +596,30 @@ int tree_entry_interesting(const struct name_entry *entry,
596 &never_interesting))
597 return 1;
598 }
599 +
600 +match_wildcards:
601 + if (!ps->items[i].has_wildcard)
602 + continue;
603 +
604 + /*
605 + * Concatenate base and entry->path into one and do
606 + * fnmatch() on it.
607 + */
608 +
609 + strbuf_add(base, entry->path, pathlen);
610 +
611 + if (!fnmatch(match, base->buf, 0)) {
612 + strbuf_setlen(base, baselen);
613 + return 1;
614 + }
615 + strbuf_setlen(base, baselen);
616 +
617 + /*
618 + * Match all directories. We'll try to match files
619 + * later on.
620 + */
621 + if (ps->recursive && S_ISDIR(entry->mode))
622 + return 1;
623 }
624 return never_interesting; /* No matches */
625 }
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 *, const struct strbuf *, const struct pathspec *ps);
63 +extern int tree_entry_interesting(const struct name_entry *, struct strbuf *, const struct pathspec *ps);
64
65 #endif