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>
This commit is contained in:
parent
86e4ca69e3
commit
d38f28093e
2
cache.h
2
cache.h
@ -503,11 +503,13 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct
|
|||||||
struct pathspec {
|
struct pathspec {
|
||||||
const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
|
const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
|
||||||
int nr;
|
int nr;
|
||||||
|
int has_wildcard:1;
|
||||||
int recursive:1;
|
int recursive:1;
|
||||||
int max_depth;
|
int max_depth;
|
||||||
struct pathspec_item {
|
struct pathspec_item {
|
||||||
const char *match;
|
const char *match;
|
||||||
int len;
|
int len;
|
||||||
|
int has_wildcard:1;
|
||||||
} *items;
|
} *items;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
3
dir.c
3
dir.c
@ -1197,6 +1197,9 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
|
|||||||
|
|
||||||
item->match = path;
|
item->match = path;
|
||||||
item->len = strlen(path);
|
item->len = strlen(path);
|
||||||
|
item->has_wildcard = !no_wildcard(path);
|
||||||
|
if (item->has_wildcard)
|
||||||
|
pathspec->has_wildcard = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
qsort(pathspec->items, pathspec->nr,
|
qsort(pathspec->items, pathspec->nr,
|
||||||
|
@ -70,4 +70,18 @@ test_expect_success 'diff-tree pathspec' '
|
|||||||
test_cmp expected current
|
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
|
test_done
|
||||||
|
30
tree-walk.c
30
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"
|
* - negative for "no, and no subsequent entries will be either"
|
||||||
*/
|
*/
|
||||||
int tree_entry_interesting(const struct name_entry *entry,
|
int tree_entry_interesting(const struct name_entry *entry,
|
||||||
const struct strbuf *base,
|
struct strbuf *base,
|
||||||
const struct pathspec *ps)
|
const struct pathspec *ps)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int pathlen, baselen = base->len;
|
int pathlen, baselen = base->len;
|
||||||
int never_interesting = -1;
|
int never_interesting = ps->has_wildcard ? 0 : -1;
|
||||||
|
|
||||||
if (!ps->nr) {
|
if (!ps->nr) {
|
||||||
if (!ps->recursive || ps->max_depth == -1)
|
if (!ps->recursive || ps->max_depth == -1)
|
||||||
@ -578,7 +578,7 @@ int tree_entry_interesting(const struct name_entry *entry,
|
|||||||
if (baselen >= matchlen) {
|
if (baselen >= matchlen) {
|
||||||
/* If it doesn't match, move along... */
|
/* If it doesn't match, move along... */
|
||||||
if (!match_dir_prefix(base->buf, baselen, match, matchlen))
|
if (!match_dir_prefix(base->buf, baselen, match, matchlen))
|
||||||
continue;
|
goto match_wildcards;
|
||||||
|
|
||||||
if (!ps->recursive || ps->max_depth == -1)
|
if (!ps->recursive || ps->max_depth == -1)
|
||||||
return 2;
|
return 2;
|
||||||
@ -596,6 +596,30 @@ int tree_entry_interesting(const struct name_entry *entry,
|
|||||||
&never_interesting))
|
&never_interesting))
|
||||||
return 1;
|
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 */
|
return never_interesting; /* No matches */
|
||||||
}
|
}
|
||||||
|
@ -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);
|
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
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user