From ebad02be2211aa19692c388284253cbc5882eed0 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 7 Oct 2024 18:33:51 +0200 Subject: [PATCH] path-walk API: avoid adding a root tree more than once When adding tree objects, we are very careful to avoid adding the same tree object more than once. There was one small gap in that logic, though: when adding a root tree object. Two refs can easily share the same root tree object, and we should still not add it more than once. Signed-off-by: Johannes Schindelin --- path-walk.c | 12 +++++++++--- t/t6601-path-walk.sh | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/path-walk.c b/path-walk.c index aaa2cce7471941..dd1acb29d92b45 100644 --- a/path-walk.c +++ b/path-walk.c @@ -278,9 +278,11 @@ int walk_objects_by_path(struct path_walk_info *info) struct object_array_entry *pending = info->revs->pending.objects + i; struct object *obj = pending->item; - if (obj->type == OBJ_COMMIT) + if (obj->type == OBJ_COMMIT || obj->flags & SEEN) continue; + obj->flags |= SEEN; + while (obj->type == OBJ_TAG) { struct tag *tag = lookup_tag(info->revs->repo, &obj->oid); @@ -341,8 +343,12 @@ int walk_objects_by_path(struct path_walk_info *info) t = lookup_tree(info->revs->repo, oid); if (t) { - oidset_insert(&root_tree_set, oid); - oid_array_append(&root_tree_list->oids, oid); + if (t->object.flags & SEEN) + continue; + t->object.flags |= SEEN; + + if (!oidset_insert(&root_tree_set, oid)) + oid_array_append(&root_tree_list->oids, oid); } else { warning("could not find tree %s", oid_to_hex(oid)); } diff --git a/t/t6601-path-walk.sh b/t/t6601-path-walk.sh index 26498cab24890d..943adc6c8f132f 100755 --- a/t/t6601-path-walk.sh +++ b/t/t6601-path-walk.sh @@ -276,4 +276,26 @@ test_expect_success 'topic, not base, boundary with pruning' ' test_cmp expect.sorted out.sorted ' +test_expect_success 'trees are reported exactly once' ' + test_when_finished "rm -rf unique-trees" && + test_create_repo unique-trees && + ( + cd unique-trees && + mkdir initial && + test_commit initial/file && + + git switch -c move-to-top && + git mv initial/file.t ./ && + test_tick && + git commit -m moved && + + git update-ref refs/heads/other HEAD + ) && + + test-tool -C unique-trees path-walk -- --all >out && + tree=$(git -C unique-trees rev-parse HEAD:) && + grep "$tree" out >out-filtered && + test_line_count = 1 out-filtered +' + test_done