X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=builtin-read-tree.c;h=00cdb5a6d9388c3a20e106c2047e7f6580b05ec6;hb=15b5536ee47c6684806edd7725adbbdede9fb95c;hp=716f7925142bca11cf7ab5438ce5908e55285463;hpb=3f69d405d749742945afd462bff6541604ecd420;p=git.git diff --git a/builtin-read-tree.c b/builtin-read-tree.c index 716f7925..00cdb5a6 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -9,6 +9,7 @@ #include "object.h" #include "tree.h" +#include "tree-walk.h" #include "cache-tree.h" #include #include @@ -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,40 @@ 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 tree_entry_list *ret = NULL; + struct tree_entry_list **list_p = &ret; + + desc.buf = tree->buffer; + desc.size = tree->size; + + while (desc.size) { + unsigned mode; + const char *path; + const unsigned char *sha1; + struct tree_entry_list *entry; + + sha1 = tree_entry_extract(&desc, &path, &mode); + update_tree_entry(&desc); + + entry = xmalloc(sizeof(struct tree_entry_list)); + entry->name = path; + entry->sha1 = sha1; + entry->mode = mode; + entry->directory = S_ISDIR(mode) != 0; + entry->executable = (mode & S_IXUSR) != 0; + entry->symlink = S_ISLNK(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 +111,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 +205,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 +232,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 +413,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)) @@ -774,19 +819,28 @@ 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; 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 (desc.size) { + unsigned mode; + const char *name; + const unsigned char *sha1; + + sha1 = tree_entry_extract(&desc, &name, &mode); + update_tree_entry(&desc); + if (!S_ISDIR(mode)) cnt++; else { struct cache_tree_sub *sub; - struct tree *subtree = (struct tree *)ent->item.tree; + struct tree *subtree = lookup_tree(sha1); if (!subtree->object.parsed) parse_tree(subtree); - sub = cache_tree_sub(it, ent->name); + sub = cache_tree_sub(it, name); sub->cache_tree = cache_tree(); prime_cache_tree_rec(sub->cache_tree, subtree); cnt += sub->cache_tree->entry_count;