pack-bitmap: iterate object sources when opening bitmaps

When opening a bitmap for a repository we perform two steps: - We first look for a multi-pack index bitmap in any of the object sources connected to the repository. - We then look for a packfile bitmap in any of the packfiles of any of the object sources. Both of these steps thus iterate through object sources themselves, one via `odb_prepare_alternates()` and one via `repo_for_each_pack()`. This layout makes it hard to introduce a way to open the bitmap of one specific object source, which is functionality that we'll require in a subsequent commit. Reverse the loop so that we instead loop through all sources in the outer loop, and then for each source we try to load its bitmap via either the multi-pack index or via a packfile. Note that this changes the precedence of bitmaps in one specific edge case: when an earlier object source only has a packfile bitmap, but a later source has a multi-pack index bitmap, we now pick the packfile bitmap of the earlier source. Previously, a multi-pack index bitmap from any source would have taken precedence over all packfile bitmaps. Given that object sources are ordered such that the local source comes first, this arguably is an improvement, as we now prefer local bitmaps over bitmaps in alternates. Furthermore, we already warn about repositories that have multiple bitmaps, so this setup is broken and thus arguably not worth worrying about too much. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jul 15, 2026 at 08:22 UTC eaa9807c970254e503cdb2d719d873521de4ed05
1 file changed +31 -38
pack-bitmap.c
+31 -38
@@ -680,60 +680,53 @@ static int load_bitmap(struct repository *r, struct bitmap_index *bitmap_git,
680 return 0;
681 }
682
683 -static int open_pack_bitmap(struct repository *r,
684 - struct bitmap_index *bitmap_git)
683 +static int open_bitmap_for_source(struct odb_source_packed *source,
684 + struct bitmap_index *bitmap_git)
685 {
686 - struct packed_git *p;
687 - int ret = -1;
686 + struct multi_pack_index *midx = get_multi_pack_index(source);
687 + struct packfile_list_entry *e;
688 + bool found = false;
689
689 - repo_for_each_pack(r, p) {
690 - if (open_pack_bitmap_1(bitmap_git, p) == 0) {
691 - ret = 0;
692 - /*
693 - * The only reason to keep looking is to report
694 - * duplicates.
695 - */
696 - if (!trace2_is_enabled())
697 - break;
698 - }
690 + if (midx && !open_midx_bitmap_1(bitmap_git, midx))
691 + found = true;
692 +
693 + for (e = packfile_store_get_packs(source); e; e = e->next) {
694 + /*
695 + * When tracing is enabled we want to keep looking to report
696 + * duplicates even if we have already found a bitmap.
697 + */
698 + if (found && !trace2_is_enabled())
699 + break;
700 +
701 + if (!open_pack_bitmap_1(bitmap_git, e->pack))
702 + found = true;
703 }
704
701 - return ret;
705 + return found ? 0 : -1;
706 }
707
704 -static int open_midx_bitmap(struct repository *r,
705 - struct bitmap_index *bitmap_git)
708 +static int open_bitmap(struct repository *r,
709 + struct bitmap_index *bitmap_git)
710 {
711 struct odb_source *source;
708 - int ret = -1;
712 + bool found = false;
713
714 assert(!bitmap_git->map);
715
716 odb_prepare_alternates(r->objects);
717 for (source = r->objects->sources; source; source = source->next) {
718 struct odb_source_files *files = odb_source_files_downcast(source);
715 - struct multi_pack_index *midx = get_multi_pack_index(files->packed);
716 - if (midx && !open_midx_bitmap_1(bitmap_git, midx))
717 - ret = 0;
718 - }
719 - return ret;
720 -}
721 -
722 -static int open_bitmap(struct repository *r,
723 - struct bitmap_index *bitmap_git)
724 -{
725 - int found;
719
727 - assert(!bitmap_git->map);
720 + if (!open_bitmap_for_source(files->packed, bitmap_git))
721 + found = true;
722
729 - found = !open_midx_bitmap(r, bitmap_git);
730 -
731 - /*
732 - * these will all be skipped if we opened a midx bitmap; but run it
733 - * anyway if tracing is enabled to report the duplicates
734 - */
735 - if (!found || trace2_is_enabled())
736 - found |= !open_pack_bitmap(r, bitmap_git);
723 + /*
724 + * The only reason to keep looking after having found a bitmap
725 + * is to report duplicates.
726 + */
727 + if (found && !trace2_is_enabled())
728 + break;
729 + }
730
731 return found ? 0 : -1;
732 }