Browse Source

Merge branch 'lt/tree-2'

* lt/tree-2:
  fetch.c: do not call process_tree() from process_tree().
  tree_entry(): new tree-walking helper function
  adjust to the rebased series by Linus.
  Remove "tree->entries" tree-entry list from tree parser
  Switch "read_tree_recursive()" over to tree-walk functionality
  Make "tree_entry" have a SHA1 instead of a union of object pointers
  Add raw tree buffer info to "struct tree"
  Remove last vestiges of generic tree_entry_list
  Convert fetch.c: process_tree() to raw tree walker
  Convert "mark_tree_uninteresting()" to raw tree walker
  Remove unused "zeropad" entry from tree_list_entry
  fsck-objects: avoid unnecessary tree_entry_list usage
  Remove "tree->entries" tree-entry list from tree parser
  builtin-read-tree.c: avoid tree_entry_list in prime_cache_tree_rec()
  Switch "read_tree_recursive()" over to tree-walk functionality
  Make "tree_entry" have a SHA1 instead of a union of object pointers
  Make "struct tree" contain the pointer to the tree buffer
maint
Junio C Hamano 19 years ago
parent
commit
16a4c6ee0d
  1. 4
      blame.c
  2. 26
      builtin-grep.c
  3. 2
      builtin-ls-tree.c
  4. 68
      builtin-read-tree.c
  5. 23
      builtin-rev-list.c
  6. 21
      builtin-tar-tree.c
  7. 31
      fetch.c
  8. 68
      fsck-objects.c
  9. 24
      http-push.c
  10. 7
      object.c
  11. 27
      pack-objects.c
  12. 26
      revision.c
  13. 33
      tree-walk.c
  14. 5
      tree-walk.h
  15. 124
      tree.c
  16. 20
      tree.h

4
blame.c

@ -149,7 +149,7 @@ static void free_patch(struct patch *p) @@ -149,7 +149,7 @@ static void free_patch(struct patch *p)
free(p);
}

static int get_blob_sha1_internal(unsigned char *sha1, const char *base,
static int get_blob_sha1_internal(const unsigned char *sha1, const char *base,
int baselen, const char *pathname,
unsigned mode, int stage);

@ -178,7 +178,7 @@ static int get_blob_sha1(struct tree *t, const char *pathname, @@ -178,7 +178,7 @@ static int get_blob_sha1(struct tree *t, const char *pathname,
return 0;
}

static int get_blob_sha1_internal(unsigned char *sha1, const char *base,
static int get_blob_sha1_internal(const unsigned char *sha1, const char *base,
int baselen, const char *pathname,
unsigned mode, int stage)
{

26
builtin-grep.c

@ -578,11 +578,9 @@ static int grep_tree(struct grep_opt *opt, const char **paths, @@ -578,11 +578,9 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
struct tree_desc *tree,
const char *tree_name, const char *base)
{
unsigned mode;
int len;
int hit = 0;
const char *path;
const unsigned char *sha1;
struct name_entry entry;
char *down;
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, @@ -597,36 +595,32 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
}
len = strlen(path_buf);

while (tree->size) {
int pathlen;
sha1 = tree_entry_extract(tree, &path, &mode);
pathlen = strlen(path);
strcpy(path_buf + len, path);
while (tree_entry(tree, &entry)) {
strcpy(path_buf + len, entry.path);

if (S_ISDIR(mode))
if (S_ISDIR(entry.mode))
/* Match "abc/" against pathspec to
* decide if we want to descend into "abc"
* directory.
*/
strcpy(path_buf + len + pathlen, "/");
strcpy(path_buf + len + entry.pathlen, "/");

if (!pathspec_matches(paths, down))
;
else if (S_ISREG(mode))
hit |= grep_sha1(opt, sha1, path_buf);
else if (S_ISDIR(mode)) {
else if (S_ISREG(entry.mode))
hit |= grep_sha1(opt, entry.sha1, path_buf);
else if (S_ISDIR(entry.mode)) {
char type[20];
struct tree_desc sub;
void *data;
data = read_sha1_file(sha1, type, &sub.size);
data = read_sha1_file(entry.sha1, type, &sub.size);
if (!data)
die("unable to read tree (%s)",
sha1_to_hex(sha1));
sha1_to_hex(entry.sha1));
sub.buf = data;
hit |= grep_tree(opt, paths, &sub, tree_name, down);
free(data);
}
update_tree_entry(tree);
}
return hit;
}

2
builtin-ls-tree.c

@ -53,7 +53,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname) @@ -53,7 +53,7 @@ static int show_recursive(const char *base, int baselen, const char *pathname)
}
}

static int show_tree(unsigned char *sha1, const char *base, int baselen,
static int show_tree(const unsigned char *sha1, const char *base, int baselen,
const char *pathname, unsigned mode, int stage)
{
int retval = 0;

68
builtin-read-tree.c

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@

#include "object.h"
#include "tree.h"
#include "tree-walk.h"
#include "cache-tree.h"
#include <sys/time.h>
#include <signal.h>
@ -29,7 +30,17 @@ static int merge_size = 0; @@ -29,7 +30,17 @@ static int merge_size = 0;

static struct object_list *trees = NULL;

static struct cache_entry df_conflict_entry = {
static struct cache_entry df_conflict_entry = {
};

struct tree_entry_list {
struct tree_entry_list *next;
unsigned directory : 1;
unsigned executable : 1;
unsigned symlink : 1;
unsigned int mode;
const char *name;
const unsigned char *sha1;
};

static struct tree_entry_list df_conflict_list = {
@ -39,7 +50,35 @@ static struct tree_entry_list df_conflict_list = { @@ -39,7 +50,35 @@ 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 struct tree_entry_list *create_tree_entry_list(struct tree *tree)
{
struct tree_desc desc;
struct name_entry one;
struct tree_entry_list *ret = NULL;
struct tree_entry_list **list_p = &ret;

desc.buf = tree->buffer;
desc.size = tree->size;

while (tree_entry(&desc, &one)) {
struct tree_entry_list *entry;

entry = xmalloc(sizeof(struct tree_entry_list));
entry->name = one.path;
entry->sha1 = one.sha1;
entry->mode = one.mode;
entry->directory = S_ISDIR(one.mode) != 0;
entry->executable = (one.mode & S_IXUSR) != 0;
entry->symlink = S_ISLNK(one.mode) != 0;
entry->next = NULL;

*list_p = entry;
list_p = &entry->next;
}
return ret;
}

static int entcmp(const char *name1, int dir1, const char *name2, int dir2)
{
int len1 = strlen(name1);
int len2 = strlen(name2);
@ -67,7 +106,7 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len, @@ -67,7 +106,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;
@ -161,9 +200,10 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len, @@ -161,9 +200,10 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,
}

if (posns[i]->directory) {
struct tree *tree = lookup_tree(posns[i]->sha1);
any_dirs = 1;
parse_tree(posns[i]->item.tree);
subposns[i] = posns[i]->item.tree->entries;
parse_tree(tree);
subposns[i] = create_tree_entry_list(tree);
posns[i] = posns[i]->next;
src[i + merge] = &df_conflict_entry;
continue;
@ -187,7 +227,7 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len, @@ -187,7 +227,7 @@ static int unpack_trees_rec(struct tree_entry_list **posns, int len,

any_files = 1;

memcpy(ce->sha1, posns[i]->item.any->sha1, 20);
memcpy(ce->sha1, posns[i]->sha1, 20);
src[i + merge] = ce;
subposns[i] = &df_conflict_list;
posns[i] = posns[i]->next;
@ -368,7 +408,7 @@ static int unpack_trees(merge_fn_t fn) @@ -368,7 +408,7 @@ static int unpack_trees(merge_fn_t fn)
if (len) {
posns = xmalloc(len * sizeof(struct tree_entry_list *));
for (i = 0; i < len; i++) {
posns[i] = ((struct tree *) posn->item)->entries;
posns[i] = create_tree_entry_list((struct tree *) posn->item);
posn = posn->next;
}
if (unpack_trees_rec(posns, len, "", fn, &indpos))
@ -775,19 +815,23 @@ static int read_cache_unmerged(void) @@ -775,19 +815,23 @@ static int read_cache_unmerged(void)

static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
{
struct tree_entry_list *ent;
struct tree_desc desc;
struct name_entry entry;
int cnt;

memcpy(it->sha1, tree->object.sha1, 20);
for (cnt = 0, ent = tree->entries; ent; ent = ent->next) {
if (!ent->directory)
desc.buf = tree->buffer;
desc.size = tree->size;
cnt = 0;
while (tree_entry(&desc, &entry)) {
if (!S_ISDIR(entry.mode))
cnt++;
else {
struct cache_tree_sub *sub;
struct tree *subtree = (struct tree *)ent->item.tree;
struct tree *subtree = lookup_tree(entry.sha1);
if (!subtree->object.parsed)
parse_tree(subtree);
sub = cache_tree_sub(it, ent->name);
sub = cache_tree_sub(it, entry.path);
sub->cache_tree = cache_tree();
prime_cache_tree_rec(sub->cache_tree, subtree);
cnt += sub->cache_tree->entry_count;

23
builtin-rev-list.c

@ -113,7 +113,8 @@ static struct object_list **process_tree(struct tree *tree, @@ -113,7 +113,8 @@ static struct object_list **process_tree(struct tree *tree,
const char *name)
{
struct object *obj = &tree->object;
struct tree_entry_list *entry;
struct tree_desc desc;
struct name_entry entry;
struct name_path me;

if (!revs.tree_objects)
@ -128,18 +129,18 @@ static struct object_list **process_tree(struct tree *tree, @@ -128,18 +129,18 @@ static struct object_list **process_tree(struct tree *tree,
me.up = path;
me.elem = name;
me.elem_len = strlen(name);
entry = tree->entries;
tree->entries = NULL;
while (entry) {
struct tree_entry_list *next = entry->next;
if (entry->directory)
p = process_tree(entry->item.tree, p, &me, entry->name);

desc.buf = tree->buffer;
desc.size = tree->size;

while (tree_entry(&desc, &entry)) {
if (S_ISDIR(entry.mode))
p = process_tree(lookup_tree(entry.sha1), p, &me, name);
else
p = process_blob(entry->item.blob, p, &me, entry->name);
free(entry->name);
free(entry);
entry = next;
p = process_blob(lookup_blob(entry.sha1), p, &me, name);
}
free(tree->buffer);
tree->buffer = NULL;
return p;
}


21
builtin-tar-tree.c

@ -271,30 +271,25 @@ static void write_global_extended_header(const unsigned char *sha1) @@ -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)
{
int pathlen = path->len;
struct name_entry entry;

while (tree->size) {
const char *name;
const unsigned char *sha1;
unsigned mode;
while (tree_entry(tree, &entry)) {
void *eltbuf;
char elttype[20];
unsigned long eltsize;

sha1 = tree_entry_extract(tree, &name, &mode);
update_tree_entry(tree);

eltbuf = read_sha1_file(sha1, elttype, &eltsize);
eltbuf = read_sha1_file(entry.sha1, elttype, &eltsize);
if (!eltbuf)
die("cannot read %s", sha1_to_hex(sha1));
die("cannot read %s", sha1_to_hex(entry.sha1));

path->len = pathlen;
strbuf_append_string(path, name);
if (S_ISDIR(mode))
strbuf_append_string(path, entry.path);
if (S_ISDIR(entry.mode))
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;
subtree.buf = eltbuf;
subtree.size = eltsize;

31
fetch.c

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
#include "cache.h"
#include "commit.h"
#include "tree.h"
#include "tree-walk.h"
#include "tag.h"
#include "blob.h"
#include "refs.h"
@ -37,21 +38,33 @@ static int process(struct object *obj); @@ -37,21 +38,33 @@ static int process(struct object *obj);

static int process_tree(struct tree *tree)
{
struct tree_entry_list *entry;
struct tree_desc desc;
struct name_entry entry;

if (parse_tree(tree))
return -1;

entry = tree->entries;
tree->entries = NULL;
while (entry) {
struct tree_entry_list *next = entry->next;
if (process(entry->item.any))
desc.buf = tree->buffer;
desc.size = tree->size;
while (tree_entry(&desc, &entry)) {
struct object *obj = NULL;

if (S_ISDIR(entry.mode)) {
struct tree *tree = lookup_tree(entry.sha1);
if (tree)
obj = &tree->object;
}
else {
struct blob *blob = lookup_blob(entry.sha1);
if (blob)
obj = &blob->object;
}
if (!obj || process(obj))
return -1;
free(entry->name);
free(entry);
entry = next;
}
free(tree->buffer);
tree->buffer = NULL;
tree->size = 0;
return 0;
}


68
fsck-objects.c

@ -9,8 +9,10 @@ @@ -9,8 +9,10 @@
#include "refs.h"
#include "pack.h"
#include "cache-tree.h"
#include "tree-walk.h"

#define REACHABLE 0x0001
#define SEEN 0x0002

static int show_root = 0;
static int show_tags = 0;
@ -115,15 +117,15 @@ static void check_connectivity(void) @@ -115,15 +117,15 @@ static void check_connectivity(void)
#define TREE_UNORDERED (-1)
#define TREE_HAS_DUPS (-2)

static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b)
static int verify_ordered(unsigned mode1, const char *name1, unsigned mode2, const char *name2)
{
int len1 = strlen(a->name);
int len2 = strlen(b->name);
int len1 = strlen(name1);
int len2 = strlen(name2);
int len = len1 < len2 ? len1 : len2;
unsigned char c1, c2;
int cmp;

cmp = memcmp(a->name, b->name, len);
cmp = memcmp(name1, name2, len);
if (cmp < 0)
return 0;
if (cmp > 0)
@ -134,8 +136,8 @@ static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) @@ -134,8 +136,8 @@ static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b)
* Now we need to order the next one, but turn
* a '\0' into a '/' for a directory entry.
*/
c1 = a->name[len];
c2 = b->name[len];
c1 = name1[len];
c2 = name2[len];
if (!c1 && !c2)
/*
* git-write-tree used to write out a nonsense tree that has
@ -143,9 +145,9 @@ static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b) @@ -143,9 +145,9 @@ static int verify_ordered(struct tree_entry_list *a, struct tree_entry_list *b)
* sure we do not have duplicate entries.
*/
return TREE_HAS_DUPS;
if (!c1 && a->directory)
if (!c1 && S_ISDIR(mode1))
c1 = '/';
if (!c2 && b->directory)
if (!c2 && S_ISDIR(mode2))
c2 = '/';
return c1 < c2 ? 0 : TREE_UNORDERED;
}
@ -158,17 +160,32 @@ static int fsck_tree(struct tree *item) @@ -158,17 +160,32 @@ static int fsck_tree(struct tree *item)
int has_bad_modes = 0;
int has_dup_entries = 0;
int not_properly_sorted = 0;
struct tree_entry_list *entry, *last;
struct tree_desc desc;
unsigned o_mode;
const char *o_name;
const unsigned char *o_sha1;

last = NULL;
for (entry = item->entries; entry; entry = entry->next) {
if (strchr(entry->name, '/'))
desc.buf = item->buffer;
desc.size = item->size;

o_mode = 0;
o_name = NULL;
o_sha1 = NULL;
while (desc.size) {
unsigned mode;
const char *name;
const unsigned char *sha1;

sha1 = tree_entry_extract(&desc, &name, &mode);

if (strchr(name, '/'))
has_full_path = 1;
has_zero_pad |= entry->zeropad;
has_zero_pad |= *(char *)desc.buf == '0';
update_tree_entry(&desc);

switch (entry->mode) {
switch (mode) {
/*
* Standard modes..
* Standard modes..
*/
case S_IFREG | 0755:
case S_IFREG | 0644:
@ -187,8 +204,8 @@ static int fsck_tree(struct tree *item) @@ -187,8 +204,8 @@ static int fsck_tree(struct tree *item)
has_bad_modes = 1;
}

if (last) {
switch (verify_ordered(last, entry)) {
if (o_name) {
switch (verify_ordered(o_mode, o_name, mode, name)) {
case TREE_UNORDERED:
not_properly_sorted = 1;
break;
@ -198,17 +215,14 @@ static int fsck_tree(struct tree *item) @@ -198,17 +215,14 @@ static int fsck_tree(struct tree *item)
default:
break;
}
free(last->name);
free(last);
}

last = entry;
o_mode = mode;
o_name = name;
o_sha1 = sha1;
}
if (last) {
free(last->name);
free(last);
}
item->entries = NULL;
free(item->buffer);
item->buffer = NULL;

retval = 0;
if (has_full_path) {
@ -278,6 +292,9 @@ static int fsck_sha1(unsigned char *sha1) @@ -278,6 +292,9 @@ static int fsck_sha1(unsigned char *sha1)
struct object *obj = parse_object(sha1);
if (!obj)
return error("%s: object not found", sha1_to_hex(sha1));
if (obj->flags & SEEN)
return 0;
obj->flags |= SEEN;
if (obj->type == blob_type)
return 0;
if (obj->type == tree_type)
@ -465,6 +482,7 @@ int main(int argc, char **argv) @@ -465,6 +482,7 @@ int main(int argc, char **argv)
{
int i, heads;

track_object_refs = 1;
setup_git_directory();

for (i = 1; i < argc; i++) {

24
http-push.c

@ -1704,6 +1704,7 @@ static struct object_list **process_blob(struct blob *blob, @@ -1704,6 +1704,7 @@ static struct object_list **process_blob(struct blob *blob,
return p;

obj->flags |= SEEN;
name = strdup(name);
return add_object(obj, p, path, name);
}

@ -1713,7 +1714,8 @@ static struct object_list **process_tree(struct tree *tree, @@ -1713,7 +1714,8 @@ static struct object_list **process_tree(struct tree *tree,
const char *name)
{
struct object *obj = &tree->object;
struct tree_entry_list *entry;
struct tree_desc desc;
struct name_entry entry;
struct name_path me;

obj->flags |= LOCAL;
@ -1724,21 +1726,23 @@ static struct object_list **process_tree(struct tree *tree, @@ -1724,21 +1726,23 @@ static struct object_list **process_tree(struct tree *tree,
die("bad tree object %s", sha1_to_hex(obj->sha1));

obj->flags |= SEEN;
name = strdup(name);
p = add_object(obj, p, NULL, name);
me.up = path;
me.elem = name;
me.elem_len = strlen(name);
entry = tree->entries;
tree->entries = NULL;
while (entry) {
struct tree_entry_list *next = entry->next;
if (entry->directory)
p = process_tree(entry->item.tree, p, &me, entry->name);

desc.buf = tree->buffer;
desc.size = tree->size;

while (tree_entry(&desc, &entry)) {
if (S_ISDIR(entry.mode))
p = process_tree(lookup_tree(entry.sha1), p, &me, name);
else
p = process_blob(entry->item.blob, p, &me, entry->name);
free(entry);
entry = next;
p = process_blob(lookup_blob(entry.sha1), p, &me, name);
}
free(tree->buffer);
tree->buffer = NULL;
return p;
}


7
object.c

@ -9,7 +9,7 @@ struct object **objs; @@ -9,7 +9,7 @@ struct object **objs;
static int nr_objs;
int obj_allocs;

int track_object_refs = 1;
int track_object_refs = 0;

static int hashtable_index(const unsigned char *sha1)
{
@ -200,8 +200,11 @@ struct object *parse_object(const unsigned char *sha1) @@ -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);

27
pack-objects.c

@ -690,25 +690,20 @@ static void add_pbase_object(struct tree_desc *tree, @@ -690,25 +690,20 @@ static void add_pbase_object(struct tree_desc *tree,
const char *name,
int cmplen)
{
while (tree->size) {
const unsigned char *sha1;
const char *entry_name;
int entry_len;
unsigned mode;
struct name_entry entry;

while (tree_entry(tree,&entry)) {
unsigned long size;
char type[20];

sha1 = tree_entry_extract(tree, &entry_name, &mode);
update_tree_entry(tree);
entry_len = strlen(entry_name);
if (entry_len != cmplen ||
memcmp(entry_name, name, cmplen) ||
!has_sha1_file(sha1) ||
sha1_object_info(sha1, type, &size))
if (entry.pathlen != cmplen ||
memcmp(entry.path, name, cmplen) ||
!has_sha1_file(entry.sha1) ||
sha1_object_info(entry.sha1, type, &size))
continue;
if (name[cmplen] != '/') {
unsigned hash = name_hash(up, name);
add_object_entry(sha1, hash, 1);
add_object_entry(entry.sha1, hash, 1);
return;
}
if (!strcmp(type, tree_type)) {
@ -718,15 +713,15 @@ static void add_pbase_object(struct tree_desc *tree, @@ -718,15 +713,15 @@ static void add_pbase_object(struct tree_desc *tree,
const char *down = name+cmplen+1;
int downlen = name_cmp_len(down);

tree = pbase_tree_get(sha1);
tree = pbase_tree_get(entry.sha1);
if (!tree)
return;
sub.buf = tree->tree_data;
sub.size = tree->tree_size;

me.up = up;
me.elem = entry_name;
me.len = entry_len;
me.elem = entry.path;
me.len = entry.pathlen;
add_pbase_object(&sub, &me, down, downlen);
pbase_tree_put(tree);
}

26
revision.c

@ -53,8 +53,9 @@ static void mark_blob_uninteresting(struct blob *blob) @@ -53,8 +53,9 @@ static void mark_blob_uninteresting(struct blob *blob)

void mark_tree_uninteresting(struct tree *tree)
{
struct tree_desc desc;
struct name_entry entry;
struct object *obj = &tree->object;
struct tree_entry_list *entry;

if (obj->flags & UNINTERESTING)
return;
@ -63,17 +64,22 @@ void mark_tree_uninteresting(struct tree *tree) @@ -63,17 +64,22 @@ void mark_tree_uninteresting(struct tree *tree)
return;
if (parse_tree(tree) < 0)
die("bad tree %s", sha1_to_hex(obj->sha1));
entry = tree->entries;
tree->entries = NULL;
while (entry) {
struct tree_entry_list *next = entry->next;
if (entry->directory)
mark_tree_uninteresting(entry->item.tree);

desc.buf = tree->buffer;
desc.size = tree->size;
while (tree_entry(&desc, &entry)) {
if (S_ISDIR(entry.mode))
mark_tree_uninteresting(lookup_tree(entry.sha1));
else
mark_blob_uninteresting(entry->item.blob);
free(entry);
entry = next;
mark_blob_uninteresting(lookup_blob(entry.sha1));
}

/*
* We don't care about the tree any more
* after it has been marked uninteresting.
*/
free(tree->buffer);
tree->buffer = NULL;
}

void mark_parents_uninteresting(struct commit *commit)

33
tree-walk.c

@ -37,7 +37,7 @@ static void entry_extract(struct tree_desc *t, struct name_entry *a) @@ -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 *buf = desc->buf;
const void *buf = desc->buf;
unsigned long size = desc->size;
int len = strlen(buf) + 1 + 20;

@ -63,7 +63,7 @@ static const char *get_mode(const char *str, unsigned int *modep) @@ -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)
{
void *tree = desc->buf;
const void *tree = desc->buf;
unsigned long size = desc->size;
int len = strlen(tree)+1;
const unsigned char *sha1 = tree + len;
@ -78,6 +78,35 @@ const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pat @@ -78,6 +78,35 @@ const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pat
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)
{
struct name_entry *entry = xmalloc(n*sizeof(*entry));

5
tree-walk.h

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
#define TREE_WALK_H

struct tree_desc {
void *buf;
const void *buf;
unsigned long size;
};

@ -16,6 +16,9 @@ struct name_entry { @@ -16,6 +16,9 @@ struct name_entry {
void update_tree_entry(struct tree_desc *);
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);

typedef void (*traverse_callback_t)(int n, unsigned long mask, struct name_entry *entry, const char *base);

124
tree.c

@ -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)

20
tree.h

@ -5,24 +5,10 @@ @@ -5,24 +5,10 @@

extern const char *tree_type;

struct tree_entry_list {
struct tree_entry_list *next;
unsigned directory : 1;
unsigned executable : 1;
unsigned symlink : 1;
unsigned zeropad : 1;
unsigned int mode;
char *name;
union {
struct object *any;
struct tree *tree;
struct blob *blob;
} item;
};

struct tree {
struct object object;
struct tree_entry_list *entries;
void *buffer;
unsigned long size;
};

struct tree *lookup_tree(const unsigned char *sha1);
@ -35,7 +21,7 @@ int parse_tree(struct tree *tree); @@ -35,7 +21,7 @@ int parse_tree(struct tree *tree);
struct tree *parse_tree_indirect(const unsigned char *sha1);

#define READ_TREE_RECURSIVE 1
typedef int (*read_tree_fn_t)(unsigned char *, const char *, int, const char *, unsigned int, int);
typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int);

extern int read_tree_recursive(struct tree *tree,
const char *base, int baselen,

Loading…
Cancel
Save