From 930a3aaa917af92918b447a9ee117c0e2b26b36e 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 1dc0d0cf55e605..56655211225fd7 100644 --- a/path-walk.c +++ b/path-walk.c @@ -296,9 +296,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); @@ -358,9 +360,13 @@ int walk_objects_by_path(struct path_walk_info *info) oid = get_commit_tree_oid(c); t = lookup_tree(info->revs->repo, oid); + if (t->object.flags & SEEN) + continue; + t->object.flags |= SEEN; + if (t) { - oidset_insert(&root_tree_set, oid); - oid_array_append(&root_tree_list->oids, oid); + 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 84d3a71cc67e12..312bf3c19c176a 100755 --- a/t/t6601-path-walk.sh +++ b/t/t6601-path-walk.sh @@ -311,4 +311,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