Reimplement read_tree_recursive() using tree_entry_interesting()
read_tree_recursive() uses a very similar function, match_tree_entry, to tree_entry_interesting() to do its path matching. This patch kills match_tree_entry() in favor of tree_entry_interesting(). match_tree_entry(), like older version of tree_entry_interesting(), does not support wildcard matching. New read_tree_recursive() retains this behavior by forcing all pathspecs literal. 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
f2cfc9c81e
commit
ffd31f661d
168
tree.c
168
tree.c
@ -45,51 +45,69 @@ static int read_one_entry_quick(const unsigned char *sha1, const char *base, int
|
|||||||
ADD_CACHE_JUST_APPEND);
|
ADD_CACHE_JUST_APPEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int match_tree_entry(const char *base, int baselen, const char *path, unsigned int mode, const char **paths)
|
static int read_tree_1(struct tree *tree, struct strbuf *base,
|
||||||
|
int stage, struct pathspec *pathspec,
|
||||||
|
read_tree_fn_t fn, void *context)
|
||||||
{
|
{
|
||||||
const char *match;
|
struct tree_desc desc;
|
||||||
int pathlen;
|
struct name_entry entry;
|
||||||
|
unsigned char sha1[20];
|
||||||
|
int len, retval = 0, oldlen = base->len;
|
||||||
|
|
||||||
if (!paths)
|
if (parse_tree(tree))
|
||||||
return 1;
|
return -1;
|
||||||
pathlen = strlen(path);
|
|
||||||
while ((match = *paths++) != NULL) {
|
|
||||||
int matchlen = strlen(match);
|
|
||||||
|
|
||||||
if (baselen >= matchlen) {
|
init_tree_desc(&desc, tree->buffer, tree->size);
|
||||||
/* If it doesn't match, move along... */
|
|
||||||
if (strncmp(base, match, matchlen))
|
|
||||||
continue;
|
|
||||||
/* pathspecs match only at the directory boundaries */
|
|
||||||
if (!matchlen ||
|
|
||||||
baselen == matchlen ||
|
|
||||||
base[matchlen] == '/' ||
|
|
||||||
match[matchlen - 1] == '/')
|
|
||||||
return 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Does the base match? */
|
while (tree_entry(&desc, &entry)) {
|
||||||
if (strncmp(base, match, baselen))
|
if (retval != 2) {
|
||||||
continue;
|
retval = tree_entry_interesting(&entry, base, 0, pathspec);
|
||||||
|
if (retval < 0)
|
||||||
match += baselen;
|
break;
|
||||||
matchlen -= baselen;
|
if (retval == 0)
|
||||||
|
|
||||||
if (pathlen > matchlen)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (matchlen > pathlen) {
|
|
||||||
if (match[pathlen] != '/')
|
|
||||||
continue;
|
|
||||||
if (!S_ISDIR(mode))
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(path, match, pathlen))
|
switch (fn(entry.sha1, base->buf, base->len,
|
||||||
|
entry.path, entry.mode, stage, context)) {
|
||||||
|
case 0:
|
||||||
|
continue;
|
||||||
|
case READ_TREE_RECURSIVE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_ISDIR(entry.mode))
|
||||||
|
hashcpy(sha1, entry.sha1);
|
||||||
|
else if (S_ISGITLINK(entry.mode)) {
|
||||||
|
struct commit *commit;
|
||||||
|
|
||||||
|
commit = lookup_commit(entry.sha1);
|
||||||
|
if (!commit)
|
||||||
|
die("Commit %s in submodule path %s%s not found",
|
||||||
|
sha1_to_hex(entry.sha1),
|
||||||
|
base->buf, entry.path);
|
||||||
|
|
||||||
|
if (parse_commit(commit))
|
||||||
|
die("Invalid commit %s in submodule path %s%s",
|
||||||
|
sha1_to_hex(entry.sha1),
|
||||||
|
base->buf, entry.path);
|
||||||
|
|
||||||
|
hashcpy(sha1, commit->tree->object.sha1);
|
||||||
|
}
|
||||||
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return 1;
|
len = tree_entry_len(entry.path, entry.sha1);
|
||||||
|
strbuf_add(base, entry.path, len);
|
||||||
|
strbuf_addch(base, '/');
|
||||||
|
retval = read_tree_1(lookup_tree(sha1),
|
||||||
|
base, stage, pathspec,
|
||||||
|
fn, context);
|
||||||
|
strbuf_setlen(base, oldlen);
|
||||||
|
if (retval)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -99,74 +117,18 @@ int read_tree_recursive(struct tree *tree,
|
|||||||
int stage, const char **match,
|
int stage, const char **match,
|
||||||
read_tree_fn_t fn, void *context)
|
read_tree_fn_t fn, void *context)
|
||||||
{
|
{
|
||||||
struct tree_desc desc;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
struct name_entry entry;
|
struct pathspec pathspec;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
if (parse_tree(tree))
|
init_pathspec(&pathspec, match);
|
||||||
return -1;
|
for (i = 0; i < pathspec.nr; i++)
|
||||||
|
pathspec.items[i].has_wildcard = 0;
|
||||||
init_tree_desc(&desc, tree->buffer, tree->size);
|
strbuf_add(&sb, base, baselen);
|
||||||
|
ret = read_tree_1(tree, &sb, stage, &pathspec, fn, context);
|
||||||
while (tree_entry(&desc, &entry)) {
|
strbuf_release(&sb);
|
||||||
if (!match_tree_entry(base, baselen, entry.path, entry.mode, match))
|
free_pathspec(&pathspec);
|
||||||
continue;
|
return ret;
|
||||||
|
|
||||||
switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) {
|
|
||||||
case 0:
|
|
||||||
continue;
|
|
||||||
case READ_TREE_RECURSIVE:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (S_ISDIR(entry.mode)) {
|
|
||||||
int retval;
|
|
||||||
char *newbase;
|
|
||||||
unsigned int pathlen = tree_entry_len(entry.path, entry.sha1);
|
|
||||||
|
|
||||||
newbase = xmalloc(baselen + 1 + pathlen);
|
|
||||||
memcpy(newbase, base, baselen);
|
|
||||||
memcpy(newbase + baselen, entry.path, pathlen);
|
|
||||||
newbase[baselen + pathlen] = '/';
|
|
||||||
retval = read_tree_recursive(lookup_tree(entry.sha1),
|
|
||||||
newbase,
|
|
||||||
baselen + pathlen + 1,
|
|
||||||
stage, match, fn, context);
|
|
||||||
free(newbase);
|
|
||||||
if (retval)
|
|
||||||
return -1;
|
|
||||||
continue;
|
|
||||||
} else if (S_ISGITLINK(entry.mode)) {
|
|
||||||
int retval;
|
|
||||||
struct strbuf path;
|
|
||||||
unsigned int entrylen;
|
|
||||||
struct commit *commit;
|
|
||||||
|
|
||||||
entrylen = tree_entry_len(entry.path, entry.sha1);
|
|
||||||
strbuf_init(&path, baselen + entrylen + 1);
|
|
||||||
strbuf_add(&path, base, baselen);
|
|
||||||
strbuf_add(&path, entry.path, entrylen);
|
|
||||||
strbuf_addch(&path, '/');
|
|
||||||
|
|
||||||
commit = lookup_commit(entry.sha1);
|
|
||||||
if (!commit)
|
|
||||||
die("Commit %s in submodule path %s not found",
|
|
||||||
sha1_to_hex(entry.sha1), path.buf);
|
|
||||||
|
|
||||||
if (parse_commit(commit))
|
|
||||||
die("Invalid commit %s in submodule path %s",
|
|
||||||
sha1_to_hex(entry.sha1), path.buf);
|
|
||||||
|
|
||||||
retval = read_tree_recursive(commit->tree,
|
|
||||||
path.buf, path.len,
|
|
||||||
stage, match, fn, context);
|
|
||||||
strbuf_release(&path);
|
|
||||||
if (retval)
|
|
||||||
return -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmp_cache_name_compare(const void *a_, const void *b_)
|
static int cmp_cache_name_compare(const void *a_, const void *b_)
|
||||||
|
Loading…
Reference in New Issue
Block a user