loose: refactor object map to operate on `struct odb_source_loose`

While the loose object map functions in "loose.c" accept a generic `struct odb_source *`, they always expect this to be the "files" backend. Furthermore, the subsystem doesn't even care about the "files" backend, but only uses it as a stepping stone to get to the "loose" backend. This assumption is implicit and thus not immediately obvious. Refactor the interfaces to instead operate on a `struct odb_source_loose` instead, which eliminates the implicit dependency and unnecessary detour via the "files" source. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jun 1, 2026 at 10:20 UTC 87588db131a5c1c33471606860951c9959bbe6ae
3 files changed +30 -28
loose.c
+22 -23
@@ -46,38 +46,36 @@ static int insert_oid_pair(kh_oid_map_t *map, const struct object_id *key, const
46 return 1;
47 }
48
49 -static int insert_loose_map(struct odb_source *source,
49 +static int insert_loose_map(struct odb_source_loose *loose,
50 const struct object_id *oid,
51 const struct object_id *compat_oid)
52 {
53 - struct odb_source_files *files = odb_source_files_downcast(source);
54 - struct loose_object_map *map = files->loose->map;
53 + struct loose_object_map *map = loose->map;
54 int inserted = 0;
55
56 inserted |= insert_oid_pair(map->to_compat, oid, compat_oid);
57 inserted |= insert_oid_pair(map->to_storage, compat_oid, oid);
58 if (inserted)
60 - oidtree_insert(files->loose->cache, compat_oid, NULL);
59 + oidtree_insert(loose->cache, compat_oid, NULL);
60
61 return inserted;
62 }
63
65 -static int load_one_loose_object_map(struct repository *repo, struct odb_source *source)
64 +static int load_one_loose_object_map(struct repository *repo, struct odb_source_loose *loose)
65 {
67 - struct odb_source_files *files = odb_source_files_downcast(source);
66 struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
67 FILE *fp;
68
71 - if (!files->loose->map)
72 - loose_object_map_init(&files->loose->map);
73 - if (!files->loose->cache) {
74 - ALLOC_ARRAY(files->loose->cache, 1);
75 - oidtree_init(files->loose->cache);
69 + if (!loose->map)
70 + loose_object_map_init(&loose->map);
71 + if (!loose->cache) {
72 + ALLOC_ARRAY(loose->cache, 1);
73 + oidtree_init(loose->cache);
74 }
75
78 - insert_loose_map(source, repo->hash_algo->empty_tree, repo->compat_hash_algo->empty_tree);
79 - insert_loose_map(source, repo->hash_algo->empty_blob, repo->compat_hash_algo->empty_blob);
80 - insert_loose_map(source, repo->hash_algo->null_oid, repo->compat_hash_algo->null_oid);
76 + insert_loose_map(loose, repo->hash_algo->empty_tree, repo->compat_hash_algo->empty_tree);
77 + insert_loose_map(loose, repo->hash_algo->empty_blob, repo->compat_hash_algo->empty_blob);
78 + insert_loose_map(loose, repo->hash_algo->null_oid, repo->compat_hash_algo->null_oid);
79
80 repo_common_path_replace(repo, &path, "objects/loose-object-idx");
81 fp = fopen(path.buf, "rb");
@@ -97,7 +95,7 @@ static int load_one_loose_object_map(struct repository *repo, struct odb_source
95 parse_oid_hex_algop(p, &compat_oid, &p, repo->compat_hash_algo) ||
96 p != buf.buf + buf.len)
97 goto err;
100 - insert_loose_map(source, &oid, &compat_oid);
98 + insert_loose_map(loose, &oid, &compat_oid);
99 }
100
101 strbuf_release(&buf);
@@ -119,7 +117,8 @@ int repo_read_loose_object_map(struct repository *repo)
117 odb_prepare_alternates(repo->objects);
118
119 for (source = repo->objects->sources; source; source = source->next) {
122 - if (load_one_loose_object_map(repo, source) < 0) {
120 + struct odb_source_files *files = odb_source_files_downcast(source);
121 + if (load_one_loose_object_map(repo, files->loose) < 0) {
122 return -1;
123 }
124 }
@@ -171,7 +170,7 @@ errout:
170 return -1;
171 }
172
174 -static int write_one_object(struct odb_source *source,
173 +static int write_one_object(struct odb_source_loose *loose,
174 const struct object_id *oid,
175 const struct object_id *compat_oid)
176 {
@@ -180,7 +179,7 @@ static int write_one_object(struct odb_source *source,
179 struct stat st;
180 struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
181
183 - strbuf_addf(&path, "%s/loose-object-idx", source->path);
182 + strbuf_addf(&path, "%s/loose-object-idx", loose->base.path);
183 hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1);
184
185 fd = open(path.buf, O_WRONLY | O_CREAT | O_APPEND, 0666);
@@ -196,7 +195,7 @@ static int write_one_object(struct odb_source *source,
195 goto errout;
196 if (close(fd))
197 goto errout;
199 - adjust_shared_perm(source->odb->repo, path.buf);
198 + adjust_shared_perm(loose->base.odb->repo, path.buf);
199 rollback_lock_file(&lock);
200 strbuf_release(&buf);
201 strbuf_release(&path);
@@ -210,18 +209,18 @@ errout:
209 return -1;
210 }
211
213 -int repo_add_loose_object_map(struct odb_source *source,
212 +int repo_add_loose_object_map(struct odb_source_loose *loose,
213 const struct object_id *oid,
214 const struct object_id *compat_oid)
215 {
216 int inserted = 0;
217
219 - if (!should_use_loose_object_map(source->odb->repo))
218 + if (!should_use_loose_object_map(loose->base.odb->repo))
219 return 0;
220
222 - inserted = insert_loose_map(source, oid, compat_oid);
221 + inserted = insert_loose_map(loose, oid, compat_oid);
222 if (inserted)
224 - return write_one_object(source, oid, compat_oid);
223 + return write_one_object(loose, oid, compat_oid);
224 return 0;
225 }
226
loose.h
+2 -2
@@ -4,7 +4,7 @@
4 #include "khash.h"
5
6 struct repository;
7 -struct odb_source;
7 +struct odb_source_loose;
8
9 struct loose_object_map {
10 kh_oid_map_t *to_compat;
@@ -17,7 +17,7 @@ int repo_loose_object_map_oid(struct repository *repo,
17 const struct object_id *src,
18 const struct git_hash_algo *dest_algo,
19 struct object_id *dest);
20 -int repo_add_loose_object_map(struct odb_source *source,
20 +int repo_add_loose_object_map(struct odb_source_loose *loose,
21 const struct object_id *oid,
22 const struct object_id *compat_oid);
23 int repo_read_loose_object_map(struct repository *repo);
object-file.c
+6 -3
@@ -810,6 +810,7 @@ int odb_source_loose_write_stream(struct odb_source *source,
810 struct odb_write_stream *in_stream, size_t len,
811 struct object_id *oid)
812 {
813 + struct odb_source_files *files = odb_source_files_downcast(source);
814 const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
815 struct object_id compat_oid;
816 int fd, ret, err = 0, flush = 0;
@@ -918,7 +919,7 @@ int odb_source_loose_write_stream(struct odb_source *source,
919 err = finalize_object_file_flags(source->odb->repo, tmp_file.buf, filename.buf,
920 FOF_SKIP_COLLISION_CHECK);
921 if (!err && compat)
921 - err = repo_add_loose_object_map(source, oid, &compat_oid);
922 + err = repo_add_loose_object_map(files->loose, oid, &compat_oid);
923 cleanup:
924 strbuf_release(&tmp_file);
925 strbuf_release(&filename);
@@ -931,6 +932,7 @@ int odb_source_loose_write_object(struct odb_source *source,
932 struct object_id *compat_oid_in,
933 enum odb_write_object_flags flags)
934 {
935 + struct odb_source_files *files = odb_source_files_downcast(source);
936 const struct git_hash_algo *algo = source->odb->repo->hash_algo;
937 const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
938 struct object_id compat_oid;
@@ -962,13 +964,14 @@ int odb_source_loose_write_object(struct odb_source *source,
964 if (write_loose_object(source, oid, hdr, hdrlen, buf, len, 0, flags))
965 return -1;
966 if (compat)
965 - return repo_add_loose_object_map(source, oid, &compat_oid);
967 + return repo_add_loose_object_map(files->loose, oid, &compat_oid);
968 return 0;
969 }
970
971 int force_object_loose(struct odb_source *source,
972 const struct object_id *oid, time_t mtime)
973 {
974 + struct odb_source_files *files = odb_source_files_downcast(source);
975 const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
976 void *buf;
977 unsigned long len;
@@ -998,7 +1001,7 @@ int force_object_loose(struct odb_source *source,
1001 hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
1002 ret = write_loose_object(source, oid, hdr, hdrlen, buf, len, mtime, 0);
1003 if (!ret && compat)
1001 - ret = repo_add_loose_object_map(source, oid, &compat_oid);
1004 + ret = repo_add_loose_object_map(files->loose, oid, &compat_oid);
1005 free(buf);
1006
1007 return ret;