From 136f2e548a34f1f504b0f062f87ddf33e8d6e83b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 29 May 2006 12:16:12 -0700 Subject: [PATCH] Make "struct tree" contain the pointer to the tree buffer This allows us to avoid allocating information for names etc, because we can just use the information from the tree buffer directly. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-read-tree.c | 4 ++-- builtin-rev-list.c | 3 ++- fsck-objects.c | 7 +++---- object.c | 5 ++++- tree.c | 47 +++++++++++++++++++++------------------------ tree.h | 4 +++- 6 files changed, 36 insertions(+), 34 deletions(-) diff --git a/builtin-read-tree.c b/builtin-read-tree.c index 716f79251..6876f3d79 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -39,7 +39,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); @@ -67,7 +67,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; diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 5277d3cf1..72c1549c7 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -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; } diff --git a/fsck-objects.c b/fsck-objects.c index 1922b6d84..5e65df436 100644 --- a/fsck-objects.c +++ b/fsck-objects.c @@ -198,17 +198,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) { diff --git a/object.c b/object.c index 4d46e0d5e..1a7823c23 100644 --- a/object.c +++ b/object.c @@ -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); diff --git a/tree.c b/tree.c index d599fb5e1..1e76d9cc1 100644 --- a/tree.c +++ b/tree.c @@ -3,6 +3,7 @@ #include "blob.h" #include "commit.h" #include "tag.h" +#include "tree-walk.h" #include 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) diff --git a/tree.h b/tree.h index 330ab64bb..066ac5d5b 100644 --- a/tree.h +++ b/tree.h @@ -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; }; -- 2.26.2