зеркало из https://github.com/microsoft/git.git
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:
Родитель
f2cfc9c81e
Коммит
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);
|
||||
}
|
||||
|
||||
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;
|
||||
int pathlen;
|
||||
struct tree_desc desc;
|
||||
struct name_entry entry;
|
||||
unsigned char sha1[20];
|
||||
int len, retval = 0, oldlen = base->len;
|
||||
|
||||
if (!paths)
|
||||
return 1;
|
||||
pathlen = strlen(path);
|
||||
while ((match = *paths++) != NULL) {
|
||||
int matchlen = strlen(match);
|
||||
if (parse_tree(tree))
|
||||
return -1;
|
||||
|
||||
if (baselen >= matchlen) {
|
||||
/* 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;
|
||||
}
|
||||
init_tree_desc(&desc, tree->buffer, tree->size);
|
||||
|
||||
/* Does the base match? */
|
||||
if (strncmp(base, match, baselen))
|
||||
continue;
|
||||
|
||||
match += baselen;
|
||||
matchlen -= baselen;
|
||||
|
||||
if (pathlen > matchlen)
|
||||
continue;
|
||||
|
||||
if (matchlen > pathlen) {
|
||||
if (match[pathlen] != '/')
|
||||
continue;
|
||||
if (!S_ISDIR(mode))
|
||||
while (tree_entry(&desc, &entry)) {
|
||||
if (retval != 2) {
|
||||
retval = tree_entry_interesting(&entry, base, 0, pathspec);
|
||||
if (retval < 0)
|
||||
break;
|
||||
if (retval == 0)
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -99,74 +117,18 @@ int read_tree_recursive(struct tree *tree,
|
|||
int stage, const char **match,
|
||||
read_tree_fn_t fn, void *context)
|
||||
{
|
||||
struct tree_desc desc;
|
||||
struct name_entry entry;
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
struct pathspec pathspec;
|
||||
int i, ret;
|
||||
|
||||
if (parse_tree(tree))
|
||||
return -1;
|
||||
|
||||
init_tree_desc(&desc, tree->buffer, tree->size);
|
||||
|
||||
while (tree_entry(&desc, &entry)) {
|
||||
if (!match_tree_entry(base, baselen, entry.path, entry.mode, match))
|
||||
continue;
|
||||
|
||||
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;
|
||||
init_pathspec(&pathspec, match);
|
||||
for (i = 0; i < pathspec.nr; i++)
|
||||
pathspec.items[i].has_wildcard = 0;
|
||||
strbuf_add(&sb, base, baselen);
|
||||
ret = read_tree_1(tree, &sb, stage, &pathspec, fn, context);
|
||||
strbuf_release(&sb);
|
||||
free_pathspec(&pathspec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cmp_cache_name_compare(const void *a_, const void *b_)
|
||||
|
|
Загрузка…
Ссылка в новой задаче