diff options
Diffstat (limited to 'tree.c')
-rw-r--r-- | tree.c | 182 |
1 files changed, 47 insertions, 135 deletions
@@ -1,58 +1,24 @@ #include "cache.h" #include "cache-tree.h" #include "tree.h" +#include "object-store.h" #include "blob.h" #include "commit.h" #include "tag.h" +#include "alloc.h" #include "tree-walk.h" +#include "repository.h" const char *tree_type = "tree"; -static int read_one_entry_opt(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, int opt) -{ - int len; - unsigned int size; - struct cache_entry *ce; - - if (S_ISDIR(mode)) - return READ_TREE_RECURSIVE; - - len = strlen(pathname); - size = cache_entry_size(baselen + len); - ce = xcalloc(1, size); - - ce->ce_mode = create_ce_mode(mode); - ce->ce_flags = create_ce_flags(stage); - ce->ce_namelen = baselen + len; - memcpy(ce->name, base, baselen); - memcpy(ce->name + baselen, pathname, len+1); - hashcpy(ce->sha1, sha1); - return add_cache_entry(ce, opt); -} - -static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context) -{ - return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage, - ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK); -} - -/* - * This is used when the caller knows there is no existing entries at - * the stage that will conflict with the entry being added. - */ -static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context) -{ - return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage, - ADD_CACHE_JUST_APPEND); -} - -static int read_tree_1(struct tree *tree, struct strbuf *base, - int stage, struct pathspec *pathspec, - read_tree_fn_t fn, void *context) +int read_tree_at(struct repository *r, + struct tree *tree, struct strbuf *base, + const struct pathspec *pathspec, + read_tree_fn_t fn, void *context) { struct tree_desc desc; struct name_entry entry; - unsigned char sha1[20]; + struct object_id oid; int len, oldlen = base->len; enum interesting retval = entry_not_interesting; @@ -63,15 +29,16 @@ static int read_tree_1(struct tree *tree, struct strbuf *base, while (tree_entry(&desc, &entry)) { if (retval != all_entries_interesting) { - retval = tree_entry_interesting(&entry, base, 0, pathspec); + retval = tree_entry_interesting(r->index, &entry, + base, 0, pathspec); if (retval == all_entries_not_interesting) break; if (retval == entry_not_interesting) continue; } - switch (fn(entry.sha1, base->buf, base->len, - entry.path, entry.mode, stage, context)) { + switch (fn(&entry.oid, base, + entry.path, entry.mode, context)) { case 0: continue; case READ_TREE_RECURSIVE: @@ -81,22 +48,22 @@ static int read_tree_1(struct tree *tree, struct strbuf *base, } if (S_ISDIR(entry.mode)) - hashcpy(sha1, entry.sha1); + oidcpy(&oid, &entry.oid); else if (S_ISGITLINK(entry.mode)) { struct commit *commit; - commit = lookup_commit(entry.sha1); + commit = lookup_commit(r, &entry.oid); if (!commit) die("Commit %s in submodule path %s%s not found", - sha1_to_hex(entry.sha1), + oid_to_hex(&entry.oid), base->buf, entry.path); if (parse_commit(commit)) die("Invalid commit %s in submodule path %s%s", - sha1_to_hex(entry.sha1), + oid_to_hex(&entry.oid), base->buf, entry.path); - hashcpy(sha1, commit->tree->object.sha1); + oidcpy(&oid, get_commit_tree_oid(commit)); } else continue; @@ -104,9 +71,9 @@ static int read_tree_1(struct tree *tree, struct strbuf *base, len = tree_entry_len(&entry); strbuf_add(base, entry.path, len); strbuf_addch(base, '/'); - retval = read_tree_1(lookup_tree(sha1), - base, stage, pathspec, - fn, context); + retval = read_tree_at(r, lookup_tree(r, &oid), + base, pathspec, + fn, context); strbuf_setlen(base, oldlen); if (retval) return -1; @@ -114,21 +81,18 @@ static int read_tree_1(struct tree *tree, struct strbuf *base, return 0; } -int read_tree_recursive(struct tree *tree, - const char *base, int baselen, - int stage, struct pathspec *pathspec, - read_tree_fn_t fn, void *context) +int read_tree(struct repository *r, + struct tree *tree, + const struct pathspec *pathspec, + read_tree_fn_t fn, void *context) { struct strbuf sb = STRBUF_INIT; - int ret; - - strbuf_add(&sb, base, baselen); - ret = read_tree_1(tree, &sb, stage, pathspec, fn, context); + int ret = read_tree_at(r, tree, &sb, pathspec, fn, context); strbuf_release(&sb); return ret; } -static int cmp_cache_name_compare(const void *a_, const void *b_) +int cmp_cache_name_compare(const void *a_, const void *b_) { const struct cache_entry *ce1, *ce2; @@ -138,60 +102,12 @@ static int cmp_cache_name_compare(const void *a_, const void *b_) ce2->name, ce2->ce_namelen, ce_stage(ce2)); } -int read_tree(struct tree *tree, int stage, struct pathspec *match) +struct tree *lookup_tree(struct repository *r, const struct object_id *oid) { - read_tree_fn_t fn = NULL; - int i, err; - - /* - * Currently the only existing callers of this function all - * call it with stage=1 and after making sure there is nothing - * at that stage; we could always use read_one_entry_quick(). - * - * But when we decide to straighten out git-read-tree not to - * use unpack_trees() in some cases, this will probably start - * to matter. - */ - - /* - * See if we have cache entry at the stage. If so, - * do it the original slow way, otherwise, append and then - * sort at the end. - */ - for (i = 0; !fn && i < active_nr; i++) { - struct cache_entry *ce = active_cache[i]; - if (ce_stage(ce) == stage) - fn = read_one_entry; - } - - if (!fn) - fn = read_one_entry_quick; - err = read_tree_recursive(tree, "", 0, stage, match, fn, NULL); - if (fn == read_one_entry || err) - return err; - - /* - * Sort the cache entry -- we need to nuke the cache tree, though. - */ - cache_tree_free(&active_cache_tree); - qsort(active_cache, active_nr, sizeof(active_cache[0]), - cmp_cache_name_compare); - return 0; -} - -struct tree *lookup_tree(const unsigned char *sha1) -{ - struct object *obj = lookup_object(sha1); + struct object *obj = lookup_object(r, oid); if (!obj) - return create_object(sha1, OBJ_TREE, alloc_tree_node()); - if (!obj->type) - obj->type = OBJ_TREE; - if (obj->type != OBJ_TREE) { - error("Object %s is a %s, not a tree", - sha1_to_hex(sha1), typename(obj->type)); - return NULL; - } - return (struct tree *) obj; + return create_object(r, oid, alloc_tree_node(r)); + return object_as_type(obj, OBJ_TREE, 0); } int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size) @@ -205,7 +121,7 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size) return 0; } -int parse_tree(struct tree *item) +int parse_tree_gently(struct tree *item, int quiet_on_missing) { enum object_type type; void *buffer; @@ -213,33 +129,29 @@ int parse_tree(struct tree *item) if (item->object.parsed) return 0; - buffer = read_sha1_file(item->object.sha1, &type, &size); + buffer = read_object_file(&item->object.oid, &type, &size); if (!buffer) - return error("Could not read %s", - sha1_to_hex(item->object.sha1)); + return quiet_on_missing ? -1 : + error("Could not read %s", + oid_to_hex(&item->object.oid)); if (type != OBJ_TREE) { free(buffer); return error("Object %s not a tree", - sha1_to_hex(item->object.sha1)); + oid_to_hex(&item->object.oid)); } return parse_tree_buffer(item, buffer, size); } -struct tree *parse_tree_indirect(const unsigned char *sha1) +void free_tree_buffer(struct tree *tree) { - struct object *obj = parse_object(sha1); - do { - if (!obj) - return NULL; - if (obj->type == OBJ_TREE) - return (struct tree *) obj; - else if (obj->type == OBJ_COMMIT) - obj = &(((struct commit *) obj)->tree->object); - else if (obj->type == OBJ_TAG) - obj = ((struct tag *) obj)->tagged; - else - return NULL; - if (!obj->parsed) - parse_object(obj->sha1); - } while (1); + FREE_AND_NULL(tree->buffer); + tree->size = 0; + tree->object.parsed = 0; +} + +struct tree *parse_tree_indirect(const struct object_id *oid) +{ + struct repository *r = the_repository; + struct object *obj = parse_object(r, oid); + return (struct tree *)repo_peel_to_type(r, NULL, 0, obj, OBJ_TREE); } |