From d38f28093ef795bef13d2fda6621b4952afb42db Mon Sep 17 00:00:00 2001 From: =?utf8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Wed, 15 Dec 2010 22:02:46 +0700 Subject: [PATCH] tree_entry_interesting(): support wildcard matching MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Junio C Hamano --- cache.h | 2 ++ dir.c | 3 +++ t/t4010-diff-pathspec.sh | 14 ++++++++++++++ tree-walk.c | 30 +++++++++++++++++++++++++++--- tree-walk.h | 2 +- 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/cache.h b/cache.h index 0cf0bac89..800efa232 100644 --- a/cache.h +++ b/cache.h @@ -503,11 +503,13 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct struct pathspec { const char **raw; /* get_pathspec() result, not freed by free_pathspec() */ int nr; + int has_wildcard:1; int recursive:1; int max_depth; struct pathspec_item { const char *match; int len; + int has_wildcard:1; } *items; }; diff --git a/dir.c b/dir.c index 5b4e2b1cb..b6ccaf370 100644 --- a/dir.c +++ b/dir.c @@ -1197,6 +1197,9 @@ int init_pathspec(struct pathspec *pathspec, const char **paths) item->match = path; item->len = strlen(path); + item->has_wildcard = !no_wildcard(path); + if (item->has_wildcard) + pathspec->has_wildcard = 1; } qsort(pathspec->items, pathspec->nr, diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh index 94df7ae53..4b120f8e2 100755 --- a/t/t4010-diff-pathspec.sh +++ b/t/t4010-diff-pathspec.sh @@ -70,4 +70,18 @@ test_expect_success 'diff-tree pathspec' ' test_cmp expected current ' +EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904 + +test_expect_success 'diff-tree with wildcard shows dir also matches' ' + git diff-tree --name-only $EMPTY_TREE $tree -- "f*" >result && + echo file0 >expected && + test_cmp expected result +' + +test_expect_success 'diff-tree -r with wildcard' ' + git diff-tree -r --name-only $EMPTY_TREE $tree -- "*file1" >result && + echo path1/file1 >expected && + test_cmp expected result +' + test_done diff --git a/tree-walk.c b/tree-walk.c index be8182c72..ae7ac1a9f 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -553,12 +553,12 @@ static int match_dir_prefix(const char *base, int baselen, * - negative for "no, and no subsequent entries will be either" */ int tree_entry_interesting(const struct name_entry *entry, - const struct strbuf *base, + struct strbuf *base, const struct pathspec *ps) { int i; int pathlen, baselen = base->len; - int never_interesting = -1; + int never_interesting = ps->has_wildcard ? 0 : -1; if (!ps->nr) { if (!ps->recursive || ps->max_depth == -1) @@ -578,7 +578,7 @@ int tree_entry_interesting(const struct name_entry *entry, if (baselen >= matchlen) { /* If it doesn't match, move along... */ if (!match_dir_prefix(base->buf, baselen, match, matchlen)) - continue; + goto match_wildcards; if (!ps->recursive || ps->max_depth == -1) return 2; @@ -596,6 +596,30 @@ int tree_entry_interesting(const struct name_entry *entry, &never_interesting)) return 1; } + +match_wildcards: + if (!ps->items[i].has_wildcard) + continue; + + /* + * Concatenate base and entry->path into one and do + * fnmatch() on it. + */ + + strbuf_add(base, entry->path, pathlen); + + if (!fnmatch(match, base->buf, 0)) { + strbuf_setlen(base, baselen); + return 1; + } + strbuf_setlen(base, baselen); + + /* + * Match all directories. We'll try to match files + * later on. + */ + if (ps->recursive && S_ISDIR(entry->mode)) + return 1; } return never_interesting; /* No matches */ } diff --git a/tree-walk.h b/tree-walk.h index f81c232b5..6589ee27e 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -60,6 +60,6 @@ static inline int traverse_path_len(const struct traverse_info *info, const stru return info->pathlen + tree_entry_len(n->path, n->sha1); } -extern int tree_entry_interesting(const struct name_entry *, const struct strbuf *, const struct pathspec *ps); +extern int tree_entry_interesting(const struct name_entry *, struct strbuf *, const struct pathspec *ps); #endif -- 2.30.2