Skip to content

Commit f3badae

Browse files
peffgitster
authored andcommitted
list-objects: convert name_path to a strbuf
The "struct name_path" data is examined in only two places: we generate it in process_tree(), and we convert it to a single string in path_name(). Everyone else just passes it through to those functions. We can further note that process_tree() already keeps a single strbuf with the leading tree path, for use with tree_entry_interesting(). Instead of building a separate name_path linked list, let's just use the one we already build in "base". This reduces the amount of code (especially tricky code in path_name() which did not check for integer overflows caused by deep or large pathnames). It is also more efficient in some instances. Any time we were using tree_entry_interesting, we were building up the strbuf anyway, so this is an immediate and obvious win there. In cases where we were not, we trade off storing "pathname/" in a strbuf on the heap for each level of the path, instead of two pointers and an int on the stack (with one pointer into the tree object). On a 64-bit system, the latter is 20 bytes; so if path components are less than that on average, this has lower peak memory usage. In practice it probably doesn't matter either way; we are already holding in memory all of the tree objects leading up to each pathname, and for normal-depth pathnames, we are only talking about hundreds of bytes. This patch leaves "struct name_path" as a thin wrapper around the strbuf, to avoid disrupting callbacks. We should fix them, but leaving it out makes this diff easier to view. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8eee9f9 commit f3badae

File tree

3 files changed

+15
-36
lines changed

3 files changed

+15
-36
lines changed

list-objects.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ static void process_gitlink(struct rev_info *revs,
6262
static void process_tree(struct rev_info *revs,
6363
struct tree *tree,
6464
show_object_fn show,
65-
struct name_path *path,
6665
struct strbuf *base,
6766
const char *name,
6867
void *cb_data)
@@ -86,17 +85,14 @@ static void process_tree(struct rev_info *revs,
8685
return;
8786
die("bad tree object %s", sha1_to_hex(obj->sha1));
8887
}
88+
8989
obj->flags |= SEEN;
90-
show(obj, path, name, cb_data);
91-
me.up = path;
92-
me.elem = name;
93-
me.elem_len = strlen(name);
94-
95-
if (!match) {
96-
strbuf_addstr(base, name);
97-
if (base->len)
98-
strbuf_addch(base, '/');
99-
}
90+
me.base = base;
91+
show(obj, &me, name, cb_data);
92+
93+
strbuf_addstr(base, name);
94+
if (base->len)
95+
strbuf_addch(base, '/');
10096

10197
init_tree_desc(&desc, tree->buffer, tree->size);
10298

@@ -113,7 +109,7 @@ static void process_tree(struct rev_info *revs,
113109
if (S_ISDIR(entry.mode))
114110
process_tree(revs,
115111
lookup_tree(entry.sha1),
116-
show, &me, base, entry.path,
112+
show, base, entry.path,
117113
cb_data);
118114
else if (S_ISGITLINK(entry.mode))
119115
process_gitlink(revs, entry.sha1,
@@ -220,7 +216,7 @@ void traverse_commit_list(struct rev_info *revs,
220216
path = "";
221217
if (obj->type == OBJ_TREE) {
222218
process_tree(revs, (struct tree *)obj, show_object,
223-
NULL, &base, path, data);
219+
&base, path, data);
224220
continue;
225221
}
226222
if (obj->type == OBJ_BLOB) {

revision.c

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,11 @@ volatile show_early_output_fn_t show_early_output;
2323

2424
char *path_name(const struct name_path *path, const char *name)
2525
{
26-
const struct name_path *p;
27-
char *n, *m;
28-
int nlen = strlen(name);
29-
int len = nlen + 1;
30-
31-
for (p = path; p; p = p->up) {
32-
if (p->elem_len)
33-
len += p->elem_len + 1;
34-
}
35-
n = xmalloc(len);
36-
m = n + len - (nlen + 1);
37-
strcpy(m, name);
38-
for (p = path; p; p = p->up) {
39-
if (p->elem_len) {
40-
m -= p->elem_len + 1;
41-
memcpy(m, p->elem, p->elem_len);
42-
m[p->elem_len] = '/';
43-
}
44-
}
45-
return n;
26+
struct strbuf ret = STRBUF_INIT;
27+
if (path)
28+
strbuf_addbuf(&ret, path->base);
29+
strbuf_addstr(&ret, name);
30+
return strbuf_detach(&ret, NULL);
4631
}
4732

4833
void show_object_with_name(FILE *out, struct object *obj,

revision.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,7 @@ extern void mark_parents_uninteresting(struct commit *commit);
257257
extern void mark_tree_uninteresting(struct tree *tree);
258258

259259
struct name_path {
260-
struct name_path *up;
261-
int elem_len;
262-
const char *elem;
260+
struct strbuf *base;
263261
};
264262

265263
char *path_name(const struct name_path *path, const char *name);

0 commit comments

Comments
 (0)