Skip to content

Commit ffd31f6

Browse files
pcloudsgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f2cfc9c commit ffd31f6

File tree

1 file changed

+57
-95
lines changed

1 file changed

+57
-95
lines changed

tree.c

Lines changed: 57 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -45,130 +45,92 @@ static int read_one_entry_quick(const unsigned char *sha1, const char *base, int
4545
ADD_CACHE_JUST_APPEND);
4646
}
4747

48-
static int match_tree_entry(const char *base, int baselen, const char *path, unsigned int mode, const char **paths)
49-
{
50-
const char *match;
51-
int pathlen;
52-
53-
if (!paths)
54-
return 1;
55-
pathlen = strlen(path);
56-
while ((match = *paths++) != NULL) {
57-
int matchlen = strlen(match);
58-
59-
if (baselen >= matchlen) {
60-
/* If it doesn't match, move along... */
61-
if (strncmp(base, match, matchlen))
62-
continue;
63-
/* pathspecs match only at the directory boundaries */
64-
if (!matchlen ||
65-
baselen == matchlen ||
66-
base[matchlen] == '/' ||
67-
match[matchlen - 1] == '/')
68-
return 1;
69-
continue;
70-
}
71-
72-
/* Does the base match? */
73-
if (strncmp(base, match, baselen))
74-
continue;
75-
76-
match += baselen;
77-
matchlen -= baselen;
78-
79-
if (pathlen > matchlen)
80-
continue;
81-
82-
if (matchlen > pathlen) {
83-
if (match[pathlen] != '/')
84-
continue;
85-
if (!S_ISDIR(mode))
86-
continue;
87-
}
88-
89-
if (strncmp(path, match, pathlen))
90-
continue;
91-
92-
return 1;
93-
}
94-
return 0;
95-
}
96-
97-
int read_tree_recursive(struct tree *tree,
98-
const char *base, int baselen,
99-
int stage, const char **match,
100-
read_tree_fn_t fn, void *context)
48+
static int read_tree_1(struct tree *tree, struct strbuf *base,
49+
int stage, struct pathspec *pathspec,
50+
read_tree_fn_t fn, void *context)
10151
{
10252
struct tree_desc desc;
10353
struct name_entry entry;
54+
unsigned char sha1[20];
55+
int len, retval = 0, oldlen = base->len;
10456

10557
if (parse_tree(tree))
10658
return -1;
10759

10860
init_tree_desc(&desc, tree->buffer, tree->size);
10961

11062
while (tree_entry(&desc, &entry)) {
111-
if (!match_tree_entry(base, baselen, entry.path, entry.mode, match))
112-
continue;
63+
if (retval != 2) {
64+
retval = tree_entry_interesting(&entry, base, 0, pathspec);
65+
if (retval < 0)
66+
break;
67+
if (retval == 0)
68+
continue;
69+
}
11370

114-
switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) {
71+
switch (fn(entry.sha1, base->buf, base->len,
72+
entry.path, entry.mode, stage, context)) {
11573
case 0:
11674
continue;
11775
case READ_TREE_RECURSIVE:
11876
break;
11977
default:
12078
return -1;
12179
}
122-
if (S_ISDIR(entry.mode)) {
123-
int retval;
124-
char *newbase;
125-
unsigned int pathlen = tree_entry_len(entry.path, entry.sha1);
126-
127-
newbase = xmalloc(baselen + 1 + pathlen);
128-
memcpy(newbase, base, baselen);
129-
memcpy(newbase + baselen, entry.path, pathlen);
130-
newbase[baselen + pathlen] = '/';
131-
retval = read_tree_recursive(lookup_tree(entry.sha1),
132-
newbase,
133-
baselen + pathlen + 1,
134-
stage, match, fn, context);
135-
free(newbase);
136-
if (retval)
137-
return -1;
138-
continue;
139-
} else if (S_ISGITLINK(entry.mode)) {
140-
int retval;
141-
struct strbuf path;
142-
unsigned int entrylen;
143-
struct commit *commit;
14480

145-
entrylen = tree_entry_len(entry.path, entry.sha1);
146-
strbuf_init(&path, baselen + entrylen + 1);
147-
strbuf_add(&path, base, baselen);
148-
strbuf_add(&path, entry.path, entrylen);
149-
strbuf_addch(&path, '/');
81+
if (S_ISDIR(entry.mode))
82+
hashcpy(sha1, entry.sha1);
83+
else if (S_ISGITLINK(entry.mode)) {
84+
struct commit *commit;
15085

15186
commit = lookup_commit(entry.sha1);
15287
if (!commit)
153-
die("Commit %s in submodule path %s not found",
154-
sha1_to_hex(entry.sha1), path.buf);
88+
die("Commit %s in submodule path %s%s not found",
89+
sha1_to_hex(entry.sha1),
90+
base->buf, entry.path);
15591

15692
if (parse_commit(commit))
157-
die("Invalid commit %s in submodule path %s",
158-
sha1_to_hex(entry.sha1), path.buf);
159-
160-
retval = read_tree_recursive(commit->tree,
161-
path.buf, path.len,
162-
stage, match, fn, context);
163-
strbuf_release(&path);
164-
if (retval)
165-
return -1;
166-
continue;
93+
die("Invalid commit %s in submodule path %s%s",
94+
sha1_to_hex(entry.sha1),
95+
base->buf, entry.path);
96+
97+
hashcpy(sha1, commit->tree->object.sha1);
16798
}
99+
else
100+
continue;
101+
102+
len = tree_entry_len(entry.path, entry.sha1);
103+
strbuf_add(base, entry.path, len);
104+
strbuf_addch(base, '/');
105+
retval = read_tree_1(lookup_tree(sha1),
106+
base, stage, pathspec,
107+
fn, context);
108+
strbuf_setlen(base, oldlen);
109+
if (retval)
110+
return -1;
168111
}
169112
return 0;
170113
}
171114

115+
int read_tree_recursive(struct tree *tree,
116+
const char *base, int baselen,
117+
int stage, const char **match,
118+
read_tree_fn_t fn, void *context)
119+
{
120+
struct strbuf sb = STRBUF_INIT;
121+
struct pathspec pathspec;
122+
int i, ret;
123+
124+
init_pathspec(&pathspec, match);
125+
for (i = 0; i < pathspec.nr; i++)
126+
pathspec.items[i].has_wildcard = 0;
127+
strbuf_add(&sb, base, baselen);
128+
ret = read_tree_1(tree, &sb, stage, &pathspec, fn, context);
129+
strbuf_release(&sb);
130+
free_pathspec(&pathspec);
131+
return ret;
132+
}
133+
172134
static int cmp_cache_name_compare(const void *a_, const void *b_)
173135
{
174136
const struct cache_entry *ce1, *ce2;

0 commit comments

Comments
 (0)