Skip to content

Commit 2d9c58c

Browse files
Linus TorvaldsJunio C Hamano
Linus Torvalds
authored and
Junio C Hamano
committed
Remove "tree->entries" tree-entry list from tree parser
Instead, just use the tree buffer directly, and use the tree-walk infrastructure to walk the buffers instead of the tree-entry list. The tree-entry list is inefficient, and generates tons of small allocations for no good reason. The tree-walk infrastructure is generally no harder to use than following a linked list, and allows us to do most tree parsing in-place. Some programs still use the old tree-entry lists, and are a bit painful to convert without major surgery. For them we have a helper function that creates a temporary tree-entry list on demand. Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1ccf5a3 commit 2d9c58c

9 files changed

+116
-57
lines changed

builtin-ls-tree.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname)
5353
}
5454
}
5555

56-
static int show_tree(unsigned char *sha1, const char *base, int baselen,
56+
static int show_tree(const unsigned char *sha1, const char *base, int baselen,
5757
const char *pathname, unsigned mode, int stage)
5858
{
5959
int retval = 0;

builtin-read-tree.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
165165
struct tree *tree = lookup_tree(posns[i]->sha1);
166166
any_dirs = 1;
167167
parse_tree(tree);
168-
subposns[i] = tree->entries;
168+
subposns[i] = create_tree_entry_list(tree);
169169
posns[i] = posns[i]->next;
170170
src[i + merge] = &df_conflict_entry;
171171
continue;
@@ -370,7 +370,7 @@ static int unpack_trees(merge_fn_t fn)
370370
if (len) {
371371
posns = xmalloc(len * sizeof(struct tree_entry_list *));
372372
for (i = 0; i < len; i++) {
373-
posns[i] = ((struct tree *) posn->item)->entries;
373+
posns[i] = create_tree_entry_list((struct tree *) posn->item);
374374
posn = posn->next;
375375
}
376376
if (unpack_trees_rec(posns, len, "", fn, &indpos))

builtin-rev-list.c

+16-10
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ static struct object_list **process_tree(struct tree *tree,
113113
const char *name)
114114
{
115115
struct object *obj = &tree->object;
116-
struct tree_entry_list *entry;
116+
struct tree_desc desc;
117117
struct name_path me;
118118

119119
if (!revs.tree_objects)
@@ -128,16 +128,22 @@ static struct object_list **process_tree(struct tree *tree,
128128
me.up = path;
129129
me.elem = name;
130130
me.elem_len = strlen(name);
131-
entry = tree->entries;
132-
tree->entries = NULL;
133-
while (entry) {
134-
struct tree_entry_list *next = entry->next;
135-
if (entry->directory)
136-
p = process_tree(lookup_tree(entry->sha1), p, &me, entry->name);
131+
132+
desc.buf = tree->buffer;
133+
desc.size = tree->size;
134+
135+
while (desc.size) {
136+
unsigned mode;
137+
const char *name;
138+
const unsigned char *sha1;
139+
140+
sha1 = tree_entry_extract(&desc, &name, &mode);
141+
update_tree_entry(&desc);
142+
143+
if (S_ISDIR(mode))
144+
p = process_tree(lookup_tree(sha1), p, &me, name);
137145
else
138-
p = process_blob(lookup_blob(entry->sha1), p, &me, entry->name);
139-
free(entry);
140-
entry = next;
146+
p = process_blob(lookup_blob(sha1), p, &me, name);
141147
}
142148
free(tree->buffer);
143149
tree->buffer = NULL;

fetch.c

+11-5
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,22 @@ static int process_tree(struct tree *tree)
4141
if (parse_tree(tree))
4242
return -1;
4343

44-
entry = tree->entries;
45-
tree->entries = NULL;
44+
entry = create_tree_entry_list(tree);
4645
while (entry) {
4746
struct tree_entry_list *next = entry->next;
48-
if (process(entry->item.any))
49-
return -1;
50-
free(entry->name);
47+
48+
if (entry->directory) {
49+
struct tree *tree = lookup_tree(entry->sha1);
50+
process_tree(tree);
51+
} else {
52+
struct blob *blob = lookup_blob(entry->sha1);
53+
process(&blob->object);
54+
}
5155
free(entry);
5256
entry = next;
5357
}
58+
free(tree->buffer);
59+
tree->buffer = NULL;
5460
return 0;
5561
}
5662

fsck-objects.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "cache-tree.h"
1212

1313
#define REACHABLE 0x0001
14+
#define SEEN 0x0002
1415

1516
static int show_root = 0;
1617
static int show_tags = 0;
@@ -161,7 +162,7 @@ static int fsck_tree(struct tree *item)
161162
struct tree_entry_list *entry, *last;
162163

163164
last = NULL;
164-
for (entry = item->entries; entry; entry = entry->next) {
165+
for (entry = create_tree_entry_list(item); entry; entry = entry->next) {
165166
if (strchr(entry->name, '/'))
166167
has_full_path = 1;
167168
has_zero_pad |= entry->zeropad;
@@ -205,7 +206,6 @@ static int fsck_tree(struct tree *item)
205206
}
206207
if (last)
207208
free(last);
208-
item->entries = NULL;
209209
free(item->buffer);
210210
item->buffer = NULL;
211211

@@ -277,6 +277,9 @@ static int fsck_sha1(unsigned char *sha1)
277277
struct object *obj = parse_object(sha1);
278278
if (!obj)
279279
return error("%s: object not found", sha1_to_hex(sha1));
280+
if (obj->flags & SEEN)
281+
return 0;
282+
obj->flags |= SEEN;
280283
if (obj->type == blob_type)
281284
return 0;
282285
if (obj->type == tree_type)

http-push.c

+20-10
Original file line numberDiff line numberDiff line change
@@ -1704,6 +1704,7 @@ static struct object_list **process_blob(struct blob *blob,
17041704
return p;
17051705

17061706
obj->flags |= SEEN;
1707+
name = strdup(name);
17071708
return add_object(obj, p, path, name);
17081709
}
17091710

@@ -1713,7 +1714,7 @@ static struct object_list **process_tree(struct tree *tree,
17131714
const char *name)
17141715
{
17151716
struct object *obj = &tree->object;
1716-
struct tree_entry_list *entry;
1717+
struct tree_desc desc;
17171718
struct name_path me;
17181719

17191720
obj->flags |= LOCAL;
@@ -1724,21 +1725,30 @@ static struct object_list **process_tree(struct tree *tree,
17241725
die("bad tree object %s", sha1_to_hex(obj->sha1));
17251726

17261727
obj->flags |= SEEN;
1728+
name = strdup(name);
17271729
p = add_object(obj, p, NULL, name);
17281730
me.up = path;
17291731
me.elem = name;
17301732
me.elem_len = strlen(name);
1731-
entry = tree->entries;
1732-
tree->entries = NULL;
1733-
while (entry) {
1734-
struct tree_entry_list *next = entry->next;
1735-
if (entry->directory)
1736-
p = process_tree(lookup_tree(entry->sha1), p, &me, entry->name);
1733+
1734+
desc.buf = tree->buffer;
1735+
desc.size = tree->size;
1736+
1737+
while (desc.size) {
1738+
unsigned mode;
1739+
const char *name;
1740+
const unsigned char *sha1;
1741+
1742+
sha1 = tree_entry_extract(&desc, &name, &mode);
1743+
update_tree_entry(&desc);
1744+
1745+
if (S_ISDIR(mode))
1746+
p = process_tree(lookup_tree(sha1), p, &me, name);
17371747
else
1738-
p = process_blob(lookup_blob(entry->sha1), p, &me, entry->name);
1739-
free(entry);
1740-
entry = next;
1748+
p = process_blob(lookup_blob(sha1), p, &me, name);
17411749
}
1750+
free(tree->buffer);
1751+
tree->buffer = NULL;
17421752
return p;
17431753
}
17441754

revision.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ void mark_tree_uninteresting(struct tree *tree)
6363
return;
6464
if (parse_tree(tree) < 0)
6565
die("bad tree %s", sha1_to_hex(obj->sha1));
66-
entry = tree->entries;
67-
tree->entries = NULL;
66+
entry = create_tree_entry_list(tree);
6867
while (entry) {
6968
struct tree_entry_list *next = entry->next;
7069
if (entry->directory)

tree.c

+57-24
Original file line numberDiff line numberDiff line change
@@ -151,22 +151,65 @@ struct tree *lookup_tree(const unsigned char *sha1)
151151
return (struct tree *) obj;
152152
}
153153

154-
int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
154+
static int track_tree_refs(struct tree *item)
155155
{
156+
int n_refs = 0, i;
157+
struct object_refs *refs;
156158
struct tree_desc desc;
157-
struct tree_entry_list **list_p;
158-
int n_refs = 0;
159159

160+
/* Count how many entries there are.. */
161+
desc.buf = item->buffer;
162+
desc.size = item->size;
163+
while (desc.size) {
164+
n_refs++;
165+
update_tree_entry(&desc);
166+
}
167+
168+
/* Allocate object refs and walk it again.. */
169+
i = 0;
170+
refs = alloc_object_refs(n_refs);
171+
desc.buf = item->buffer;
172+
desc.size = item->size;
173+
while (desc.size) {
174+
unsigned mode;
175+
const char *name;
176+
const unsigned char *sha1;
177+
struct object *obj;
178+
179+
sha1 = tree_entry_extract(&desc, &name, &mode);
180+
update_tree_entry(&desc);
181+
if (S_ISDIR(mode))
182+
obj = &lookup_tree(sha1)->object;
183+
else
184+
obj = &lookup_blob(sha1)->object;
185+
refs->ref[i++] = obj;
186+
}
187+
set_object_refs(&item->object, refs);
188+
return 0;
189+
}
190+
191+
int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
192+
{
160193
if (item->object.parsed)
161194
return 0;
162195
item->object.parsed = 1;
163196
item->buffer = buffer;
164197
item->size = size;
165198

166-
desc.buf = buffer;
167-
desc.size = size;
199+
if (track_object_refs)
200+
track_tree_refs(item);
201+
return 0;
202+
}
203+
204+
struct tree_entry_list *create_tree_entry_list(struct tree *tree)
205+
{
206+
struct tree_desc desc;
207+
struct tree_entry_list *ret = NULL;
208+
struct tree_entry_list **list_p = &ret;
209+
210+
desc.buf = tree->buffer;
211+
desc.size = tree->size;
168212

169-
list_p = &item->entries;
170213
while (desc.size) {
171214
unsigned mode;
172215
const char *path;
@@ -186,29 +229,19 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
186229
entry->next = NULL;
187230

188231
update_tree_entry(&desc);
189-
n_refs++;
190232
*list_p = entry;
191233
list_p = &entry->next;
192234
}
235+
return ret;
236+
}
193237

194-
if (track_object_refs) {
195-
struct tree_entry_list *entry;
196-
unsigned i = 0;
197-
struct object_refs *refs = alloc_object_refs(n_refs);
198-
for (entry = item->entries; entry; entry = entry->next) {
199-
struct object *obj;
200-
201-
if (entry->directory)
202-
obj = &lookup_tree(entry->sha1)->object;
203-
else
204-
obj = &lookup_blob(entry->sha1)->object;
205-
refs->ref[i++] = obj;
206-
}
207-
208-
set_object_refs(&item->object, refs);
238+
void free_tree_entry_list(struct tree_entry_list *list)
239+
{
240+
while (list) {
241+
struct tree_entry_list *next = list->next;
242+
free(list);
243+
list = next;
209244
}
210-
211-
return 0;
212245
}
213246

214247
int parse_tree(struct tree *item)

tree.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ struct tree {
2020
struct object object;
2121
void *buffer;
2222
unsigned long size;
23-
struct tree_entry_list *entries;
2423
};
2524

25+
struct tree_entry_list *create_tree_entry_list(struct tree *);
26+
void free_tree_entry_list(struct tree_entry_list *);
27+
2628
struct tree *lookup_tree(const unsigned char *sha1);
2729

2830
int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size);

0 commit comments

Comments
 (0)