setup: detangle loading of loose object maps

When a repository is configured to use a compatibility hash function then we load the loose object map when we initialize the repository. This object map provides the mappings between the canonical object hash and the compatibility object hash. Loading the object map happens in `repo_set_compat_hash_algo()`, which calls `repo_read_loose_object_map()` in case the compatibility object hash is non-zero. This setup sequence has two major downsides: - We assume that the primary object database is the "files" object database so that we can extract its "loose" backend. This stops working with pluggable object databases. - We require the object database to already have been initialized when configuring the object database. This means that we must intermix configuration of the repository and initialization of its sub-structures in a weird way. Refactor the logic so that we instead load the loose object map via the "loose" backend, which fixes both of the above issues. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jul 24, 2026 at 05:48 UTC 109e40dfcb18c4555aecb6c41a650d114a3bec7b
5 files changed +11 -10
loose.c
+5 -6
@@ -61,7 +61,7 @@ static int insert_loose_map(struct odb_source_loose *loose,
61 return inserted;
62 }
63
64 -static int load_one_loose_object_map(struct odb_source_loose *loose)
64 +int loose_object_map_load(struct odb_source_loose *loose)
65 {
66 struct repository *repo = loose->base.odb->repo;
67 struct strbuf buf = STRBUF_INIT;
@@ -69,6 +69,9 @@ static int load_one_loose_object_map(struct odb_source_loose *loose)
69 FILE *fp;
70 int ret = -1;
71
72 + if (!should_use_loose_object_map(repo))
73 + return 0;
74 +
75 if (!loose->map)
76 loose_object_map_init(&loose->map);
77 if (!loose->cache) {
@@ -112,14 +115,10 @@ int repo_read_loose_object_map(struct repository *repo)
115 {
116 struct odb_source *source;
117
115 - if (!should_use_loose_object_map(repo))
116 - return 0;
117 -
118 odb_prepare_alternates(repo->objects);
119 -
119 for (source = repo->objects->sources; source; source = source->next) {
120 struct odb_source_files *files = odb_source_files_downcast(source);
122 - if (load_one_loose_object_map(files->loose) < 0)
121 + if (loose_object_map_load(files->loose) < 0)
122 return -1;
123 }
124
loose.h
+1
@@ -13,6 +13,7 @@ struct loose_object_map {
13
14 void loose_object_map_init(struct loose_object_map **map);
15 void loose_object_map_clear(struct loose_object_map **map);
16 +int loose_object_map_load(struct odb_source_loose *loose);
17 int repo_loose_object_map_oid(struct repository *repo,
18 const struct object_id *src,
19 const struct git_hash_algo *dest_algo,
odb/source-loose.c
+2
@@ -727,5 +727,7 @@ struct odb_source_loose *odb_source_loose_new(struct object_database *odb,
727 if (!is_absolute_path(loose->base.path))
728 chdir_notify_register(NULL, odb_source_loose_reparent, loose);
729
730 + loose_object_map_load(loose);
731 +
732 return loose;
733 }
repository.c
-2
@@ -201,8 +201,6 @@ void repo_set_compat_hash_algo(struct repository *repo MAYBE_UNUSED, uint32_t al
201 if (hash_algo_by_ptr(repo->hash_algo) == algo)
202 BUG("hash_algo and compat_hash_algo match");
203 repo->compat_hash_algo = algo ? &hash_algos[algo] : NULL;
204 - if (repo->compat_hash_algo)
205 - repo_read_loose_object_map(repo);
204 #else
205 if (algo)
206 die(_("compatibility hash algorithm support requires Rust"));
setup.c
+3 -2
@@ -1788,8 +1788,6 @@ int apply_repository_format(struct repository *repo,
1788
1789 repo->bare_cfg = format->is_bare;
1790 repo_set_hash_algo(repo, format->hash_algo);
1791 - repo->objects = odb_new(repo, object_directory,
1792 - alternate_object_directories);
1791 repo_set_compat_hash_algo(repo, format->compat_hash_algo);
1792 repo_set_ref_storage_format(repo,
1793 format->ref_storage_format,
@@ -1805,6 +1803,9 @@ int apply_repository_format(struct repository *repo,
1803 repo->repository_format_precious_objects =
1804 format->precious_objects;
1805
1806 + repo->objects = odb_new(repo, object_directory,
1807 + alternate_object_directories);
1808 +
1809 free(alternate_object_directories);
1810 free(object_directory);
1811 return 0;