@ -3,11 +3,12 @@
@@ -3,11 +3,12 @@
#include "blob.h"
#include "commit.h"
#include "tag.h"
#include "tree-walk.h"
#include <stdlib.h>
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;
@ -77,19 +78,20 @@ int read_tree_recursive(struct tree *tree,
@@ -77,19 +78,20 @@ int read_tree_recursive(struct tree *tree,
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:
@ -97,18 +99,17 @@ int read_tree_recursive(struct tree *tree,
@@ -97,18 +99,17 @@ int read_tree_recursive(struct tree *tree,
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)
@ -143,61 +144,49 @@ struct tree *lookup_tree(const unsigned char *sha1)
@@ -143,61 +144,49 @@ struct tree *lookup_tree(const unsigned char *sha1)
return (struct tree *) obj;
}
int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
static int track_tree_refs(struct tree *item)
{
void *bufptr = buffer;
struct tree_entry_list **list_p;
int n_refs = 0;
int n_refs = 0, i;
struct object_refs *refs;
struct tree_desc desc;
struct name_entry entry;
/* Count how many entries there are.. */
desc.buf = item->buffer;
desc.size = item->size;
while (desc.size) {
n_refs++;
update_tree_entry(&desc);
}
if (item->object.parsed)
return 0;
item->object.parsed = 1;
list_p = &item->entries;
while (size) {
/* 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;
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;
entry = xmalloc(sizeof(struct tree_entry_list));
entry->name = strdup(path + 1);
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->next = NULL;
bufptr += len + 20;
size -= len + 20;
if (entry->directory) {
entry->item.tree = lookup_tree(file_sha1);
obj = &entry->item.tree->object;
} else {
entry->item.blob = lookup_blob(file_sha1);
obj = &entry->item.blob->object;
}
if (obj)
n_refs++;
*list_p = entry;
list_p = &entry->next;
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;
}
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);
}
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;
}
@ -206,7 +195,6 @@ int parse_tree(struct tree *item)
@@ -206,7 +195,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 +207,7 @@ int parse_tree(struct tree *item)
@@ -219,9 +207,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)