const char *tree_type = "tree";
-static int read_one_entry(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
+static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
{
int len;
unsigned int size;
int stage, const char **match,
read_tree_fn_t fn)
{
- struct tree_entry_list *list;
+ struct tree_desc desc;
+ struct name_entry entry;
+
if (parse_tree(tree))
return -1;
- list = tree->entries;
- while (list) {
- struct tree_entry_list *current = list;
- list = list->next;
- if (!match_tree_entry(base, baselen, current->name,
- current->mode, match))
+
+ desc.buf = tree->buffer;
+ desc.size = tree->size;
+
+ while (tree_entry(&desc, &entry)) {
+ if (!match_tree_entry(base, baselen, entry.path, entry.mode, match))
continue;
- switch (fn(current->item.any->sha1, base, baselen,
- current->name, current->mode, stage)) {
+ switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage)) {
case 0:
continue;
case READ_TREE_RECURSIVE:
default:
return -1;
}
- if (current->directory) {
+ if (S_ISDIR(entry.mode)) {
int retval;
- int pathlen = strlen(current->name);
char *newbase;
- newbase = xmalloc(baselen + 1 + pathlen);
+ newbase = xmalloc(baselen + 1 + entry.pathlen);
memcpy(newbase, base, baselen);
- memcpy(newbase + baselen, current->name, pathlen);
- newbase[baselen + pathlen] = '/';
- retval = read_tree_recursive(current->item.tree,
+ memcpy(newbase + baselen, entry.path, entry.pathlen);
+ newbase[baselen + entry.pathlen] = '/';
+ retval = read_tree_recursive(lookup_tree(entry.sha1),
newbase,
- baselen + pathlen + 1,
+ baselen + entry.pathlen + 1,
stage, match, fn);
free(newbase);
if (retval)
{
struct object *obj = lookup_object(sha1);
if (!obj) {
- struct tree *ret = xcalloc(1, sizeof(struct tree));
+ struct tree *ret = alloc_tree_node();
created_object(sha1, &ret->object);
- ret->object.type = tree_type;
+ ret->object.type = TYPE_TREE;
return ret;
}
if (!obj->type)
- obj->type = tree_type;
- if (obj->type != tree_type) {
- error("Object %s is a %s, not a tree",
- sha1_to_hex(sha1), obj->type);
+ obj->type = TYPE_TREE;
+ if (obj->type != TYPE_TREE) {
+ error("Object %s is a %s, not a tree",
+ sha1_to_hex(sha1), typename(obj->type));
return NULL;
}
return (struct tree *) obj;
}
-int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
+static int track_tree_refs(struct tree *item)
{
+ int n_refs = 0, i;
+ struct object_refs *refs;
struct tree_desc desc;
- struct tree_entry_list **list_p;
- int n_refs = 0;
+ struct name_entry entry;
- if (item->object.parsed)
- return 0;
- item->object.parsed = 1;
- item->buffer = buffer;
- item->size = size;
-
- desc.buf = buffer;
- desc.size = size;
-
- list_p = &item->entries;
+ /* Count how many entries there are.. */
+ desc.buf = item->buffer;
+ desc.size = item->size;
while (desc.size) {
- unsigned mode;
- const char *path;
- const unsigned char *sha1;
- struct tree_entry_list *entry;
-
- sha1 = tree_entry_extract(&desc, &path, &mode);
-
- entry = xmalloc(sizeof(struct tree_entry_list));
- entry->name = path;
- entry->mode = mode;
- entry->directory = S_ISDIR(mode) != 0;
- entry->executable = (mode & S_IXUSR) != 0;
- entry->symlink = S_ISLNK(mode) != 0;
- entry->zeropad = *(const char *)(desc.buf) == '0';
- entry->next = NULL;
-
- update_tree_entry(&desc);
-
- if (entry->directory) {
- entry->item.tree = lookup_tree(sha1);
- } else {
- entry->item.blob = lookup_blob(sha1);
- }
n_refs++;
- *list_p = entry;
- list_p = &entry->next;
+ update_tree_entry(&desc);
}
- if (track_object_refs) {
- struct tree_entry_list *entry;
- unsigned i = 0;
- struct object_refs *refs = alloc_object_refs(n_refs);
- for (entry = item->entries; entry; entry = entry->next)
- refs->ref[i++] = entry->item.any;
- set_object_refs(&item->object, refs);
+ /* Allocate object refs and walk it again.. */
+ i = 0;
+ refs = alloc_object_refs(n_refs);
+ desc.buf = item->buffer;
+ desc.size = item->size;
+ while (tree_entry(&desc, &entry)) {
+ struct object *obj;
+
+ if (S_ISDIR(entry.mode))
+ obj = &lookup_tree(entry.sha1)->object;
+ else
+ obj = &lookup_blob(entry.sha1)->object;
+ refs->ref[i++] = obj;
}
+ set_object_refs(&item->object, refs);
+ return 0;
+}
+
+int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
+{
+ if (item->object.parsed)
+ return 0;
+ item->object.parsed = 1;
+ item->buffer = buffer;
+ item->size = size;
+ if (track_object_refs)
+ track_tree_refs(item);
return 0;
}
do {
if (!obj)
return NULL;
- if (obj->type == tree_type)
+ if (obj->type == TYPE_TREE)
return (struct tree *) obj;
- else if (obj->type == commit_type)
+ else if (obj->type == TYPE_COMMIT)
obj = &(((struct commit *) obj)->tree->object);
- else if (obj->type == tag_type)
+ else if (obj->type == TYPE_TAG)
obj = ((struct tag *) obj)->tagged;
else
return NULL;