tree-walk: init_tree_desc take an oid to get the hash algorithm

To make it possible for git ls-tree to display the tree encoded
in the hash algorithm of the oid specified to git ls-tree, update
init_tree_desc to take as a parameter the oid of the tree object.

Update all callers of init_tree_desc and init_tree_desc_gently
to pass the oid of the tree object.

Use the oid of the tree object to discover the hash algorithm
of the oid and store that hash algorithm in struct tree_desc.

Use the hash algorithm in decode_tree_entry and
update_tree_entry_internal to handle reading a tree object encoded in
a hash algorithm that differs from the repositories hash algorithm.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Eric W. Biederman 2023-10-01 21:40:28 -05:00 committed by Junio C Hamano
parent d6222a2d05
commit efed687edc
28 changed files with 80 additions and 59 deletions

View file

@ -339,7 +339,8 @@ int write_archive_entries(struct archiver_args *args,
opts.src_index = args->repo->index; opts.src_index = args->repo->index;
opts.dst_index = args->repo->index; opts.dst_index = args->repo->index;
opts.fn = oneway_merge; opts.fn = oneway_merge;
init_tree_desc(&t, args->tree->buffer, args->tree->size); init_tree_desc(&t, &args->tree->object.oid,
args->tree->buffer, args->tree->size);
if (unpack_trees(1, &t, &opts)) if (unpack_trees(1, &t, &opts))
return -1; return -1;
git_attr_set_direction(GIT_ATTR_INDEX); git_attr_set_direction(GIT_ATTR_INDEX);

View file

@ -1991,8 +1991,8 @@ static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
opts.reset = reset ? UNPACK_RESET_PROTECT_UNTRACKED : 0; opts.reset = reset ? UNPACK_RESET_PROTECT_UNTRACKED : 0;
opts.preserve_ignored = 0; /* FIXME: !overwrite_ignore */ opts.preserve_ignored = 0; /* FIXME: !overwrite_ignore */
opts.fn = twoway_merge; opts.fn = twoway_merge;
init_tree_desc(&t[0], head->buffer, head->size); init_tree_desc(&t[0], &head->object.oid, head->buffer, head->size);
init_tree_desc(&t[1], remote->buffer, remote->size); init_tree_desc(&t[1], &remote->object.oid, remote->buffer, remote->size);
if (unpack_trees(2, t, &opts)) { if (unpack_trees(2, t, &opts)) {
rollback_lock_file(&lock_file); rollback_lock_file(&lock_file);
@ -2026,7 +2026,7 @@ static int merge_tree(struct tree *tree)
opts.dst_index = &the_index; opts.dst_index = &the_index;
opts.merge = 1; opts.merge = 1;
opts.fn = oneway_merge; opts.fn = oneway_merge;
init_tree_desc(&t[0], tree->buffer, tree->size); init_tree_desc(&t[0], &tree->object.oid, tree->buffer, tree->size);
if (unpack_trees(1, t, &opts)) { if (unpack_trees(1, t, &opts)) {
rollback_lock_file(&lock_file); rollback_lock_file(&lock_file);

View file

@ -701,7 +701,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
info->commit ? &info->commit->object.oid : null_oid(), info->commit ? &info->commit->object.oid : null_oid(),
NULL); NULL);
parse_tree(tree); parse_tree(tree);
init_tree_desc(&tree_desc, tree->buffer, tree->size); init_tree_desc(&tree_desc, &tree->object.oid, tree->buffer, tree->size);
switch (unpack_trees(1, &tree_desc, &opts)) { switch (unpack_trees(1, &tree_desc, &opts)) {
case -2: case -2:
*writeout_error = 1; *writeout_error = 1;
@ -815,10 +815,12 @@ static int merge_working_tree(const struct checkout_opts *opts,
die(_("unable to parse commit %s"), die(_("unable to parse commit %s"),
oid_to_hex(old_commit_oid)); oid_to_hex(old_commit_oid));
init_tree_desc(&trees[0], tree->buffer, tree->size); init_tree_desc(&trees[0], &tree->object.oid,
tree->buffer, tree->size);
parse_tree(new_tree); parse_tree(new_tree);
tree = new_tree; tree = new_tree;
init_tree_desc(&trees[1], tree->buffer, tree->size); init_tree_desc(&trees[1], &tree->object.oid,
tree->buffer, tree->size);
ret = unpack_trees(2, trees, &topts); ret = unpack_trees(2, trees, &topts);
clear_unpack_trees_porcelain(&topts); clear_unpack_trees_porcelain(&topts);

View file

@ -737,7 +737,7 @@ static int checkout(int submodule_progress, int filter_submodules)
if (!tree) if (!tree)
die(_("unable to parse commit %s"), oid_to_hex(&oid)); die(_("unable to parse commit %s"), oid_to_hex(&oid));
parse_tree(tree); parse_tree(tree);
init_tree_desc(&t, tree->buffer, tree->size); init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);
if (unpack_trees(1, &t, &opts) < 0) if (unpack_trees(1, &t, &opts) < 0)
die(_("unable to checkout working tree")); die(_("unable to checkout working tree"));

View file

@ -340,7 +340,7 @@ static void create_base_index(const struct commit *current_head)
if (!tree) if (!tree)
die(_("failed to unpack HEAD tree object")); die(_("failed to unpack HEAD tree object"));
parse_tree(tree); parse_tree(tree);
init_tree_desc(&t, tree->buffer, tree->size); init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);
if (unpack_trees(1, &t, &opts)) if (unpack_trees(1, &t, &opts))
exit(128); /* We've already reported the error, finish dying */ exit(128); /* We've already reported the error, finish dying */
} }

View file

@ -530,7 +530,7 @@ static int grep_submodule(struct grep_opt *opt,
strbuf_addstr(&base, filename); strbuf_addstr(&base, filename);
strbuf_addch(&base, '/'); strbuf_addch(&base, '/');
init_tree_desc(&tree, data, size); init_tree_desc(&tree, oid, data, size);
hit = grep_tree(&subopt, pathspec, &tree, &base, base.len, hit = grep_tree(&subopt, pathspec, &tree, &base, base.len,
object_type == OBJ_COMMIT); object_type == OBJ_COMMIT);
strbuf_release(&base); strbuf_release(&base);
@ -574,7 +574,7 @@ static int grep_cache(struct grep_opt *opt,
data = repo_read_object_file(the_repository, &ce->oid, data = repo_read_object_file(the_repository, &ce->oid,
&type, &size); &type, &size);
init_tree_desc(&tree, data, size); init_tree_desc(&tree, &ce->oid, data, size);
hit |= grep_tree(opt, pathspec, &tree, &name, 0, 0); hit |= grep_tree(opt, pathspec, &tree, &name, 0, 0);
strbuf_setlen(&name, name_base_len); strbuf_setlen(&name, name_base_len);
@ -670,7 +670,7 @@ static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
oid_to_hex(&entry.oid)); oid_to_hex(&entry.oid));
strbuf_addch(base, '/'); strbuf_addch(base, '/');
init_tree_desc(&sub, data, size); init_tree_desc(&sub, &entry.oid, data, size);
hit |= grep_tree(opt, pathspec, &sub, base, tn_len, hit |= grep_tree(opt, pathspec, &sub, base, tn_len,
check_attr); check_attr);
free(data); free(data);
@ -714,7 +714,7 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
strbuf_add(&base, name, len); strbuf_add(&base, name, len);
strbuf_addch(&base, ':'); strbuf_addch(&base, ':');
} }
init_tree_desc(&tree, data, size); init_tree_desc(&tree, &obj->oid, data, size);
hit = grep_tree(opt, pathspec, &tree, &base, base.len, hit = grep_tree(opt, pathspec, &tree, &base, base.len,
obj->type == OBJ_COMMIT); obj->type == OBJ_COMMIT);
strbuf_release(&base); strbuf_release(&base);

View file

@ -704,7 +704,8 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,
cache_tree_free(&the_index.cache_tree); cache_tree_free(&the_index.cache_tree);
for (i = 0; i < nr_trees; i++) { for (i = 0; i < nr_trees; i++) {
parse_tree(trees[i]); parse_tree(trees[i]);
init_tree_desc(t+i, trees[i]->buffer, trees[i]->size); init_tree_desc(t+i, &trees[i]->object.oid,
trees[i]->buffer, trees[i]->size);
} }
if (unpack_trees(nr_trees, t, &opts)) if (unpack_trees(nr_trees, t, &opts))
return -1; return -1;

View file

@ -1756,7 +1756,8 @@ static void add_pbase_object(struct tree_desc *tree,
tree = pbase_tree_get(&entry.oid); tree = pbase_tree_get(&entry.oid);
if (!tree) if (!tree)
return; return;
init_tree_desc(&sub, tree->tree_data, tree->tree_size); init_tree_desc(&sub, &tree->oid,
tree->tree_data, tree->tree_size);
add_pbase_object(&sub, down, downlen, fullname); add_pbase_object(&sub, down, downlen, fullname);
pbase_tree_put(tree); pbase_tree_put(tree);
@ -1816,7 +1817,8 @@ static void add_preferred_base_object(const char *name)
} }
else { else {
struct tree_desc tree; struct tree_desc tree;
init_tree_desc(&tree, it->pcache.tree_data, it->pcache.tree_size); init_tree_desc(&tree, &it->pcache.oid,
it->pcache.tree_data, it->pcache.tree_size);
add_pbase_object(&tree, name, cmplen, name); add_pbase_object(&tree, name, cmplen, name);
} }
} }

View file

@ -264,7 +264,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
for (i = 0; i < nr_trees; i++) { for (i = 0; i < nr_trees; i++) {
struct tree *tree = trees[i]; struct tree *tree = trees[i];
parse_tree(tree); parse_tree(tree);
init_tree_desc(t+i, tree->buffer, tree->size); init_tree_desc(t+i, &tree->object.oid, tree->buffer, tree->size);
} }
if (unpack_trees(nr_trees, t, &opts)) if (unpack_trees(nr_trees, t, &opts))
return 128; return 128;

View file

@ -285,7 +285,7 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)
if (parse_tree(tree)) if (parse_tree(tree))
return -1; return -1;
init_tree_desc(t, tree->buffer, tree->size); init_tree_desc(t, &tree->object.oid, tree->buffer, tree->size);
opts.head_idx = 1; opts.head_idx = 1;
opts.src_index = &the_index; opts.src_index = &the_index;
@ -871,7 +871,8 @@ static void diff_include_untracked(const struct stash_info *info, struct diff_op
tree[i] = parse_tree_indirect(oid[i]); tree[i] = parse_tree_indirect(oid[i]);
if (parse_tree(tree[i]) < 0) if (parse_tree(tree[i]) < 0)
die(_("failed to parse tree")); die(_("failed to parse tree"));
init_tree_desc(&tree_desc[i], tree[i]->buffer, tree[i]->size); init_tree_desc(&tree_desc[i], &tree[i]->object.oid,
tree[i]->buffer, tree[i]->size);
} }
unpack_tree_opt.head_idx = -1; unpack_tree_opt.head_idx = -1;

View file

@ -770,7 +770,7 @@ static void prime_cache_tree_rec(struct repository *r,
oidcpy(&it->oid, &tree->object.oid); oidcpy(&it->oid, &tree->object.oid);
init_tree_desc(&desc, tree->buffer, tree->size); init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
cnt = 0; cnt = 0;
while (tree_entry(&desc, &entry)) { while (tree_entry(&desc, &entry)) {
if (!S_ISDIR(entry.mode)) if (!S_ISDIR(entry.mode))

View file

@ -289,7 +289,7 @@ void resolve_tree_islands(struct repository *r,
if (!tree || parse_tree(tree) < 0) if (!tree || parse_tree(tree) < 0)
die(_("bad tree object %s"), oid_to_hex(&ent->idx.oid)); die(_("bad tree object %s"), oid_to_hex(&ent->idx.oid));
init_tree_desc(&desc, tree->buffer, tree->size); init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) { while (tree_entry(&desc, &entry)) {
struct object *obj; struct object *obj;

View file

@ -558,7 +558,7 @@ static int diff_cache(struct rev_info *revs,
opts.pathspec = &revs->diffopt.pathspec; opts.pathspec = &revs->diffopt.pathspec;
opts.pathspec->recursive = 1; opts.pathspec->recursive = 1;
init_tree_desc(&t, tree->buffer, tree->size); init_tree_desc(&t, &tree->object.oid, tree->buffer, tree->size);
return unpack_trees(1, &t, &opts); return unpack_trees(1, &t, &opts);
} }

6
fsck.c
View file

@ -313,7 +313,8 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
return -1; return -1;
name = fsck_get_object_name(options, &tree->object.oid); name = fsck_get_object_name(options, &tree->object.oid);
if (init_tree_desc_gently(&desc, tree->buffer, tree->size, 0)) if (init_tree_desc_gently(&desc, &tree->object.oid,
tree->buffer, tree->size, 0))
return -1; return -1;
while (tree_entry_gently(&desc, &entry)) { while (tree_entry_gently(&desc, &entry)) {
struct object *obj; struct object *obj;
@ -583,7 +584,8 @@ static int fsck_tree(const struct object_id *tree_oid,
const char *o_name; const char *o_name;
struct name_stack df_dup_candidates = { NULL }; struct name_stack df_dup_candidates = { NULL };
if (init_tree_desc_gently(&desc, buffer, size, TREE_DESC_RAW_MODES)) { if (init_tree_desc_gently(&desc, tree_oid, buffer, size,
TREE_DESC_RAW_MODES)) {
retval += report(options, tree_oid, OBJ_TREE, retval += report(options, tree_oid, OBJ_TREE,
FSCK_MSG_BAD_TREE, FSCK_MSG_BAD_TREE,
"cannot be parsed as a tree"); "cannot be parsed as a tree");

View file

@ -1308,7 +1308,7 @@ static struct object_list **process_tree(struct tree *tree,
obj->flags |= SEEN; obj->flags |= SEEN;
p = add_one_object(obj, p); p = add_one_object(obj, p);
init_tree_desc(&desc, tree->buffer, tree->size); init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) while (tree_entry(&desc, &entry))
switch (object_type(entry.mode)) { switch (object_type(entry.mode)) {

View file

@ -97,7 +97,7 @@ static void process_tree_contents(struct traversal_context *ctx,
enum interesting match = ctx->revs->diffopt.pathspec.nr == 0 ? enum interesting match = ctx->revs->diffopt.pathspec.nr == 0 ?
all_entries_interesting : entry_not_interesting; all_entries_interesting : entry_not_interesting;
init_tree_desc(&desc, tree->buffer, tree->size); init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) { while (tree_entry(&desc, &entry)) {
if (match != all_entries_interesting) { if (match != all_entries_interesting) {

View file

@ -63,7 +63,7 @@ static void *fill_tree_desc_strict(struct tree_desc *desc,
die("unable to read tree (%s)", oid_to_hex(hash)); die("unable to read tree (%s)", oid_to_hex(hash));
if (type != OBJ_TREE) if (type != OBJ_TREE)
die("%s is not a tree", oid_to_hex(hash)); die("%s is not a tree", oid_to_hex(hash));
init_tree_desc(desc, buffer, size); init_tree_desc(desc, hash, buffer, size);
return buffer; return buffer;
} }
@ -194,7 +194,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix,
buf = repo_read_object_file(the_repository, oid1, &type, &sz); buf = repo_read_object_file(the_repository, oid1, &type, &sz);
if (!buf) if (!buf)
die("cannot read tree %s", oid_to_hex(oid1)); die("cannot read tree %s", oid_to_hex(oid1));
init_tree_desc(&desc, buf, sz); init_tree_desc(&desc, oid1, buf, sz);
rewrite_here = NULL; rewrite_here = NULL;
while (desc.size) { while (desc.size) {

View file

@ -1679,9 +1679,10 @@ static int collect_merge_info(struct merge_options *opt,
parse_tree(merge_base); parse_tree(merge_base);
parse_tree(side1); parse_tree(side1);
parse_tree(side2); parse_tree(side2);
init_tree_desc(t + 0, merge_base->buffer, merge_base->size); init_tree_desc(t + 0, &merge_base->object.oid,
init_tree_desc(t + 1, side1->buffer, side1->size); merge_base->buffer, merge_base->size);
init_tree_desc(t + 2, side2->buffer, side2->size); init_tree_desc(t + 1, &side1->object.oid, side1->buffer, side1->size);
init_tree_desc(t + 2, &side2->object.oid, side2->buffer, side2->size);
trace2_region_enter("merge", "traverse_trees", opt->repo); trace2_region_enter("merge", "traverse_trees", opt->repo);
ret = traverse_trees(NULL, 3, t, &info); ret = traverse_trees(NULL, 3, t, &info);
@ -4400,9 +4401,9 @@ static int checkout(struct merge_options *opt,
unpack_opts.fn = twoway_merge; unpack_opts.fn = twoway_merge;
unpack_opts.preserve_ignored = 0; /* FIXME: !opts->overwrite_ignore */ unpack_opts.preserve_ignored = 0; /* FIXME: !opts->overwrite_ignore */
parse_tree(prev); parse_tree(prev);
init_tree_desc(&trees[0], prev->buffer, prev->size); init_tree_desc(&trees[0], &prev->object.oid, prev->buffer, prev->size);
parse_tree(next); parse_tree(next);
init_tree_desc(&trees[1], next->buffer, next->size); init_tree_desc(&trees[1], &next->object.oid, next->buffer, next->size);
ret = unpack_trees(2, trees, &unpack_opts); ret = unpack_trees(2, trees, &unpack_opts);
clear_unpack_trees_porcelain(&unpack_opts); clear_unpack_trees_porcelain(&unpack_opts);

View file

@ -411,7 +411,7 @@ static inline int merge_detect_rename(struct merge_options *opt)
static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree) static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree)
{ {
parse_tree(tree); parse_tree(tree);
init_tree_desc(desc, tree->buffer, tree->size); init_tree_desc(desc, &tree->object.oid, tree->buffer, tree->size);
} }
static int unpack_trees_start(struct merge_options *opt, static int unpack_trees_start(struct merge_options *opt,

View file

@ -81,7 +81,8 @@ int checkout_fast_forward(struct repository *r,
} }
for (i = 0; i < nr_trees; i++) { for (i = 0; i < nr_trees; i++) {
parse_tree(trees[i]); parse_tree(trees[i]);
init_tree_desc(t+i, trees[i]->buffer, trees[i]->size); init_tree_desc(t+i, &trees[i]->object.oid,
trees[i]->buffer, trees[i]->size);
} }
memset(&opts, 0, sizeof(opts)); memset(&opts, 0, sizeof(opts));

View file

@ -366,7 +366,7 @@ static int fill_bitmap_tree(struct bitmap *bitmap,
if (parse_tree(tree) < 0) if (parse_tree(tree) < 0)
die("unable to load tree object %s", die("unable to load tree object %s",
oid_to_hex(&tree->object.oid)); oid_to_hex(&tree->object.oid));
init_tree_desc(&desc, tree->buffer, tree->size); init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) { while (tree_entry(&desc, &entry)) {
switch (object_type(entry.mode)) { switch (object_type(entry.mode)) {

View file

@ -2250,7 +2250,8 @@ static int add_promisor_object(const struct object_id *oid,
struct tree *tree = (struct tree *)obj; struct tree *tree = (struct tree *)obj;
struct tree_desc desc; struct tree_desc desc;
struct name_entry entry; struct name_entry entry;
if (init_tree_desc_gently(&desc, tree->buffer, tree->size, 0)) if (init_tree_desc_gently(&desc, &tree->object.oid,
tree->buffer, tree->size, 0))
/* /*
* Error messages are given when packs are * Error messages are given when packs are
* verified, so do not print any here. * verified, so do not print any here.

View file

@ -40,7 +40,7 @@ static int tree_is_complete(const struct object_id *oid)
tree->buffer = data; tree->buffer = data;
tree->size = size; tree->size = size;
} }
init_tree_desc(&desc, tree->buffer, tree->size); init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
complete = 1; complete = 1;
while (tree_entry(&desc, &entry)) { while (tree_entry(&desc, &entry)) {
if (!repo_has_object_file(the_repository, &entry.oid) || if (!repo_has_object_file(the_repository, &entry.oid) ||

View file

@ -82,7 +82,7 @@ static void mark_tree_contents_uninteresting(struct repository *r,
if (parse_tree_gently(tree, 1) < 0) if (parse_tree_gently(tree, 1) < 0)
return; return;
init_tree_desc(&desc, tree->buffer, tree->size); init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) { while (tree_entry(&desc, &entry)) {
switch (object_type(entry.mode)) { switch (object_type(entry.mode)) {
case OBJ_TREE: case OBJ_TREE:
@ -189,7 +189,7 @@ static void add_children_by_path(struct repository *r,
if (parse_tree_gently(tree, 1) < 0) if (parse_tree_gently(tree, 1) < 0)
return; return;
init_tree_desc(&desc, tree->buffer, tree->size); init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) { while (tree_entry(&desc, &entry)) {
switch (object_type(entry.mode)) { switch (object_type(entry.mode)) {
case OBJ_TREE: case OBJ_TREE:

View file

@ -15,7 +15,7 @@ static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned l
const char *path; const char *path;
unsigned int len; unsigned int len;
uint16_t mode; uint16_t mode;
const unsigned hashsz = the_hash_algo->rawsz; const unsigned hashsz = desc->algo->rawsz;
if (size < hashsz + 3 || buf[size - (hashsz + 1)]) { if (size < hashsz + 3 || buf[size - (hashsz + 1)]) {
strbuf_addstr(err, _("too-short tree object")); strbuf_addstr(err, _("too-short tree object"));
@ -37,15 +37,19 @@ static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned l
desc->entry.path = path; desc->entry.path = path;
desc->entry.mode = (desc->flags & TREE_DESC_RAW_MODES) ? mode : canon_mode(mode); desc->entry.mode = (desc->flags & TREE_DESC_RAW_MODES) ? mode : canon_mode(mode);
desc->entry.pathlen = len - 1; desc->entry.pathlen = len - 1;
oidread(&desc->entry.oid, (const unsigned char *)path + len); oidread_algop(&desc->entry.oid, (const unsigned char *)path + len,
desc->algo);
return 0; return 0;
} }
static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer, static int init_tree_desc_internal(struct tree_desc *desc,
unsigned long size, struct strbuf *err, const struct object_id *oid,
const void *buffer, unsigned long size,
struct strbuf *err,
enum tree_desc_flags flags) enum tree_desc_flags flags)
{ {
desc->algo = (oid && oid->algo) ? &hash_algos[oid->algo] : the_hash_algo;
desc->buffer = buffer; desc->buffer = buffer;
desc->size = size; desc->size = size;
desc->flags = flags; desc->flags = flags;
@ -54,19 +58,21 @@ static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer,
return 0; return 0;
} }
void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size) void init_tree_desc(struct tree_desc *desc, const struct object_id *tree_oid,
const void *buffer, unsigned long size)
{ {
struct strbuf err = STRBUF_INIT; struct strbuf err = STRBUF_INIT;
if (init_tree_desc_internal(desc, buffer, size, &err, 0)) if (init_tree_desc_internal(desc, tree_oid, buffer, size, &err, 0))
die("%s", err.buf); die("%s", err.buf);
strbuf_release(&err); strbuf_release(&err);
} }
int init_tree_desc_gently(struct tree_desc *desc, const void *buffer, unsigned long size, int init_tree_desc_gently(struct tree_desc *desc, const struct object_id *oid,
const void *buffer, unsigned long size,
enum tree_desc_flags flags) enum tree_desc_flags flags)
{ {
struct strbuf err = STRBUF_INIT; struct strbuf err = STRBUF_INIT;
int result = init_tree_desc_internal(desc, buffer, size, &err, flags); int result = init_tree_desc_internal(desc, oid, buffer, size, &err, flags);
if (result) if (result)
error("%s", err.buf); error("%s", err.buf);
strbuf_release(&err); strbuf_release(&err);
@ -85,7 +91,7 @@ void *fill_tree_descriptor(struct repository *r,
if (!buf) if (!buf)
die("unable to read tree %s", oid_to_hex(oid)); die("unable to read tree %s", oid_to_hex(oid));
} }
init_tree_desc(desc, buf, size); init_tree_desc(desc, oid, buf, size);
return buf; return buf;
} }
@ -102,7 +108,7 @@ static void entry_extract(struct tree_desc *t, struct name_entry *a)
static int update_tree_entry_internal(struct tree_desc *desc, struct strbuf *err) static int update_tree_entry_internal(struct tree_desc *desc, struct strbuf *err)
{ {
const void *buf = desc->buffer; const void *buf = desc->buffer;
const unsigned char *end = (const unsigned char *)desc->entry.path + desc->entry.pathlen + 1 + the_hash_algo->rawsz; const unsigned char *end = (const unsigned char *)desc->entry.path + desc->entry.pathlen + 1 + desc->algo->rawsz;
unsigned long size = desc->size; unsigned long size = desc->size;
unsigned long len = end - (const unsigned char *)buf; unsigned long len = end - (const unsigned char *)buf;
@ -611,7 +617,7 @@ int get_tree_entry(struct repository *r,
retval = -1; retval = -1;
} else { } else {
struct tree_desc t; struct tree_desc t;
init_tree_desc(&t, tree, size); init_tree_desc(&t, tree_oid, tree, size);
retval = find_tree_entry(r, &t, name, oid, mode); retval = find_tree_entry(r, &t, name, oid, mode);
} }
free(tree); free(tree);
@ -654,7 +660,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r,
struct tree_desc t; struct tree_desc t;
int follows_remaining = GET_TREE_ENTRY_FOLLOW_SYMLINKS_MAX_LINKS; int follows_remaining = GET_TREE_ENTRY_FOLLOW_SYMLINKS_MAX_LINKS;
init_tree_desc(&t, NULL, 0UL); init_tree_desc(&t, NULL, NULL, 0UL);
strbuf_addstr(&namebuf, name); strbuf_addstr(&namebuf, name);
oidcpy(&current_tree_oid, tree_oid); oidcpy(&current_tree_oid, tree_oid);
@ -690,7 +696,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r,
goto done; goto done;
/* descend */ /* descend */
init_tree_desc(&t, tree, size); init_tree_desc(&t, &current_tree_oid, tree, size);
} }
/* Handle symlinks to e.g. a//b by removing leading slashes */ /* Handle symlinks to e.g. a//b by removing leading slashes */
@ -724,7 +730,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r,
free(parent->tree); free(parent->tree);
parents_nr--; parents_nr--;
parent = &parents[parents_nr - 1]; parent = &parents[parents_nr - 1];
init_tree_desc(&t, parent->tree, parent->size); init_tree_desc(&t, &parent->oid, parent->tree, parent->size);
strbuf_remove(&namebuf, 0, remainder ? 3 : 2); strbuf_remove(&namebuf, 0, remainder ? 3 : 2);
continue; continue;
} }
@ -804,7 +810,7 @@ enum get_oid_result get_tree_entry_follow_symlinks(struct repository *r,
contents_start = contents; contents_start = contents;
parent = &parents[parents_nr - 1]; parent = &parents[parents_nr - 1];
init_tree_desc(&t, parent->tree, parent->size); init_tree_desc(&t, &parent->oid, parent->tree, parent->size);
strbuf_splice(&namebuf, 0, len, strbuf_splice(&namebuf, 0, len,
contents_start, link_len); contents_start, link_len);
if (remainder) if (remainder)

View file

@ -26,6 +26,7 @@ struct name_entry {
* A semi-opaque data structure used to maintain the current state of the walk. * A semi-opaque data structure used to maintain the current state of the walk.
*/ */
struct tree_desc { struct tree_desc {
const struct git_hash_algo *algo;
/* /*
* pointer into the memory representation of the tree. It always * pointer into the memory representation of the tree. It always
* points at the current entry being visited. * points at the current entry being visited.
@ -85,9 +86,11 @@ int update_tree_entry_gently(struct tree_desc *);
* size parameters are assumed to be the same as the buffer and size * size parameters are assumed to be the same as the buffer and size
* members of `struct tree`. * members of `struct tree`.
*/ */
void init_tree_desc(struct tree_desc *desc, const void *buf, unsigned long size); void init_tree_desc(struct tree_desc *desc, const struct object_id *tree_oid,
const void *buf, unsigned long size);
int init_tree_desc_gently(struct tree_desc *desc, const void *buf, unsigned long size, int init_tree_desc_gently(struct tree_desc *desc, const struct object_id *oid,
const void *buf, unsigned long size,
enum tree_desc_flags flags); enum tree_desc_flags flags);
/* /*

2
tree.c
View file

@ -27,7 +27,7 @@ int read_tree_at(struct repository *r,
if (parse_tree(tree)) if (parse_tree(tree))
return -1; return -1;
init_tree_desc(&desc, tree->buffer, tree->size); init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) { while (tree_entry(&desc, &entry)) {
if (retval != all_entries_interesting) { if (retval != all_entries_interesting) {

View file

@ -45,7 +45,7 @@ static int process_tree(struct walker *walker, struct tree *tree)
if (parse_tree(tree)) if (parse_tree(tree))
return -1; return -1;
init_tree_desc(&desc, tree->buffer, tree->size); init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) { while (tree_entry(&desc, &entry)) {
struct object *obj = NULL; struct object *obj = NULL;