Merge branch 'lt/tree-2' into next

* lt/tree-2:
  tree_entry(): new tree-walking helper function
This commit is contained in:
Junio C Hamano 2006-05-31 14:23:58 -07:00
commit 422dfaf079
11 changed files with 112 additions and 141 deletions

View File

@ -578,11 +578,9 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
struct tree_desc *tree, struct tree_desc *tree,
const char *tree_name, const char *base) const char *tree_name, const char *base)
{ {
unsigned mode;
int len; int len;
int hit = 0; int hit = 0;
const char *path; struct name_entry entry;
const unsigned char *sha1;
char *down; char *down;
char *path_buf = xmalloc(PATH_MAX + strlen(tree_name) + 100); char *path_buf = xmalloc(PATH_MAX + strlen(tree_name) + 100);
@ -597,36 +595,32 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
} }
len = strlen(path_buf); len = strlen(path_buf);
while (tree->size) { while (tree_entry(tree, &entry)) {
int pathlen; strcpy(path_buf + len, entry.path);
sha1 = tree_entry_extract(tree, &path, &mode);
pathlen = strlen(path);
strcpy(path_buf + len, path);
if (S_ISDIR(mode)) if (S_ISDIR(entry.mode))
/* Match "abc/" against pathspec to /* Match "abc/" against pathspec to
* decide if we want to descend into "abc" * decide if we want to descend into "abc"
* directory. * directory.
*/ */
strcpy(path_buf + len + pathlen, "/"); strcpy(path_buf + len + entry.pathlen, "/");
if (!pathspec_matches(paths, down)) if (!pathspec_matches(paths, down))
; ;
else if (S_ISREG(mode)) else if (S_ISREG(entry.mode))
hit |= grep_sha1(opt, sha1, path_buf); hit |= grep_sha1(opt, entry.sha1, path_buf);
else if (S_ISDIR(mode)) { else if (S_ISDIR(entry.mode)) {
char type[20]; char type[20];
struct tree_desc sub; struct tree_desc sub;
void *data; void *data;
data = read_sha1_file(sha1, type, &sub.size); data = read_sha1_file(entry.sha1, type, &sub.size);
if (!data) if (!data)
die("unable to read tree (%s)", die("unable to read tree (%s)",
sha1_to_hex(sha1)); sha1_to_hex(entry.sha1));
sub.buf = data; sub.buf = data;
hit |= grep_tree(opt, paths, &sub, tree_name, down); hit |= grep_tree(opt, paths, &sub, tree_name, down);
free(data); free(data);
} }
update_tree_entry(tree);
} }
return hit; return hit;
} }

View File

@ -54,28 +54,23 @@ typedef int (*merge_fn_t)(struct cache_entry **src);
static struct tree_entry_list *create_tree_entry_list(struct tree *tree) static struct tree_entry_list *create_tree_entry_list(struct tree *tree)
{ {
struct tree_desc desc; struct tree_desc desc;
struct name_entry one;
struct tree_entry_list *ret = NULL; struct tree_entry_list *ret = NULL;
struct tree_entry_list **list_p = &ret; struct tree_entry_list **list_p = &ret;
desc.buf = tree->buffer; desc.buf = tree->buffer;
desc.size = tree->size; desc.size = tree->size;
while (desc.size) { while (tree_entry(&desc, &one)) {
unsigned mode;
const char *path;
const unsigned char *sha1;
struct tree_entry_list *entry; struct tree_entry_list *entry;
sha1 = tree_entry_extract(&desc, &path, &mode);
update_tree_entry(&desc);
entry = xmalloc(sizeof(struct tree_entry_list)); entry = xmalloc(sizeof(struct tree_entry_list));
entry->name = path; entry->name = one.path;
entry->sha1 = sha1; entry->sha1 = one.sha1;
entry->mode = mode; entry->mode = one.mode;
entry->directory = S_ISDIR(mode) != 0; entry->directory = S_ISDIR(one.mode) != 0;
entry->executable = (mode & S_IXUSR) != 0; entry->executable = (one.mode & S_IXUSR) != 0;
entry->symlink = S_ISLNK(mode) != 0; entry->symlink = S_ISLNK(one.mode) != 0;
entry->next = NULL; entry->next = NULL;
*list_p = entry; *list_p = entry;
@ -846,27 +841,22 @@ static int read_cache_unmerged(void)
static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree) static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
{ {
struct tree_desc desc; struct tree_desc desc;
struct name_entry entry;
int cnt; int cnt;
memcpy(it->sha1, tree->object.sha1, 20); memcpy(it->sha1, tree->object.sha1, 20);
desc.buf = tree->buffer; desc.buf = tree->buffer;
desc.size = tree->size; desc.size = tree->size;
cnt = 0; cnt = 0;
while (desc.size) { while (tree_entry(&desc, &entry)) {
unsigned mode; if (!S_ISDIR(entry.mode))
const char *name;
const unsigned char *sha1;
sha1 = tree_entry_extract(&desc, &name, &mode);
update_tree_entry(&desc);
if (!S_ISDIR(mode))
cnt++; cnt++;
else { else {
struct cache_tree_sub *sub; struct cache_tree_sub *sub;
struct tree *subtree = lookup_tree(sha1); struct tree *subtree = lookup_tree(entry.sha1);
if (!subtree->object.parsed) if (!subtree->object.parsed)
parse_tree(subtree); parse_tree(subtree);
sub = cache_tree_sub(it, name); sub = cache_tree_sub(it, entry.path);
sub->cache_tree = cache_tree(); sub->cache_tree = cache_tree();
prime_cache_tree_rec(sub->cache_tree, subtree); prime_cache_tree_rec(sub->cache_tree, subtree);
cnt += sub->cache_tree->entry_count; cnt += sub->cache_tree->entry_count;

View File

@ -114,6 +114,7 @@ static struct object_list **process_tree(struct tree *tree,
{ {
struct object *obj = &tree->object; struct object *obj = &tree->object;
struct tree_desc desc; struct tree_desc desc;
struct name_entry entry;
struct name_path me; struct name_path me;
if (!revs.tree_objects) if (!revs.tree_objects)
@ -132,18 +133,11 @@ static struct object_list **process_tree(struct tree *tree,
desc.buf = tree->buffer; desc.buf = tree->buffer;
desc.size = tree->size; desc.size = tree->size;
while (desc.size) { while (tree_entry(&desc, &entry)) {
unsigned mode; if (S_ISDIR(entry.mode))
const char *name; p = process_tree(lookup_tree(entry.sha1), p, &me, name);
const unsigned char *sha1;
sha1 = tree_entry_extract(&desc, &name, &mode);
update_tree_entry(&desc);
if (S_ISDIR(mode))
p = process_tree(lookup_tree(sha1), p, &me, name);
else else
p = process_blob(lookup_blob(sha1), p, &me, name); p = process_blob(lookup_blob(entry.sha1), p, &me, name);
} }
free(tree->buffer); free(tree->buffer);
tree->buffer = NULL; tree->buffer = NULL;

View File

@ -271,30 +271,25 @@ static void write_global_extended_header(const unsigned char *sha1)
static void traverse_tree(struct tree_desc *tree, struct strbuf *path) static void traverse_tree(struct tree_desc *tree, struct strbuf *path)
{ {
int pathlen = path->len; int pathlen = path->len;
struct name_entry entry;
while (tree->size) { while (tree_entry(tree, &entry)) {
const char *name;
const unsigned char *sha1;
unsigned mode;
void *eltbuf; void *eltbuf;
char elttype[20]; char elttype[20];
unsigned long eltsize; unsigned long eltsize;
sha1 = tree_entry_extract(tree, &name, &mode); eltbuf = read_sha1_file(entry.sha1, elttype, &eltsize);
update_tree_entry(tree);
eltbuf = read_sha1_file(sha1, elttype, &eltsize);
if (!eltbuf) if (!eltbuf)
die("cannot read %s", sha1_to_hex(sha1)); die("cannot read %s", sha1_to_hex(entry.sha1));
path->len = pathlen; path->len = pathlen;
strbuf_append_string(path, name); strbuf_append_string(path, entry.path);
if (S_ISDIR(mode)) if (S_ISDIR(entry.mode))
strbuf_append_string(path, "/"); strbuf_append_string(path, "/");
write_entry(sha1, path, mode, eltbuf, eltsize); write_entry(entry.sha1, path, entry.mode, eltbuf, eltsize);
if (S_ISDIR(mode)) { if (S_ISDIR(entry.mode)) {
struct tree_desc subtree; struct tree_desc subtree;
subtree.buf = eltbuf; subtree.buf = eltbuf;
subtree.size = eltsize; subtree.size = eltsize;

16
fetch.c
View File

@ -39,25 +39,19 @@ static int process(struct object *obj);
static int process_tree(struct tree *tree) static int process_tree(struct tree *tree)
{ {
struct tree_desc desc; struct tree_desc desc;
struct name_entry entry;
if (parse_tree(tree)) if (parse_tree(tree))
return -1; return -1;
desc.buf = tree->buffer; desc.buf = tree->buffer;
desc.size = tree->size; desc.size = tree->size;
while (desc.size) { while (tree_entry(&desc, &entry)) {
unsigned mode; if (S_ISDIR(entry.mode)) {
const char *name; struct tree *tree = lookup_tree(entry.sha1);
const unsigned char *sha1;
sha1 = tree_entry_extract(&desc, &name, &mode);
update_tree_entry(&desc);
if (S_ISDIR(mode)) {
struct tree *tree = lookup_tree(sha1);
process_tree(tree); process_tree(tree);
} else { } else {
struct blob *blob = lookup_blob(sha1); struct blob *blob = lookup_blob(entry.sha1);
process(&blob->object); process(&blob->object);
} }
} }

View File

@ -1715,6 +1715,7 @@ static struct object_list **process_tree(struct tree *tree,
{ {
struct object *obj = &tree->object; struct object *obj = &tree->object;
struct tree_desc desc; struct tree_desc desc;
struct name_entry entry;
struct name_path me; struct name_path me;
obj->flags |= LOCAL; obj->flags |= LOCAL;
@ -1734,18 +1735,11 @@ static struct object_list **process_tree(struct tree *tree,
desc.buf = tree->buffer; desc.buf = tree->buffer;
desc.size = tree->size; desc.size = tree->size;
while (desc.size) { while (tree_entry(&desc, &entry)) {
unsigned mode; if (S_ISDIR(entry.mode))
const char *name; p = process_tree(lookup_tree(entry.sha1), p, &me, name);
const unsigned char *sha1;
sha1 = tree_entry_extract(&desc, &name, &mode);
update_tree_entry(&desc);
if (S_ISDIR(mode))
p = process_tree(lookup_tree(sha1), p, &me, name);
else else
p = process_blob(lookup_blob(sha1), p, &me, name); p = process_blob(lookup_blob(entry.sha1), p, &me, name);
} }
free(tree->buffer); free(tree->buffer);
tree->buffer = NULL; tree->buffer = NULL;

View File

@ -690,25 +690,20 @@ static void add_pbase_object(struct tree_desc *tree,
const char *name, const char *name,
int cmplen) int cmplen)
{ {
while (tree->size) { struct name_entry entry;
const unsigned char *sha1;
const char *entry_name; while (tree_entry(tree,&entry)) {
int entry_len;
unsigned mode;
unsigned long size; unsigned long size;
char type[20]; char type[20];
sha1 = tree_entry_extract(tree, &entry_name, &mode); if (entry.pathlen != cmplen ||
update_tree_entry(tree); memcmp(entry.path, name, cmplen) ||
entry_len = strlen(entry_name); !has_sha1_file(entry.sha1) ||
if (entry_len != cmplen || sha1_object_info(entry.sha1, type, &size))
memcmp(entry_name, name, cmplen) ||
!has_sha1_file(sha1) ||
sha1_object_info(sha1, type, &size))
continue; continue;
if (name[cmplen] != '/') { if (name[cmplen] != '/') {
unsigned hash = name_hash(up, name); unsigned hash = name_hash(up, name);
add_object_entry(sha1, hash, 1); add_object_entry(entry.sha1, hash, 1);
return; return;
} }
if (!strcmp(type, tree_type)) { if (!strcmp(type, tree_type)) {
@ -718,15 +713,15 @@ static void add_pbase_object(struct tree_desc *tree,
const char *down = name+cmplen+1; const char *down = name+cmplen+1;
int downlen = name_cmp_len(down); int downlen = name_cmp_len(down);
tree = pbase_tree_get(sha1); tree = pbase_tree_get(entry.sha1);
if (!tree) if (!tree)
return; return;
sub.buf = tree->tree_data; sub.buf = tree->tree_data;
sub.size = tree->tree_size; sub.size = tree->tree_size;
me.up = up; me.up = up;
me.elem = entry_name; me.elem = entry.path;
me.len = entry_len; me.len = entry.pathlen;
add_pbase_object(&sub, &me, down, downlen); add_pbase_object(&sub, &me, down, downlen);
pbase_tree_put(tree); pbase_tree_put(tree);
} }

View File

@ -54,6 +54,7 @@ static void mark_blob_uninteresting(struct blob *blob)
void mark_tree_uninteresting(struct tree *tree) void mark_tree_uninteresting(struct tree *tree)
{ {
struct tree_desc desc; struct tree_desc desc;
struct name_entry entry;
struct object *obj = &tree->object; struct object *obj = &tree->object;
if (obj->flags & UNINTERESTING) if (obj->flags & UNINTERESTING)
@ -66,18 +67,11 @@ void mark_tree_uninteresting(struct tree *tree)
desc.buf = tree->buffer; desc.buf = tree->buffer;
desc.size = tree->size; desc.size = tree->size;
while (desc.size) { while (tree_entry(&desc, &entry)) {
unsigned mode; if (S_ISDIR(entry.mode))
const char *name; mark_tree_uninteresting(lookup_tree(entry.sha1));
const unsigned char *sha1;
sha1 = tree_entry_extract(&desc, &name, &mode);
update_tree_entry(&desc);
if (S_ISDIR(mode))
mark_tree_uninteresting(lookup_tree(sha1));
else else
mark_blob_uninteresting(lookup_blob(sha1)); mark_blob_uninteresting(lookup_blob(entry.sha1));
} }
/* /*

View File

@ -37,7 +37,7 @@ static void entry_extract(struct tree_desc *t, struct name_entry *a)
void update_tree_entry(struct tree_desc *desc) void update_tree_entry(struct tree_desc *desc)
{ {
void *buf = desc->buf; const void *buf = desc->buf;
unsigned long size = desc->size; unsigned long size = desc->size;
int len = strlen(buf) + 1 + 20; int len = strlen(buf) + 1 + 20;
@ -63,7 +63,7 @@ static const char *get_mode(const char *str, unsigned int *modep)
const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep) const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep)
{ {
void *tree = desc->buf; const void *tree = desc->buf;
unsigned long size = desc->size; unsigned long size = desc->size;
int len = strlen(tree)+1; int len = strlen(tree)+1;
const unsigned char *sha1 = tree + len; const unsigned char *sha1 = tree + len;
@ -78,6 +78,35 @@ const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pat
return sha1; return sha1;
} }
int tree_entry(struct tree_desc *desc, struct name_entry *entry)
{
const void *tree = desc->buf, *path;
unsigned long len, size = desc->size;
if (!size)
return 0;
path = get_mode(tree, &entry->mode);
if (!path)
die("corrupt tree file");
entry->path = path;
len = strlen(path);
entry->pathlen = len;
path += len + 1;
entry->sha1 = path;
path += 20;
len = path - tree;
if (len > size)
die("corrupt tree file");
desc->buf = path;
desc->size = size - len;
return 1;
}
void traverse_trees(int n, struct tree_desc *t, const char *base, traverse_callback_t callback) void traverse_trees(int n, struct tree_desc *t, const char *base, traverse_callback_t callback)
{ {
struct name_entry *entry = xmalloc(n*sizeof(*entry)); struct name_entry *entry = xmalloc(n*sizeof(*entry));

View File

@ -2,7 +2,7 @@
#define TREE_WALK_H #define TREE_WALK_H
struct tree_desc { struct tree_desc {
void *buf; const void *buf;
unsigned long size; unsigned long size;
}; };
@ -16,6 +16,9 @@ struct name_entry {
void update_tree_entry(struct tree_desc *); void update_tree_entry(struct tree_desc *);
const unsigned char *tree_entry_extract(struct tree_desc *, const char **, unsigned int *); const unsigned char *tree_entry_extract(struct tree_desc *, const char **, unsigned int *);
/* Helper function that does both of the above and returns true for success */
int tree_entry(struct tree_desc *, struct name_entry *);
void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1); void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1);
typedef void (*traverse_callback_t)(int n, unsigned long mask, struct name_entry *entry, const char *base); typedef void (*traverse_callback_t)(int n, unsigned long mask, struct name_entry *entry, const char *base);

41
tree.c
View File

@ -79,6 +79,7 @@ int read_tree_recursive(struct tree *tree,
read_tree_fn_t fn) read_tree_fn_t fn)
{ {
struct tree_desc desc; struct tree_desc desc;
struct name_entry entry;
if (parse_tree(tree)) if (parse_tree(tree))
return -1; return -1;
@ -86,18 +87,11 @@ int read_tree_recursive(struct tree *tree,
desc.buf = tree->buffer; desc.buf = tree->buffer;
desc.size = tree->size; desc.size = tree->size;
while (desc.size) { while (tree_entry(&desc, &entry)) {
unsigned mode; if (!match_tree_entry(base, baselen, entry.path, entry.mode, match))
const char *name;
const unsigned char *sha1;
sha1 = tree_entry_extract(&desc, &name, &mode);
update_tree_entry(&desc);
if (!match_tree_entry(base, baselen, name, mode, match))
continue; continue;
switch (fn(sha1, base, baselen, name, mode, stage)) { switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage)) {
case 0: case 0:
continue; continue;
case READ_TREE_RECURSIVE: case READ_TREE_RECURSIVE:
@ -105,18 +99,17 @@ int read_tree_recursive(struct tree *tree,
default: default:
return -1; return -1;
} }
if (S_ISDIR(mode)) { if (S_ISDIR(entry.mode)) {
int retval; int retval;
int pathlen = strlen(name);
char *newbase; char *newbase;
newbase = xmalloc(baselen + 1 + pathlen); newbase = xmalloc(baselen + 1 + entry.pathlen);
memcpy(newbase, base, baselen); memcpy(newbase, base, baselen);
memcpy(newbase + baselen, name, pathlen); memcpy(newbase + baselen, entry.path, entry.pathlen);
newbase[baselen + pathlen] = '/'; newbase[baselen + entry.pathlen] = '/';
retval = read_tree_recursive(lookup_tree(sha1), retval = read_tree_recursive(lookup_tree(entry.sha1),
newbase, newbase,
baselen + pathlen + 1, baselen + entry.pathlen + 1,
stage, match, fn); stage, match, fn);
free(newbase); free(newbase);
if (retval) if (retval)
@ -156,6 +149,7 @@ static int track_tree_refs(struct tree *item)
int n_refs = 0, i; int n_refs = 0, i;
struct object_refs *refs; struct object_refs *refs;
struct tree_desc desc; struct tree_desc desc;
struct name_entry entry;
/* Count how many entries there are.. */ /* Count how many entries there are.. */
desc.buf = item->buffer; desc.buf = item->buffer;
@ -170,18 +164,13 @@ static int track_tree_refs(struct tree *item)
refs = alloc_object_refs(n_refs); refs = alloc_object_refs(n_refs);
desc.buf = item->buffer; desc.buf = item->buffer;
desc.size = item->size; desc.size = item->size;
while (desc.size) { while (tree_entry(&desc, &entry)) {
unsigned mode;
const char *name;
const unsigned char *sha1;
struct object *obj; struct object *obj;
sha1 = tree_entry_extract(&desc, &name, &mode); if (S_ISDIR(entry.mode))
update_tree_entry(&desc); obj = &lookup_tree(entry.sha1)->object;
if (S_ISDIR(mode))
obj = &lookup_tree(sha1)->object;
else else
obj = &lookup_blob(sha1)->object; obj = &lookup_blob(entry.sha1)->object;
refs->ref[i++] = obj; refs->ref[i++] = obj;
} }
set_object_refs(&item->object, refs); set_object_refs(&item->object, refs);