Add raw tree buffer info to "struct tree"

This allows us to avoid allocating information for names etc, because
we can just use the information from the tree buffer directly.

We still keep the old "tree_entry_list" in struct tree as well, so old
users aren't affected, apart from the fact that the allocations are
different (if you free a tree entry, you should no longer free the name
allocation for it, since it's allocated as part of "tree->buffer")

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Linus Torvalds 2006-05-28 15:07:07 -07:00 committed by Junio C Hamano
parent 7d65848afd
commit d2eafb7661
6 changed files with 36 additions and 34 deletions

View File

@ -38,7 +38,7 @@ static struct tree_entry_list df_conflict_list = {
typedef int (*merge_fn_t)(struct cache_entry **src);
static int entcmp(char *name1, int dir1, char *name2, int dir2)
static int entcmp(const char *name1, int dir1, const char *name2, int dir2)
{
int len1 = strlen(name1);
int len2 = strlen(name2);
@ -66,7 +66,7 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
int src_size = len + 1;
do {
int i;
char *first;
const char *first;
int firstdir = 0;
int pathlen;
unsigned ce_size;

View File

@ -136,10 +136,11 @@ static struct object_list **process_tree(struct tree *tree,
p = process_tree(entry->item.tree, p, &me, entry->name);
else
p = process_blob(entry->item.blob, p, &me, entry->name);
free(entry->name);
free(entry);
entry = next;
}
free(tree->buffer);
tree->buffer = NULL;
return p;
}

View File

@ -197,17 +197,16 @@ static int fsck_tree(struct tree *item)
default:
break;
}
free(last->name);
free(last);
}
last = entry;
}
if (last) {
free(last->name);
if (last)
free(last);
}
item->entries = NULL;
free(item->buffer);
item->buffer = NULL;
retval = 0;
if (has_full_path) {

View File

@ -200,8 +200,11 @@ struct object *parse_object(const unsigned char *sha1)
obj = &blob->object;
} else if (!strcmp(type, tree_type)) {
struct tree *tree = lookup_tree(sha1);
parse_tree_buffer(tree, buffer, size);
obj = &tree->object;
if (!tree->object.parsed) {
parse_tree_buffer(tree, buffer, size);
buffer = NULL;
}
} else if (!strcmp(type, commit_type)) {
struct commit *commit = lookup_commit(sha1);
parse_commit_buffer(commit, buffer, size);

47
tree.c
View File

@ -3,6 +3,7 @@
#include "blob.h"
#include "commit.h"
#include "tag.h"
#include "tree-walk.h"
#include <stdlib.h>
const char *tree_type = "tree";
@ -145,46 +146,45 @@ struct tree *lookup_tree(const unsigned char *sha1)
int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
{
void *bufptr = buffer;
struct tree_desc desc;
struct tree_entry_list **list_p;
int n_refs = 0;
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;
while (size) {
struct object *obj;
while (desc.size) {
unsigned mode;
const char *path;
const unsigned char *sha1;
struct tree_entry_list *entry;
int len = 1+strlen(bufptr);
unsigned char *file_sha1 = bufptr + len;
char *path = strchr(bufptr, ' ');
unsigned int mode;
if (size < len + 20 || !path ||
sscanf(bufptr, "%o", &mode) != 1)
return -1;
sha1 = tree_entry_extract(&desc, &path, &mode);
entry = xmalloc(sizeof(struct tree_entry_list));
entry->name = strdup(path + 1);
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 = *(char *)bufptr == '0';
entry->mode = mode;
entry->zeropad = *(const char *)(desc.buf) == '0';
entry->next = NULL;
bufptr += len + 20;
size -= len + 20;
update_tree_entry(&desc);
if (entry->directory) {
entry->item.tree = lookup_tree(file_sha1);
obj = &entry->item.tree->object;
entry->item.tree = lookup_tree(sha1);
} else {
entry->item.blob = lookup_blob(file_sha1);
obj = &entry->item.blob->object;
entry->item.blob = lookup_blob(sha1);
}
if (obj)
n_refs++;
n_refs++;
*list_p = entry;
list_p = &entry->next;
}
@ -206,7 +206,6 @@ int parse_tree(struct tree *item)
char type[20];
void *buffer;
unsigned long size;
int ret;
if (item->object.parsed)
return 0;
@ -219,9 +218,7 @@ int parse_tree(struct tree *item)
return error("Object %s not a tree",
sha1_to_hex(item->object.sha1));
}
ret = parse_tree_buffer(item, buffer, size);
free(buffer);
return ret;
return parse_tree_buffer(item, buffer, size);
}
struct tree *parse_tree_indirect(const unsigned char *sha1)

4
tree.h
View File

@ -12,7 +12,7 @@ struct tree_entry_list {
unsigned symlink : 1;
unsigned zeropad : 1;
unsigned int mode;
char *name;
const char *name;
union {
struct object *any;
struct tree *tree;
@ -22,6 +22,8 @@ struct tree_entry_list {
struct tree {
struct object object;
void *buffer;
unsigned long size;
struct tree_entry_list *entries;
};