odb: introduce "files" source
Introduce a new "files" object database source. This source encapsulates access to both loose object files and the packfile store, similar to how the "files" backend for refs encapsulates access to loose refs and the packed-refs file. Note that for now the "files" source is still a direct member of a `struct odb_source`. This architecture will be reversed in the next commit so that the files source contains a `struct odb_source`. 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
cb506a8a69c953f7b87bb3ae099e0bed8218d3ab
20 files changed
+114
-68
Makefile
+1
@@ -1215,6 +1215,7 @@ LIB_OBJS += object-name.o
1215
LIB_OBJS += object.o
1216
LIB_OBJS += odb.o
1217
LIB_OBJS += odb/source.o
1218
+LIB_OBJS += odb/source-files.o
1219
LIB_OBJS += odb/streaming.o
1220
LIB_OBJS += oid-array.o
1221
LIB_OBJS += oidmap.o
builtin/cat-file.c
+1
-1
@@ -882,7 +882,7 @@ 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->packfiles, &oi,
885
+ int ret = packfile_store_for_each_object(source->files->packed, &oi,
886
batch_one_object_oi, &payload, flags);
887
if (ret)
888
break;
builtin/fast-import.c
+3
-3
@@ -900,7 +900,7 @@ static void end_packfile(void)
900
idx_name = keep_pack(create_index());
901
902
/* Register the packfile with core git's machinery. */
903
- new_p = packfile_store_load_pack(pack_data->repo->objects->sources->packfiles,
903
+ new_p = packfile_store_load_pack(pack_data->repo->objects->sources->files->packed,
904
idx_name, 1);
905
if (!new_p)
906
die(_("core Git rejected index %s"), idx_name);
@@ -982,7 +982,7 @@ 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->packfiles), &oid))
985
+ if (!packfile_list_find_oid(packfile_store_get_packs(source->files->packed), &oid))
986
continue;
987
e->type = type;
988
e->pack_id = MAX_PACK_ID;
@@ -1187,7 +1187,7 @@ static void stream_blob(uintmax_t len, struct object_id *oidout, uintmax_t mark)
1187
}
1188
1189
for (source = the_repository->objects->sources; source; source = source->next) {
1190
- if (!packfile_list_find_oid(packfile_store_get_packs(source->packfiles), &oid))
1190
+ if (!packfile_list_find_oid(packfile_store_get_packs(source->files->packed), &oid))
1191
continue;
1192
e->type = OBJ_BLOB;
1193
e->pack_id = MAX_PACK_ID;
builtin/grep.c
+1
-1
@@ -1219,7 +1219,7 @@ int cmd_grep(int argc,
1219
1220
odb_prepare_alternates(the_repository->objects);
1221
for (source = the_repository->objects->sources; source; source = source->next)
1222
- packfile_store_prepare(source->packfiles);
1222
+ packfile_store_prepare(source->files->packed);
1223
}
1224
1225
start_threads(&opt);
builtin/index-pack.c
+1
-1
@@ -1638,7 +1638,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
1638
hash, "idx", 1);
1639
1640
if (do_fsck_object && startup_info->have_repository)
1641
- packfile_store_load_pack(the_repository->objects->sources->packfiles,
1641
+ packfile_store_load_pack(the_repository->objects->sources->files->packed,
1642
final_index_name, 0);
1643
1644
if (!from_stdin) {
builtin/pack-objects.c
+4
-4
@@ -1531,7 +1531,7 @@ 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->packfiles, flags);
1534
+ struct packed_git **cache = packfile_store_get_kept_pack_cache(source->files->packed, flags);
1535
1536
for (; *cache; cache++) {
1537
struct packed_git *p = *cache;
@@ -1753,11 +1753,11 @@ static int want_object_in_pack_mtime(const struct object_id *oid,
1753
}
1754
1755
for (source = the_repository->objects->sources; source; source = source->next) {
1756
- for (e = source->packfiles->packs.head; e; e = e->next) {
1756
+ for (e = source->files->packed->packs.head; e; e = e->next) {
1757
struct packed_git *p = e->pack;
1758
want = want_object_in_pack_one(p, oid, exclude, found_pack, found_offset, found_mtime);
1759
if (!exclude && want > 0)
1760
- packfile_list_prepend(&source->packfiles->packs, p);
1760
+ packfile_list_prepend(&source->files->packed->packs, p);
1761
if (want != -1)
1762
return want;
1763
}
@@ -4340,7 +4340,7 @@ static void add_objects_in_unpacked_packs(void)
4340
if (!source->local)
4341
continue;
4342
4343
- if (packfile_store_for_each_object(source->packfiles, &oi,
4343
+ if (packfile_store_for_each_object(source->files->packed, &oi,
4344
add_object_in_unpacked_pack, NULL,
4345
ODB_FOR_EACH_OBJECT_PACK_ORDER |
4346
ODB_FOR_EACH_OBJECT_LOCAL_ONLY |
commit-graph.c
+1
-1
@@ -1981,7 +1981,7 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
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->packfiles, &oi, add_packed_commits_oi,
1984
+ packfile_store_for_each_object(source->files->packed, &oi, add_packed_commits_oi,
1985
ctx, ODB_FOR_EACH_OBJECT_PACK_ORDER);
1986
1987
if (ctx->progress_done < ctx->approx_nr_objects)
http.c
+1
-1
@@ -2544,7 +2544,7 @@ void http_install_packfile(struct packed_git *p,
2544
struct packfile_list *list_to_remove_from)
2545
{
2546
packfile_list_remove(list_to_remove_from, p);
2547
- packfile_store_add_pack(the_repository->objects->sources->packfiles, p);
2547
+ packfile_store_add_pack(the_repository->objects->sources->files->packed, p);
2548
}
2549
2550
struct http_pack_request *new_http_pack_request(
loose.c
+9
-9
@@ -49,13 +49,13 @@ static int insert_loose_map(struct odb_source *source,
49
const struct object_id *oid,
50
const struct object_id *compat_oid)
51
{
52
- struct loose_object_map *map = source->loose->map;
52
+ struct loose_object_map *map = source->files->loose->map;
53
int inserted = 0;
54
55
inserted |= insert_oid_pair(map->to_compat, oid, compat_oid);
56
inserted |= insert_oid_pair(map->to_storage, compat_oid, oid);
57
if (inserted)
58
- oidtree_insert(source->loose->cache, compat_oid);
58
+ oidtree_insert(source->files->loose->cache, compat_oid);
59
60
return inserted;
61
}
@@ -65,11 +65,11 @@ static int load_one_loose_object_map(struct repository *repo, struct odb_source
65
struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
66
FILE *fp;
67
68
- if (!source->loose->map)
69
- loose_object_map_init(&source->loose->map);
70
- if (!source->loose->cache) {
71
- ALLOC_ARRAY(source->loose->cache, 1);
72
- oidtree_init(source->loose->cache);
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);
73
}
74
75
insert_loose_map(source, repo->hash_algo->empty_tree, repo->compat_hash_algo->empty_tree);
@@ -125,7 +125,7 @@ int repo_read_loose_object_map(struct repository *repo)
125
126
int repo_write_loose_object_map(struct repository *repo)
127
{
128
- kh_oid_map_t *map = repo->objects->sources->loose->map->to_compat;
128
+ kh_oid_map_t *map = repo->objects->sources->files->loose->map->to_compat;
129
struct lock_file lock;
130
int fd;
131
khiter_t iter;
@@ -231,7 +231,7 @@ int repo_loose_object_map_oid(struct repository *repo,
231
khiter_t pos;
232
233
for (source = repo->objects->sources; source; source = source->next) {
234
- struct loose_object_map *loose_map = source->loose->map;
234
+ struct loose_object_map *loose_map = source->files->loose->map;
235
if (!loose_map)
236
continue;
237
map = (to == repo->compat_hash_algo) ?
meson.build
+1
@@ -398,6 +398,7 @@ libgit_sources = [
398
'object.c',
399
'odb.c',
400
'odb/source.c',
401
+ 'odb/source-files.c',
402
'odb/streaming.c',
403
'oid-array.c',
404
'oidmap.c',
midx.c
+9
-9
@@ -95,8 +95,8 @@ 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->packfiles);
99
- return source->packfiles->midx;
98
+ packfile_store_prepare(source->files->packed);
99
+ return source->files->packed->midx;
100
}
101
102
static struct multi_pack_index *load_multi_pack_index_one(struct odb_source *source,
@@ -459,7 +459,7 @@ int prepare_midx_pack(struct multi_pack_index *m,
459
460
strbuf_addf(&pack_name, "%s/pack/%s", m->source->path,
461
m->pack_names[pack_int_id]);
462
- p = packfile_store_load_pack(m->source->packfiles,
462
+ p = packfile_store_load_pack(m->source->files->packed,
463
pack_name.buf, m->source->local);
464
strbuf_release(&pack_name);
465
@@ -709,12 +709,12 @@ int prepare_multi_pack_index_one(struct odb_source *source)
709
if (!r->settings.core_multi_pack_index)
710
return 0;
711
712
- if (source->packfiles->midx)
712
+ if (source->files->packed->midx)
713
return 1;
714
715
- source->packfiles->midx = load_multi_pack_index(source);
715
+ source->files->packed->midx = load_multi_pack_index(source);
716
717
- return !!source->packfiles->midx;
717
+ return !!source->files->packed->midx;
718
}
719
720
int midx_checksum_valid(struct multi_pack_index *m)
@@ -803,9 +803,9 @@ void clear_midx_file(struct repository *r)
803
struct odb_source *source;
804
805
for (source = r->objects->sources; source; source = source->next) {
806
- if (source->packfiles->midx)
807
- close_midx(source->packfiles->midx);
808
- source->packfiles->midx = NULL;
806
+ if (source->files->packed->midx)
807
+ close_midx(source->files->packed->midx);
808
+ source->files->packed->midx = NULL;
809
}
810
}
811
object-file.c
+12
-12
@@ -220,7 +220,7 @@ static void *odb_source_loose_map_object(struct odb_source *source,
220
unsigned long *size)
221
{
222
const char *p;
223
- int fd = open_loose_object(source->loose, oid, &p);
223
+ int fd = open_loose_object(source->files->loose, oid, &p);
224
225
if (fd < 0)
226
return NULL;
@@ -423,7 +423,7 @@ static int read_object_info_from_path(struct odb_source *source,
423
struct stat st;
424
425
if ((!oi || (!oi->disk_sizep && !oi->mtimep)) && (flags & OBJECT_INFO_QUICK)) {
426
- ret = quick_has_loose(source->loose, oid) ? 0 : -1;
426
+ ret = quick_has_loose(source->files->loose, oid) ? 0 : -1;
427
goto out;
428
}
429
@@ -1868,31 +1868,31 @@ struct oidtree *odb_source_loose_cache(struct odb_source *source,
1868
{
1869
int subdir_nr = oid->hash[0];
1870
struct strbuf buf = STRBUF_INIT;
1871
- size_t word_bits = bitsizeof(source->loose->subdir_seen[0]);
1871
+ size_t word_bits = bitsizeof(source->files->loose->subdir_seen[0]);
1872
size_t word_index = subdir_nr / word_bits;
1873
size_t mask = (size_t)1u << (subdir_nr % word_bits);
1874
uint32_t *bitmap;
1875
1876
if (subdir_nr < 0 ||
1877
- (size_t) subdir_nr >= bitsizeof(source->loose->subdir_seen))
1877
+ (size_t) subdir_nr >= bitsizeof(source->files->loose->subdir_seen))
1878
BUG("subdir_nr out of range");
1879
1880
- bitmap = &source->loose->subdir_seen[word_index];
1880
+ bitmap = &source->files->loose->subdir_seen[word_index];
1881
if (*bitmap & mask)
1882
- return source->loose->cache;
1883
- if (!source->loose->cache) {
1884
- ALLOC_ARRAY(source->loose->cache, 1);
1885
- oidtree_init(source->loose->cache);
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);
1886
}
1887
strbuf_addstr(&buf, source->path);
1888
for_each_file_in_obj_subdir(subdir_nr, &buf,
1889
source->odb->repo->hash_algo,
1890
append_loose_object,
1891
NULL, NULL,
1892
- source->loose->cache);
1892
+ source->files->loose->cache);
1893
*bitmap |= mask;
1894
strbuf_release(&buf);
1895
- return source->loose->cache;
1895
+ return source->files->loose->cache;
1896
}
1897
1898
static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
@@ -1905,7 +1905,7 @@ static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
1905
1906
void odb_source_loose_reprepare(struct odb_source *source)
1907
{
1908
- odb_source_loose_clear_cache(source->loose);
1908
+ odb_source_loose_clear_cache(source->files->loose);
1909
}
1910
1911
static int check_stream_oid(git_zstream *stream,
odb.c
+6
-6
@@ -691,7 +691,7 @@ 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->packfiles, real, oi, flags) ||
694
+ if (!packfile_store_read_object_info(source->files->packed, real, oi, flags) ||
695
!odb_source_loose_read_object_info(source, real, oi, flags))
696
return 0;
697
}
@@ -700,7 +700,7 @@ static int do_oid_object_info_extended(struct object_database *odb,
700
if (!(flags & OBJECT_INFO_QUICK)) {
701
odb_reprepare(odb->repo->objects);
702
for (source = odb->sources; source; source = source->next)
703
- if (!packfile_store_read_object_info(source->packfiles, real, oi, flags))
703
+ if (!packfile_store_read_object_info(source->files->packed, real, oi, flags))
704
return 0;
705
}
706
@@ -962,7 +962,7 @@ int odb_freshen_object(struct object_database *odb,
962
963
odb_prepare_alternates(odb);
964
for (source = odb->sources; source; source = source->next) {
965
- if (packfile_store_freshen_object(source->packfiles, oid))
965
+ if (packfile_store_freshen_object(source->files->packed, oid))
966
return 1;
967
968
if (odb_source_loose_freshen_object(source, oid))
@@ -992,7 +992,7 @@ int odb_for_each_object(struct object_database *odb,
992
return ret;
993
}
994
995
- ret = packfile_store_for_each_object(source->packfiles, request,
995
+ ret = packfile_store_for_each_object(source->files->packed, request,
996
cb, cb_data, flags);
997
if (ret)
998
return ret;
@@ -1091,7 +1091,7 @@ void odb_close(struct object_database *o)
1091
{
1092
struct odb_source *source;
1093
for (source = o->sources; source; source = source->next)
1094
- packfile_store_close(source->packfiles);
1094
+ packfile_store_close(source->files->packed);
1095
close_commit_graph(o);
1096
}
1097
@@ -1149,7 +1149,7 @@ void odb_reprepare(struct object_database *o)
1149
1150
for (source = o->sources; source; source = source->next) {
1151
odb_source_loose_reprepare(source);
1152
- packfile_store_reprepare(source->packfiles);
1152
+ packfile_store_reprepare(source->files->packed);
1153
}
1154
1155
o->approximate_object_count_valid = 0;
odb/source-files.c
new
+23
@@ -0,0 +1,23 @@
1
+#include "git-compat-util.h"
2
+#include "object-file.h"
3
+#include "odb/source-files.h"
4
+#include "packfile.h"
5
+
6
+void odb_source_files_free(struct odb_source_files *files)
7
+{
8
+ if (!files)
9
+ return;
10
+ odb_source_loose_free(files->loose);
11
+ packfile_store_free(files->packed);
12
+ free(files);
13
+}
14
+
15
+struct odb_source_files *odb_source_files_new(struct odb_source *source)
16
+{
17
+ struct odb_source_files *files;
18
+ CALLOC_ARRAY(files, 1);
19
+ files->source = source;
20
+ files->loose = odb_source_loose_new(source);
21
+ files->packed = packfile_store_new(source);
22
+ return files;
23
+}
odb/source-files.h
new
+24
@@ -0,0 +1,24 @@
1
+#ifndef ODB_SOURCE_FILES_H
2
+#define ODB_SOURCE_FILES_H
3
+
4
+struct odb_source_loose;
5
+struct odb_source;
6
+struct packfile_store;
7
+
8
+/*
9
+ * The files object database source uses a combination of loose objects and
10
+ * packfiles. It is the default backend used by Git to store objects.
11
+ */
12
+struct odb_source_files {
13
+ struct odb_source *source;
14
+ struct odb_source_loose *loose;
15
+ struct packfile_store *packed;
16
+};
17
+
18
+/* Allocate and initialize a new object source. */
19
+struct odb_source_files *odb_source_files_new(struct odb_source *source);
20
+
21
+/* Free the object source and release all associated resources. */
22
+void odb_source_files_free(struct odb_source_files *files);
23
+
24
+#endif
odb/source.c
+2
-4
@@ -13,8 +13,7 @@ struct odb_source *odb_source_new(struct object_database *odb,
13
source->odb = odb;
14
source->local = local;
15
source->path = xstrdup(path);
16
- source->loose = odb_source_loose_new(source);
17
- source->packfiles = packfile_store_new(source);
16
+ source->files = odb_source_files_new(source);
17
18
return source;
19
}
@@ -22,7 +21,6 @@ struct odb_source *odb_source_new(struct object_database *odb,
21
void odb_source_free(struct odb_source *source)
22
{
23
free(source->path);
25
- odb_source_loose_free(source->loose);
26
- packfile_store_free(source->packfiles);
24
+ odb_source_files_free(source->files);
25
free(source);
26
}
odb/source.h
+4
-5
@@ -1,6 +1,8 @@
1
#ifndef ODB_SOURCE_H
2
#define ODB_SOURCE_H
3
4
+#include "odb/source-files.h"
5
+
6
/*
7
* The source is the part of the object database that stores the actual
8
* objects. It thus encapsulates the logic to read and write the specific
@@ -19,11 +21,8 @@ struct odb_source {
21
/* Object database that owns this object source. */
22
struct object_database *odb;
23
22
- /* Private state for loose objects. */
23
- struct odb_source_loose *loose;
24
-
25
- /* Should only be accessed directly by packfile.c and midx.c. */
26
- struct packfile_store *packfiles;
24
+ /* The backend used to store objects. */
25
+ struct odb_source_files *files;
26
27
/*
28
* Figure out whether this is the local source of the owning
odb/streaming.c
+1
-1
@@ -187,7 +187,7 @@ 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->packfiles, oid) ||
190
+ if (!packfile_store_read_object_stream(out, source->files->packed, oid) ||
191
!odb_source_loose_read_object_stream(out, source, oid))
192
return 0;
193
}
packfile.c
+8
-8
@@ -363,7 +363,7 @@ static int unuse_one_window(struct object_database *odb)
363
struct pack_window *lru_w = NULL, *lru_l = NULL;
364
365
for (source = odb->sources; source; source = source->next)
366
- for (e = source->packfiles->packs.head; e; e = e->next)
366
+ for (e = source->files->packed->packs.head; e; e = e->next)
367
scan_windows(e->pack, &lru_p, &lru_w, &lru_l);
368
369
if (lru_p) {
@@ -537,7 +537,7 @@ static int close_one_pack(struct repository *r)
537
int accept_windows_inuse = 1;
538
539
for (source = r->objects->sources; source; source = source->next) {
540
- for (e = source->packfiles->packs.head; e; e = e->next) {
540
+ for (e = source->files->packed->packs.head; e; e = e->next) {
541
if (e->pack->pack_fd == -1)
542
continue;
543
find_lru_pack(e->pack, &lru_p, &mru_w, &accept_windows_inuse);
@@ -990,10 +990,10 @@ static void prepare_pack(const char *full_name, size_t full_name_len,
990
size_t base_len = full_name_len;
991
992
if (strip_suffix_mem(full_name, &base_len, ".idx") &&
993
- !(data->source->packfiles->midx &&
994
- midx_contains_pack(data->source->packfiles->midx, file_name))) {
993
+ !(data->source->files->packed->midx &&
994
+ midx_contains_pack(data->source->files->packed->midx, file_name))) {
995
char *trimmed_path = xstrndup(full_name, full_name_len);
996
- packfile_store_load_pack(data->source->packfiles,
996
+ packfile_store_load_pack(data->source->files->packed,
997
trimmed_path, data->source->local);
998
free(trimmed_path);
999
}
@@ -1248,7 +1248,7 @@ const struct packed_git *has_packed_and_bad(struct repository *r,
1248
1249
for (source = r->objects->sources; source; source = source->next) {
1250
struct packfile_list_entry *e;
1251
- for (e = source->packfiles->packs.head; e; e = e->next)
1251
+ for (e = source->files->packed->packs.head; e; e = e->next)
1252
if (oidset_contains(&e->pack->bad_objects, oid))
1253
return e->pack;
1254
}
@@ -2254,7 +2254,7 @@ int has_object_pack(struct repository *r, const struct object_id *oid)
2254
2255
odb_prepare_alternates(r->objects);
2256
for (source = r->objects->sources; source; source = source->next) {
2257
- int ret = find_pack_entry(source->packfiles, oid, &e);
2257
+ int ret = find_pack_entry(source->files->packed, oid, &e);
2258
if (ret)
2259
return ret;
2260
}
@@ -2271,7 +2271,7 @@ int has_object_kept_pack(struct repository *r, const struct object_id *oid,
2271
for (source = r->objects->sources; source; source = source->next) {
2272
struct packed_git **cache;
2273
2274
- cache = packfile_store_get_kept_pack_cache(source->packfiles, flags);
2274
+ cache = packfile_store_get_kept_pack_cache(source->files->packed, flags);
2275
2276
for (; *cache; cache++) {
2277
struct packed_git *p = *cache;
packfile.h
+2
-2
@@ -192,7 +192,7 @@ static inline struct repo_for_each_pack_data repo_for_eack_pack_data_init(struct
192
odb_prepare_alternates(repo->objects);
193
194
for (struct odb_source *source = repo->objects->sources; source; source = source->next) {
195
- struct packfile_list_entry *entry = packfile_store_get_packs(source->packfiles);
195
+ struct packfile_list_entry *entry = packfile_store_get_packs(source->files->packed);
196
if (!entry)
197
continue;
198
data.source = source;
@@ -212,7 +212,7 @@ static inline void repo_for_each_pack_data_next(struct repo_for_each_pack_data *
212
return;
213
214
for (source = data->source->next; source; source = source->next) {
215
- struct packfile_list_entry *entry = packfile_store_get_packs(source->packfiles);
215
+ struct packfile_list_entry *entry = packfile_store_get_packs(source->files->packed);
216
if (!entry)
217
continue;
218
data->source = source;