odb: embed base source in the "files" backend

The "files" backend is implemented as a pointer in the `struct odb_source`. This contradicts our typical pattern for pluggable backends like we use it for example in the ref store or for object database streams, where we typically embed the generic base structure in the specialized implementation. This pattern has a couple of small benefits: - We avoid an extra allocation. - We hide implementation details in the generic structure. - We can easily downcast from a generic backend to the specialized structure and vice versa because the offsets are known at compile time. - It becomes trivial to identify locations where we depend on backend specific logic because the cast needs to be explicit. Refactor our "files" object database source to do the same and embed the `struct odb_source` in the `struct odb_source_files`. There are still a bunch of sites in our code base where we do have to access internals of the "files" backend. The intent is that those will go away over time, but this will certainly take a while. Meanwhile, provide a `odb_source_files_downcast()` function that can convert a generic source into a "files" source. As we only have a single source the downcast succeeds unconditionally for now. Eventually though the intent is to make the cast `BUG()` in case the caller requests to downcast a non-"files" backend to a "files" backend. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Mar 5, 2026 at 15:19 UTC d9ecf268ef3f69130fa269012318470d908978f6
18 files changed +189 -89
builtin/cat-file.c
+2 -1
@@ -882,7 +882,8 @@ static void batch_each_object(struct batch_options *opt,
882 struct object_info oi = { 0 };
883
884 for (source = the_repository->objects->sources; source; source = source->next) {
885 - int ret = packfile_store_for_each_object(source->files->packed, &oi,
885 + struct odb_source_files *files = odb_source_files_downcast(source);
886 + int ret = packfile_store_for_each_object(files->packed, &oi,
887 batch_one_object_oi, &payload, flags);
888 if (ret)
889 break;
builtin/fast-import.c
+8 -4
@@ -875,6 +875,7 @@ static void end_packfile(void)
875 running = 1;
876 clear_delta_base_cache();
877 if (object_count) {
878 + struct odb_source_files *files = odb_source_files_downcast(pack_data->repo->objects->sources);
879 struct packed_git *new_p;
880 struct object_id cur_pack_oid;
881 char *idx_name;
@@ -900,8 +901,7 @@ static void end_packfile(void)
901 idx_name = keep_pack(create_index());
902
903 /* Register the packfile with core git's machinery. */
903 - new_p = packfile_store_load_pack(pack_data->repo->objects->sources->files->packed,
904 - idx_name, 1);
904 + new_p = packfile_store_load_pack(files->packed, idx_name, 1);
905 if (!new_p)
906 die(_("core Git rejected index %s"), idx_name);
907 all_packs[pack_id] = new_p;
@@ -982,7 +982,9 @@ static int store_object(
982 }
983
984 for (source = the_repository->objects->sources; source; source = source->next) {
985 - if (!packfile_list_find_oid(packfile_store_get_packs(source->files->packed), &oid))
985 + struct odb_source_files *files = odb_source_files_downcast(source);
986 +
987 + if (!packfile_list_find_oid(packfile_store_get_packs(files->packed), &oid))
988 continue;
989 e->type = type;
990 e->pack_id = MAX_PACK_ID;
@@ -1187,7 +1189,9 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
1189 }
1190
1191 for (source = the_repository->objects->sources; source; source = source->next) {
1190 - if (!packfile_list_find_oid(packfile_store_get_packs(source->files->packed), &oid))
1192 + struct odb_source_files *files = odb_source_files_downcast(source);
1193 +
1194 + if (!packfile_list_find_oid(packfile_store_get_packs(files->packed), &oid))
1195 continue;
1196 e->type = OBJ_BLOB;
1197 e->pack_id = MAX_PACK_ID;
builtin/grep.c
+4 -2
@@ -1218,8 +1218,10 @@ int cmd_grep(int argc,
1218 struct odb_source *source;
1219
1220 odb_prepare_alternates(the_repository->objects);
1221 - for (source = the_repository->objects->sources; source; source = source->next)
1222 - packfile_store_prepare(source->files->packed);
1221 + for (source = the_repository->objects->sources; source; source = source->next) {
1222 + struct odb_source_files *files = odb_source_files_downcast(source);
1223 + packfile_store_prepare(files->packed);
1224 + }
1225 }
1226
1227 start_threads(&opt);
builtin/index-pack.c
+5 -3
@@ -1637,9 +1637,11 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
1637 rename_tmp_packfile(&final_index_name, curr_index_name, &index_name,
1638 hash, "idx", 1);
1639
1640 - if (do_fsck_object && startup_info->have_repository)
1641 - packfile_store_load_pack(the_repository->objects->sources->files->packed,
1642 - final_index_name, 0);
1640 + if (do_fsck_object && startup_info->have_repository) {
1641 + struct odb_source_files *files =
1642 + odb_source_files_downcast(the_repository->objects->sources);
1643 + packfile_store_load_pack(files->packed, final_index_name, 0);
1644 + }
1645
1646 if (!from_stdin) {
1647 printf("%s\n", hash_to_hex(hash));
builtin/pack-objects.c
+9 -4
@@ -1531,7 +1531,8 @@ static int want_cruft_object_mtime(struct repository *r,
1531 struct odb_source *source;
1532
1533 for (source = r->objects->sources; source; source = source->next) {
1534 - struct packed_git **cache = packfile_store_get_kept_pack_cache(source->files->packed, flags);
1534 + struct odb_source_files *files = odb_source_files_downcast(source);
1535 + struct packed_git **cache = packfile_store_get_kept_pack_cache(files->packed, flags);
1536
1537 for (; *cache; cache++) {
1538 struct packed_git *p = *cache;
@@ -1753,11 +1754,13 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
1754 }
1755
1756 for (source = the_repository->objects->sources; source; source = source->next) {
1756 - for (e = source->files->packed->packs.head; e; e = e->next) {
1757 + struct odb_source_files *files = odb_source_files_downcast(source);
1758 +
1759 + for (e = files->packed->packs.head; e; e = e->next) {
1760 struct packed_git *p = e->pack;
1761 want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime);
1762 if (!exclude && want > 0)
1760 - packfile_list_prepend(&source->files->packed->packs, p);
1763 + packfile_list_prepend(&files->packed->packs, p);
1764 if (want != -1)
1765 return want;
1766 }
@@ -4337,10 +4340,12 @@ static void add_objects_in_unpacked_packs(void)
4340
4341 odb_prepare_alternates(to_pack.repo->objects);
4342 for (source = to_pack.repo->objects->sources; source; source = source->next) {
4343 + struct odb_source_files *files = odb_source_files_downcast(source);
4344 +
4345 if (!source->local)
4346 continue;
4347
4343 - if (packfile_store_for_each_object(source->files->packed, &oi,
4348 + if (packfile_store_for_each_object(files->packed, &oi,
4349 add_object_in_unpacked_pack, NULL,
4350 ODB_FOR_EACH_OBJECT_PACK_ORDER |
4351 ODB_FOR_EACH_OBJECT_LOCAL_ONLY |
commit-graph.c
+4 -2
@@ -1980,9 +1980,11 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
1980 ctx->approx_nr_objects);
1981
1982 odb_prepare_alternates(ctx->r->objects);
1983 - for (source = ctx->r->objects->sources; source; source = source->next)
1984 - packfile_store_for_each_object(source->files->packed, &oi, add_packed_commits_oi,
1983 + for (source = ctx->r->objects->sources; source; source = source->next) {
1984 + struct odb_source_files *files = odb_source_files_downcast(source);
1985 + packfile_store_for_each_object(files->packed, &oi, add_packed_commits_oi,
1986 ctx, ODB_FOR_EACH_OBJECT_PACK_ORDER);
1987 + }
1988
1989 if (ctx->progress_done < ctx->approx_nr_objects)
1990 display_progress(ctx->progress, ctx->approx_nr_objects);
http.c
+2 -1
@@ -2543,8 +2543,9 @@ cleanup:
2543 void http_install_packfile(struct packed_git *p,
2544 struct packfile_list *list_to_remove_from)
2545 {
2546 + struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->sources);
2547 packfile_list_remove(list_to_remove_from, p);
2547 - packfile_store_add_pack(the_repository->objects->sources->files->packed, p);
2548 + packfile_store_add_pack(files->packed, p);
2549 }
2550
2551 struct http_pack_request *new_http_pack_request(
loose.c
+14 -9
@@ -3,6 +3,7 @@
3 #include "path.h"
4 #include "object-file.h"
5 #include "odb.h"
6 +#include "odb/source-files.h"
7 #include "hex.h"
8 #include "repository.h"
9 #include "wrapper.h"
@@ -49,27 +50,29 @@ static int insert_loose_map(struct odb_source *source,
50 const struct object_id *oid,
51 const struct object_id *compat_oid)
52 {
52 - struct loose_object_map *map = source->files->loose->map;
53 + struct odb_source_files *files = odb_source_files_downcast(source);
54 + struct loose_object_map *map = files->loose->map;
55 int inserted = 0;
56
57 inserted |= insert_oid_pair(map->to_compat, oid, compat_oid);
58 inserted |= insert_oid_pair(map->to_storage, compat_oid, oid);
59 if (inserted)
58 - oidtree_insert(source->files->loose->cache, compat_oid);
60 + oidtree_insert(files->loose->cache, compat_oid);
61
62 return inserted;
63 }
64
65 static int load_one_loose_object_map(struct repository *repo, struct odb_source *source)
66 {
67 + struct odb_source_files *files = odb_source_files_downcast(source);
68 struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
69 FILE *fp;
70
68 - if (!source->files->loose->map)
69 - loose_object_map_init(&source->files->loose->map);
70 - if (!source->files->loose->cache) {
71 - ALLOC_ARRAY(source->files->loose->cache, 1);
72 - oidtree_init(source->files->loose->cache);
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);
76 }
77
78 insert_loose_map(source, repo->hash_algo->empty_tree, repo->compat_hash_algo->empty_tree);
@@ -125,7 +128,8 @@ int repo_read_loose_object_map(struct repository *repo)
128
129 int repo_write_loose_object_map(struct repository *repo)
130 {
128 - kh_oid_map_t *map = repo->objects->sources->files->loose->map->to_compat;
131 + struct odb_source_files *files = odb_source_files_downcast(repo->objects->sources);
132 + kh_oid_map_t *map = files->loose->map->to_compat;
133 struct lock_file lock;
134 int fd;
135 khiter_t iter;
@@ -231,7 +235,8 @@ int repo_loose_object_map_oid(struct repository *repo,
235 khiter_t pos;
236
237 for (source = repo->objects->sources; source; source = source->next) {
234 - struct loose_object_map *loose_map = source->files->loose->map;
238 + struct odb_source_files *files = odb_source_files_downcast(source);
239 + struct loose_object_map *loose_map = files->loose->map;
240 if (!loose_map)
241 continue;
242 map = (to == repo->compat_hash_algo) ?
midx.c
+15 -11
@@ -95,8 +95,9 @@ static int midx_read_object_offsets(const unsigned char *chunk_start,
95
96 struct multi_pack_index *get_multi_pack_index(struct odb_source *source)
97 {
98 - packfile_store_prepare(source->files->packed);
99 - return source->files->packed->midx;
98 + struct odb_source_files *files = odb_source_files_downcast(source);
99 + packfile_store_prepare(files->packed);
100 + return files->packed->midx;
101 }
102
103 static struct multi_pack_index *load_multi_pack_index_one(struct odb_source *source,
@@ -447,6 +448,7 @@ static uint32_t midx_for_pack(struct multi_pack_index **_m,
448 int prepare_midx_pack(struct multi_pack_index *m,
449 uint32_t pack_int_id)
450 {
451 + struct odb_source_files *files = odb_source_files_downcast(m->source);
452 struct strbuf pack_name = STRBUF_INIT;
453 struct packed_git *p;
454
@@ -457,10 +459,10 @@ int prepare_midx_pack(struct multi_pack_index *m,
459 if (m->packs[pack_int_id])
460 return 0;
461
460 - strbuf_addf(&pack_name, "%s/pack/%s", m->source->path,
462 + strbuf_addf(&pack_name, "%s/pack/%s", files->base.path,
463 m->pack_names[pack_int_id]);
462 - p = packfile_store_load_pack(m->source->files->packed,
463 - pack_name.buf, m->source->local);
464 + p = packfile_store_load_pack(files->packed,
465 + pack_name.buf, files->base.local);
466 strbuf_release(&pack_name);
467
468 if (!p) {
@@ -703,18 +705,19 @@ int midx_preferred_pack(struct multi_pack_index *m, uint32_t *pack_int_id)
705
706 int prepare_multi_pack_index_one(struct odb_source *source)
707 {
708 + struct odb_source_files *files = odb_source_files_downcast(source);
709 struct repository *r = source->odb->repo;
710
711 prepare_repo_settings(r);
712 if (!r->settings.core_multi_pack_index)
713 return 0;
714
712 - if (source->files->packed->midx)
715 + if (files->packed->midx)
716 return 1;
717
715 - source->files->packed->midx = load_multi_pack_index(source);
718 + files->packed->midx = load_multi_pack_index(source);
719
717 - return !!source->files->packed->midx;
720 + return !!files->packed->midx;
721 }
722
723 int midx_checksum_valid(struct multi_pack_index *m)
@@ -803,9 +806,10 @@ void clear_midx_file(struct repository *r)
806 struct odb_source *source;
807
808 for (source = r->objects->sources; source; source = source->next) {
806 - if (source->files->packed->midx)
807 - close_midx(source->files->packed->midx);
808 - source->files->packed->midx = NULL;
809 + struct odb_source_files *files = odb_source_files_downcast(source);
810 + if (files->packed->midx)
811 + close_midx(files->packed->midx);
812 + files->packed->midx = NULL;
813 }
814 }
815
object-file.c
+16 -12
@@ -219,8 +219,9 @@ static void *odb_source_loose_map_object(struct odb_source *source,
219 const struct object_id *oid,
220 unsigned long *size)
221 {
222 + struct odb_source_files *files = odb_source_files_downcast(source);
223 const char *p;
223 - int fd = open_loose_object(source->files->loose, oid, &p);
224 + int fd = open_loose_object(files->loose, oid, &p);
225
226 if (fd < 0)
227 return NULL;
@@ -401,6 +402,7 @@ static int read_object_info_from_path(struct odb_source *source,
402 struct object_info *oi,
403 enum object_info_flags flags)
404 {
405 + struct odb_source_files *files = odb_source_files_downcast(source);
406 int ret;
407 int fd;
408 unsigned long mapsize;
@@ -423,7 +425,7 @@ static int read_object_info_from_path(struct odb_source *source,
425 struct stat st;
426
427 if ((!oi || (!oi->disk_sizep && !oi->mtimep)) && (flags & OBJECT_INFO_QUICK)) {
426 - ret = quick_has_loose(source->files->loose, oid) ? 0 : -1;
428 + ret = quick_has_loose(files->loose, oid) ? 0 : -1;
429 goto out;
430 }
431
@@ -1866,33 +1868,34 @@ static int append_loose_object(const struct object_id *oid,
1868 struct oidtree *odb_source_loose_cache(struct odb_source *source,
1869 const struct object_id *oid)
1870 {
1871 + struct odb_source_files *files = odb_source_files_downcast(source);
1872 int subdir_nr = oid->hash[0];
1873 struct strbuf buf = STRBUF_INIT;
1871 - size_t word_bits = bitsizeof(source->files->loose->subdir_seen[0]);
1874 + size_t word_bits = bitsizeof(files->loose->subdir_seen[0]);
1875 size_t word_index = subdir_nr / word_bits;
1876 size_t mask = (size_t)1u << (subdir_nr % word_bits);
1877 uint32_t *bitmap;
1878
1879 if (subdir_nr < 0 ||
1877 - (size_t) subdir_nr >= bitsizeof(source->files->loose->subdir_seen))
1880 + (size_t) subdir_nr >= bitsizeof(files->loose->subdir_seen))
1881 BUG("subdir_nr out of range");
1882
1880 - bitmap = &source->files->loose->subdir_seen[word_index];
1883 + bitmap = &files->loose->subdir_seen[word_index];
1884 if (*bitmap & mask)
1882 - return source->files->loose->cache;
1883 - if (!source->files->loose->cache) {
1884 - ALLOC_ARRAY(source->files->loose->cache, 1);
1885 - oidtree_init(source->files->loose->cache);
1885 + return files->loose->cache;
1886 + if (!files->loose->cache) {
1887 + ALLOC_ARRAY(files->loose->cache, 1);
1888 + oidtree_init(files->loose->cache);
1889 }
1890 strbuf_addstr(&buf, source->path);
1891 for_each_file_in_obj_subdir(subdir_nr, &buf,
1892 source->odb->repo->hash_algo,
1893 append_loose_object,
1894 NULL, NULL,
1892 - source->files->loose->cache);
1895 + files->loose->cache);
1896 *bitmap |= mask;
1897 strbuf_release(&buf);
1895 - return source->files->loose->cache;
1898 + return files->loose->cache;
1899 }
1900
1901 static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
@@ -1905,7 +1908,8 @@ static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
1908
1909 void odb_source_loose_reprepare(struct odb_source *source)
1910 {
1908 - odb_source_loose_clear_cache(source->files->loose);
1911 + struct odb_source_files *files = odb_source_files_downcast(source);
1912 + odb_source_loose_clear_cache(files->loose);
1913 }
1914
1915 static int check_stream_oid(git_zstream *stream,
odb.c
+18 -8
@@ -691,7 +691,8 @@ static int do_oid_object_info_extended(struct object_database *odb,
691
692 /* Most likely it's a loose object. */
693 for (source = odb->sources; source; source = source->next) {
694 - if (!packfile_store_read_object_info(source->files->packed, real, oi, flags) ||
694 + struct odb_source_files *files = odb_source_files_downcast(source);
695 + if (!packfile_store_read_object_info(files->packed, real, oi, flags) ||
696 !odb_source_loose_read_object_info(source, real, oi, flags))
697 return 0;
698 }
@@ -699,9 +700,11 @@ static int do_oid_object_info_extended(struct object_database *odb,
700 /* Not a loose object; someone else may have just packed it. */
701 if (!(flags & OBJECT_INFO_QUICK)) {
702 odb_reprepare(odb->repo->objects);
702 - for (source = odb->sources; source; source = source->next)
703 - if (!packfile_store_read_object_info(source->files->packed, real, oi, flags))
703 + for (source = odb->sources; source; source = source->next) {
704 + struct odb_source_files *files = odb_source_files_downcast(source);
705 + if (!packfile_store_read_object_info(files->packed, real, oi, flags))
706 return 0;
707 + }
708 }
709
710 /*
@@ -962,7 +965,9 @@ int odb_freshen_object(struct object_database *odb,
965
966 odb_prepare_alternates(odb);
967 for (source = odb->sources; source; source = source->next) {
965 - if (packfile_store_freshen_object(source->files->packed, oid))
968 + struct odb_source_files *files = odb_source_files_downcast(source);
969 +
970 + if (packfile_store_freshen_object(files->packed, oid))
971 return 1;
972
973 if (odb_source_loose_freshen_object(source, oid))
@@ -982,6 +987,8 @@ int odb_for_each_object(struct object_database *odb,
987
988 odb_prepare_alternates(odb);
989 for (struct odb_source *source = odb->sources; source; source = source->next) {
990 + struct odb_source_files *files = odb_source_files_downcast(source);
991 +
992 if (flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY && !source->local)
993 continue;
994
@@ -992,7 +999,7 @@ int odb_for_each_object(struct object_database *odb,
999 return ret;
1000 }
1001
995 - ret = packfile_store_for_each_object(source->files->packed, request,
1002 + ret = packfile_store_for_each_object(files->packed, request,
1003 cb, cb_data, flags);
1004 if (ret)
1005 return ret;
@@ -1090,8 +1097,10 @@ struct object_database *odb_new(struct repository *repo,
1097 void odb_close(struct object_database *o)
1098 {
1099 struct odb_source *source;
1093 - for (source = o->sources; source; source = source->next)
1094 - packfile_store_close(source->files->packed);
1100 + for (source = o->sources; source; source = source->next) {
1101 + struct odb_source_files *files = odb_source_files_downcast(source);
1102 + packfile_store_close(files->packed);
1103 + }
1104 close_commit_graph(o);
1105 }
1106
@@ -1148,8 +1157,9 @@ void odb_reprepare(struct object_database *o)
1157 odb_prepare_alternates(o);
1158
1159 for (source = o->sources; source; source = source->next) {
1160 + struct odb_source_files *files = odb_source_files_downcast(source);
1161 odb_source_loose_reprepare(source);
1152 - packfile_store_reprepare(source->files->packed);
1162 + packfile_store_reprepare(files->packed);
1163 }
1164
1165 o->approximate_object_count_valid = 0;
odb/source-files.c
+10 -4
@@ -1,5 +1,6 @@
1 #include "git-compat-util.h"
2 #include "object-file.h"
3 +#include "odb/source.h"
4 #include "odb/source-files.h"
5 #include "packfile.h"
6
@@ -9,15 +10,20 @@ void odb_source_files_free(struct odb_source_files *files)
10 return;
11 odb_source_loose_free(files->loose);
12 packfile_store_free(files->packed);
13 + odb_source_release(&files->base);
14 free(files);
15 }
16
15 -struct odb_source_files *odb_source_files_new(struct odb_source *source)
17 +struct odb_source_files *odb_source_files_new(struct object_database *odb,
18 + const char *path,
19 + bool local)
20 {
21 struct odb_source_files *files;
22 +
23 CALLOC_ARRAY(files, 1);
19 - files->source = source;
20 - files->loose = odb_source_loose_new(source);
21 - files->packed = packfile_store_new(source);
24 + odb_source_init(&files->base, odb, path, local);
25 + files->loose = odb_source_loose_new(&files->base);
26 + files->packed = packfile_store_new(&files->base);
27 +
28 return files;
29 }
odb/source-files.h
+14 -3
@@ -1,8 +1,9 @@
1 #ifndef ODB_SOURCE_FILES_H
2 #define ODB_SOURCE_FILES_H
3
4 +#include "odb/source.h"
5 +
6 struct odb_source_loose;
5 -struct odb_source;
7 struct packfile_store;
8
9 /*
@@ -10,15 +11,25 @@ struct packfile_store;
11 * packfiles. It is the default backend used by Git to store objects.
12 */
13 struct odb_source_files {
13 - struct odb_source *source;
14 + struct odb_source base;
15 struct odb_source_loose *loose;
16 struct packfile_store *packed;
17 };
18
19 /* Allocate and initialize a new object source. */
19 -struct odb_source_files *odb_source_files_new(struct odb_source *source);
20 +struct odb_source_files *odb_source_files_new(struct object_database *odb,
21 + const char *path,
22 + bool local);
23
24 /* Free the object source and release all associated resources. */
25 void odb_source_files_free(struct odb_source_files *files);
26
27 +/*
28 + * Cast the given object database source to the files backend.
29 + */
30 +static inline struct odb_source_files *odb_source_files_downcast(struct odb_source *source)
31 +{
32 + return container_of(source, struct odb_source_files, base);
33 +}
34 +
35 #endif
odb/source.c
+19 -7
@@ -1,5 +1,6 @@
1 #include "git-compat-util.h"
2 #include "object-file.h"
3 +#include "odb/source-files.h"
4 #include "odb/source.h"
5 #include "packfile.h"
6
@@ -7,20 +8,31 @@ struct odb_source *odb_source_new(struct object_database *odb,
8 const char *path,
9 bool local)
10 {
10 - struct odb_source *source;
11 + return &odb_source_files_new(odb, path, local)->base;
12 +}
13
12 - CALLOC_ARRAY(source, 1);
14 +void odb_source_init(struct odb_source *source,
15 + struct object_database *odb,
16 + const char *path,
17 + bool local)
18 +{
19 source->odb = odb;
20 source->local = local;
21 source->path = xstrdup(path);
16 - source->files = odb_source_files_new(source);
17 -
18 - return source;
22 }
23
24 void odb_source_free(struct odb_source *source)
25 {
26 + struct odb_source_files *files;
27 + if (!source)
28 + return;
29 + files = odb_source_files_downcast(source);
30 + odb_source_files_free(files);
31 +}
32 +
33 +void odb_source_release(struct odb_source *source)
34 +{
35 + if (!source)
36 + return;
37 free(source->path);
24 - odb_source_files_free(source->files);
25 - free(source);
38 }
odb/source.h
+25 -6
@@ -1,8 +1,6 @@
1 #ifndef ODB_SOURCE_H
2 #define ODB_SOURCE_H
3
4 -#include "odb/source-files.h"
5 -
4 /*
5 * The source is the part of the object database that stores the actual
6 * objects. It thus encapsulates the logic to read and write the specific
@@ -21,9 +19,6 @@ struct odb_source {
19 /* Object database that owns this object source. */
20 struct object_database *odb;
21
24 - /* The backend used to store objects. */
25 - struct odb_source_files *files;
26 -
22 /*
23 * Figure out whether this is the local source of the owning
24 * repository, which would typically be its ".git/objects" directory.
@@ -53,7 +48,31 @@ struct odb_source *odb_source_new(struct object_database *odb,
48 const char *path,
49 bool local);
50
56 -/* Free the object database source, releasing all associated resources. */
51 +/*
52 + * Initialize the source for the given object database located at `path`.
53 + * `local` indicates whether or not the source is the local and thus primary
54 + * object source of the object database.
55 + *
56 + * This function is only supposed to be called by specific object source
57 + * implementations.
58 + */
59 +void odb_source_init(struct odb_source *source,
60 + struct object_database *odb,
61 + const char *path,
62 + bool local);
63 +
64 +/*
65 + * Free the object database source, releasing all associated resources and
66 + * freeing the structure itself.
67 + */
68 void odb_source_free(struct odb_source *source);
69
70 +/*
71 + * Release the object database source, releasing all associated resources.
72 + *
73 + * This function is only supposed to be called by specific object source
74 + * implementations.
75 + */
76 +void odb_source_release(struct odb_source *source);
77 +
78 #endif
odb/streaming.c
+2 -1
@@ -187,7 +187,8 @@ static int istream_source(struct odb_read_stream **out,
187
188 odb_prepare_alternates(odb);
189 for (source = odb->sources; source; source = source->next) {
190 - if (!packfile_store_read_object_stream(out, source->files->packed, oid) ||
190 + struct odb_source_files *files = odb_source_files_downcast(source);
191 + if (!packfile_store_read_object_stream(out, files->packed, oid) ||
192 !odb_source_loose_read_object_stream(out, source, oid))
193 return 0;
194 }
packfile.c
+17 -9
@@ -362,9 +362,11 @@ static int unuse_one_window(struct object_database *odb)
362 struct packed_git *lru_p = NULL;
363 struct pack_window *lru_w = NULL, *lru_l = NULL;
364
365 - for (source = odb->sources; source; source = source->next)
366 - for (e = source->files->packed->packs.head; e; e = e->next)
365 + for (source = odb->sources; source; source = source->next) {
366 + struct odb_source_files *files = odb_source_files_downcast(source);
367 + for (e = files->packed->packs.head; e; e = e->next)
368 scan_windows(e->pack, &lru_p, &lru_w, &lru_l);
369 + }
370
371 if (lru_p) {
372 munmap(lru_w->base, lru_w->len);
@@ -537,7 +539,8 @@ static int close_one_pack(struct repository *r)
539 int accept_windows_inuse = 1;
540
541 for (source = r->objects->sources; source; source = source->next) {
540 - for (e = source->files->packed->packs.head; e; e = e->next) {
542 + struct odb_source_files *files = odb_source_files_downcast(source);
543 + for (e = files->packed->packs.head; e; e = e->next) {
544 if (e->pack->pack_fd == -1)
545 continue;
546 find_lru_pack(e->pack, &lru_p, &mru_w, &accept_windows_inuse);
@@ -987,13 +990,14 @@ static void prepare_pack(const char *full_name, size_t full_name_len,
990 const char *file_name, void *_data)
991 {
992 struct prepare_pack_data *data = (struct prepare_pack_data *)_data;
993 + struct odb_source_files *files = odb_source_files_downcast(data->source);
994 size_t base_len = full_name_len;
995
996 if (strip_suffix_mem(full_name, &base_len, ".idx") &&
993 - !(data->source->files->packed->midx &&
994 - midx_contains_pack(data->source->files->packed->midx, file_name))) {
997 + !(files->packed->midx &&
998 + midx_contains_pack(files->packed->midx, file_name))) {
999 char *trimmed_path = xstrndup(full_name, full_name_len);
996 - packfile_store_load_pack(data->source->files->packed,
1000 + packfile_store_load_pack(files->packed,
1001 trimmed_path, data->source->local);
1002 free(trimmed_path);
1003 }
@@ -1247,8 +1251,10 @@ const struct packed_git *has_packed_and_bad(struct repository *r,
1251 struct odb_source *source;
1252
1253 for (source = r->objects->sources; source; source = source->next) {
1254 + struct odb_source_files *files = odb_source_files_downcast(source);
1255 struct packfile_list_entry *e;
1251 - for (e = source->files->packed->packs.head; e; e = e->next)
1256 +
1257 + for (e = files->packed->packs.head; e; e = e->next)
1258 if (oidset_contains(&e->pack->bad_objects, oid))
1259 return e->pack;
1260 }
@@ -2254,7 +2260,8 @@ int has_object_pack(struct repository *r, const struct object_id *oid)
2260
2261 odb_prepare_alternates(r->objects);
2262 for (source = r->objects->sources; source; source = source->next) {
2257 - int ret = find_pack_entry(source->files->packed, oid, &e);
2263 + struct odb_source_files *files = odb_source_files_downcast(source);
2264 + int ret = find_pack_entry(files->packed, oid, &e);
2265 if (ret)
2266 return ret;
2267 }
@@ -2269,9 +2276,10 @@ int has_object_kept_pack(struct repository *r, const struct object_id *oid,
2276 struct pack_entry e;
2277
2278 for (source = r->objects->sources; source; source = source->next) {
2279 + struct odb_source_files *files = odb_source_files_downcast(source);
2280 struct packed_git **cache;
2281
2274 - cache = packfile_store_get_kept_pack_cache(source->files->packed, flags);
2282 + cache = packfile_store_get_kept_pack_cache(files->packed, flags);
2283
2284 for (; *cache; cache++) {
2285 struct packed_git *p = *cache;
packfile.h
+5 -2
@@ -4,6 +4,7 @@
4 #include "list.h"
5 #include "object.h"
6 #include "odb.h"
7 +#include "odb/source-files.h"
8 #include "oidset.h"
9 #include "repository.h"
10 #include "strmap.h"
@@ -192,7 +193,8 @@ static inline struct repo_for_each_pack_data repo_for_eack_pack_data_init(struct
193 odb_prepare_alternates(repo->objects);
194
195 for (struct odb_source *source = repo->objects->sources; source; source = source->next) {
195 - struct packfile_list_entry *entry = packfile_store_get_packs(source->files->packed);
196 + struct odb_source_files *files = odb_source_files_downcast(source);
197 + struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
198 if (!entry)
199 continue;
200 data.source = source;
@@ -212,7 +214,8 @@ static inline void repo_for_each_pack_data_next(struct repo_for_each_pack_data *
214 return;
215
216 for (source = data->source->next; source; source = source->next) {
215 - struct packfile_list_entry *entry = packfile_store_get_packs(source->files->packed);
217 + struct odb_source_files *files = odb_source_files_downcast(source);
218 + struct packfile_list_entry *entry = packfile_store_get_packs(files->packed);
219 if (!entry)
220 continue;
221 data->source = source;