odb: introduce `struct odb_for_each_object_options`
The `odb_for_each_object()` function only accepts a bitset of flags. In a subsequent commit we'll want to change object iteration to also support iterating over only those objects that have a specific prefix. While we could of course add the prefix to the function signature, or alternatively introduce a new function, both of these options don't really seem to be that sensible. Instead, introduce a new `struct odb_for_each_object_options` that can be passed to a new `odb_for_each_object_ext()` function. Splice through the options structure into the respective object database sources. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Mar 20, 2026 at 08:07 UTC
cfd575f0a9730712107e4ee6799a37665bcd8204
11 files changed
+71
-34
builtin/cat-file.c
+5
-2
@@ -848,6 +848,9 @@ static void batch_each_object(struct batch_options *opt,
848
.callback = callback,
849
.payload = _payload,
850
};
851
+ struct odb_for_each_object_options opts = {
852
+ .flags = flags,
853
+ };
854
struct bitmap_index *bitmap = NULL;
855
struct odb_source *source;
856
@@ -860,7 +863,7 @@ static void batch_each_object(struct batch_options *opt,
863
odb_prepare_alternates(the_repository->objects);
864
for (source = the_repository->objects->sources; source; source = source->next) {
865
int ret = odb_source_loose_for_each_object(source, NULL, batch_one_object_oi,
863
- &payload, flags);
866
+ &payload, &opts);
867
if (ret)
868
break;
869
}
@@ -884,7 +887,7 @@ static void batch_each_object(struct batch_options *opt,
887
for (source = the_repository->objects->sources; source; source = source->next) {
888
struct odb_source_files *files = odb_source_files_downcast(source);
889
int ret = packfile_store_for_each_object(files->packed, &oi,
887
- batch_one_object_oi, &payload, flags);
890
+ batch_one_object_oi, &payload, &opts);
891
if (ret)
892
break;
893
}
builtin/pack-objects.c
+7
-5
@@ -4344,6 +4344,12 @@ static void add_objects_in_unpacked_packs(void)
4344
{
4345
struct odb_source *source;
4346
time_t mtime;
4347
+ struct odb_for_each_object_options opts = {
4348
+ .flags = ODB_FOR_EACH_OBJECT_PACK_ORDER |
4349
+ ODB_FOR_EACH_OBJECT_LOCAL_ONLY |
4350
+ ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS |
4351
+ ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS,
4352
+ };
4353
struct object_info oi = {
4354
.mtimep = &mtime,
4355
};
@@ -4356,11 +4362,7 @@ static void add_objects_in_unpacked_packs(void)
4362
continue;
4363
4364
if (packfile_store_for_each_object(files->packed, &oi,
4359
- add_object_in_unpacked_pack, NULL,
4360
- ODB_FOR_EACH_OBJECT_PACK_ORDER |
4361
- ODB_FOR_EACH_OBJECT_LOCAL_ONLY |
4362
- ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS |
4363
- ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS))
4365
+ add_object_in_unpacked_pack, NULL, &opts))
4366
die(_("cannot open pack index"));
4367
}
4368
}
commit-graph.c
+4
-1
@@ -1969,6 +1969,9 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
1969
{
1970
struct odb_source *source;
1971
enum object_type type;
1972
+ struct odb_for_each_object_options opts = {
1973
+ .flags = ODB_FOR_EACH_OBJECT_PACK_ORDER,
1974
+ };
1975
struct object_info oi = {
1976
.typep = &type,
1977
};
@@ -1983,7 +1986,7 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
1986
for (source = ctx->r->objects->sources; source; source = source->next) {
1987
struct odb_source_files *files = odb_source_files_downcast(source);
1988
packfile_store_for_each_object(files->packed, &oi, add_packed_commits_oi,
1986
- ctx, ODB_FOR_EACH_OBJECT_PACK_ORDER);
1989
+ ctx, &opts);
1990
}
1991
1992
if (ctx->progress_done < ctx->approx_nr_objects)
object-file.c
+5
-4
@@ -1849,7 +1849,7 @@ int odb_source_loose_for_each_object(struct odb_source *source,
1849
const struct object_info *request,
1850
odb_for_each_object_cb cb,
1851
void *cb_data,
1852
- unsigned flags)
1852
+ const struct odb_for_each_object_options *opts)
1853
{
1854
struct for_each_object_wrapper_data data = {
1855
.source = source,
@@ -1859,9 +1859,9 @@ int odb_source_loose_for_each_object(struct odb_source *source,
1859
};
1860
1861
/* There are no loose promisor objects, so we can return immediately. */
1862
- if ((flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY))
1862
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY))
1863
return 0;
1864
- if ((flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !source->local)
1864
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !source->local)
1865
return 0;
1866
1867
return for_each_loose_file_in_source(source, for_each_object_wrapper_cb,
@@ -1914,9 +1914,10 @@ int odb_source_loose_count_objects(struct odb_source *source,
1914
*out = count * 256;
1915
ret = 0;
1916
} else {
1917
+ struct odb_for_each_object_options opts = { 0 };
1918
*out = 0;
1919
ret = odb_source_loose_for_each_object(source, NULL, count_loose_object,
1919
- out, NULL);
1920
+ out, &opts);
1921
}
1922
1923
out:
object-file.h
+1
-1
@@ -137,7 +137,7 @@ int odb_source_loose_for_each_object(struct odb_source *source,
137
const struct object_info *request,
138
odb_for_each_object_cb cb,
139
void *cb_data,
140
- unsigned flags);
140
+ const struct odb_for_each_object_options *opts);
141
142
/*
143
* Count the number of loose objects in this source.
odb.c
+19
-7
@@ -896,20 +896,20 @@ int odb_freshen_object(struct object_database *odb,
896
return 0;
897
}
898
899
-int odb_for_each_object(struct object_database *odb,
900
- const struct object_info *request,
901
- odb_for_each_object_cb cb,
902
- void *cb_data,
903
- unsigned flags)
899
+int odb_for_each_object_ext(struct object_database *odb,
900
+ const struct object_info *request,
901
+ odb_for_each_object_cb cb,
902
+ void *cb_data,
903
+ const struct odb_for_each_object_options *opts)
904
{
905
int ret;
906
907
odb_prepare_alternates(odb);
908
for (struct odb_source *source = odb->sources; source; source = source->next) {
909
- if (flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY && !source->local)
909
+ if (opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY && !source->local)
910
continue;
911
912
- ret = odb_source_for_each_object(source, request, cb, cb_data, flags);
912
+ ret = odb_source_for_each_object(source, request, cb, cb_data, opts);
913
if (ret)
914
return ret;
915
}
@@ -917,6 +917,18 @@ int odb_for_each_object(struct object_database *odb,
917
return 0;
918
}
919
920
+int odb_for_each_object(struct object_database *odb,
921
+ const struct object_info *request,
922
+ odb_for_each_object_cb cb,
923
+ void *cb_data,
924
+ unsigned flags)
925
+{
926
+ struct odb_for_each_object_options opts = {
927
+ .flags = flags,
928
+ };
929
+ return odb_for_each_object_ext(odb, request, cb, cb_data, &opts);
930
+}
931
+
932
int odb_count_objects(struct object_database *odb,
933
enum odb_count_objects_flags flags,
934
unsigned long *out)
odb.h
+16
@@ -481,6 +481,15 @@ typedef int (*odb_for_each_object_cb)(const struct object_id *oid,
481
struct object_info *oi,
482
void *cb_data);
483
484
+/*
485
+ * Options that can be passed to `odb_for_each_object()` and its
486
+ * backend-specific implementations.
487
+ */
488
+struct odb_for_each_object_options {
489
+ /* A bitfield of `odb_for_each_object_flags`. */
490
+ enum odb_for_each_object_flags flags;
491
+};
492
+
493
/*
494
* Iterate through all objects contained in the object database. Note that
495
* objects may be iterated over multiple times in case they are either stored
@@ -495,6 +504,13 @@ typedef int (*odb_for_each_object_cb)(const struct object_id *oid,
504
* Returns 0 on success, a negative error code in case a failure occurred, or
505
* an arbitrary non-zero error code returned by the callback itself.
506
*/
507
+int odb_for_each_object_ext(struct object_database *odb,
508
+ const struct object_info *request,
509
+ odb_for_each_object_cb cb,
510
+ void *cb_data,
511
+ const struct odb_for_each_object_options *opts);
512
+
513
+/* Same as `odb_for_each_object_ext()` with `opts.flags` set to the given flags. */
514
int odb_for_each_object(struct object_database *odb,
515
const struct object_info *request,
516
odb_for_each_object_cb cb,
odb/source-files.c
+4
-4
@@ -75,18 +75,18 @@ static int odb_source_files_for_each_object(struct odb_source *source,
75
const struct object_info *request,
76
odb_for_each_object_cb cb,
77
void *cb_data,
78
- unsigned flags)
78
+ const struct odb_for_each_object_options *opts)
79
{
80
struct odb_source_files *files = odb_source_files_downcast(source);
81
int ret;
82
83
- if (!(flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) {
84
- ret = odb_source_loose_for_each_object(source, request, cb, cb_data, flags);
83
+ if (!(opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) {
84
+ ret = odb_source_loose_for_each_object(source, request, cb, cb_data, opts);
85
if (ret)
86
return ret;
87
}
88
89
- ret = packfile_store_for_each_object(files->packed, request, cb, cb_data, flags);
89
+ ret = packfile_store_for_each_object(files->packed, request, cb, cb_data, opts);
90
if (ret)
91
return ret;
92
odb/source.h
+3
-3
@@ -140,7 +140,7 @@ struct odb_source {
140
const struct object_info *request,
141
odb_for_each_object_cb cb,
142
void *cb_data,
143
- unsigned flags);
143
+ const struct odb_for_each_object_options *opts);
144
145
/*
146
* This callback is expected to count objects in the given object
@@ -343,9 +343,9 @@ static inline int odb_source_for_each_object(struct odb_source *source,
343
const struct object_info *request,
344
odb_for_each_object_cb cb,
345
void *cb_data,
346
- unsigned flags)
346
+ const struct odb_for_each_object_options *opts)
347
{
348
- return source->for_each_object(source, request, cb, cb_data, flags);
348
+ return source->for_each_object(source, request, cb, cb_data, opts);
349
}
350
351
/*
packfile.c
+6
-6
@@ -2375,7 +2375,7 @@ int packfile_store_for_each_object(struct packfile_store *store,
2375
const struct object_info *request,
2376
odb_for_each_object_cb cb,
2377
void *cb_data,
2378
- unsigned flags)
2378
+ const struct odb_for_each_object_options *opts)
2379
{
2380
struct packfile_store_for_each_object_wrapper_data data = {
2381
.store = store,
@@ -2391,15 +2391,15 @@ int packfile_store_for_each_object(struct packfile_store *store,
2391
for (e = packfile_store_get_packs(store); e; e = e->next) {
2392
struct packed_git *p = e->pack;
2393
2394
- if ((flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
2394
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !p->pack_local)
2395
continue;
2396
- if ((flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY) &&
2396
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY) &&
2397
!p->pack_promisor)
2398
continue;
2399
- if ((flags & ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
2399
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_IN_CORE_KEPT_PACKS) &&
2400
p->pack_keep_in_core)
2401
continue;
2402
- if ((flags & ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
2402
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_SKIP_ON_DISK_KEPT_PACKS) &&
2403
p->pack_keep)
2404
continue;
2405
if (open_pack_index(p)) {
@@ -2408,7 +2408,7 @@ int packfile_store_for_each_object(struct packfile_store *store,
2408
}
2409
2410
ret = for_each_object_in_pack(p, packfile_store_for_each_object_wrapper,
2411
- &data, flags);
2411
+ &data, opts->flags);
2412
if (ret)
2413
goto out;
2414
}
packfile.h
+1
-1
@@ -367,7 +367,7 @@ int packfile_store_for_each_object(struct packfile_store *store,
367
const struct object_info *request,
368
odb_for_each_object_cb cb,
369
void *cb_data,
370
- unsigned flags);
370
+ const struct odb_for_each_object_options *opts);
371
372
/* A hook to report invalid files in pack directory */
373
#define PACKDIR_FILE_PACK 1