odb/source-loose: wire up `for_each_object()` callback
Move `odb_source_loose_for_each_object()` and its associated helpers from "object-file.c" into "odb/source-loose.c" and wire it up as the `for_each_object()` callback of the loose source. Again, as in the preceding commit, we are forced to expose a couple of functions from "object-file.c" that are now used by both subsystems. 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
e4f1d9ba5714957389bee87dd5f9fedb69d8a764
5 files changed
+297
-305
builtin/cat-file.c
+3
-2
@@ -862,8 +862,9 @@ static void batch_each_object(struct batch_options *opt,
862
*/
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,
866
- &payload, &opts);
865
+ struct odb_source_files *files = odb_source_files_downcast(source);
866
+ int ret = odb_source_for_each_object(&files->loose->base, NULL, batch_one_object_oi,
867
+ &payload, &opts);
868
if (ret)
869
break;
870
}
object-file.c
+16
-283
@@ -22,7 +22,6 @@
22
#include "odb.h"
23
#include "odb/streaming.h"
24
#include "odb/transaction.h"
25
-#include "oidtree.h"
25
#include "pack.h"
26
#include "packfile.h"
27
#include "path.h"
@@ -31,12 +30,6 @@
30
#include "tempfile.h"
31
#include "tmp-objdir.h"
32
34
-/* The maximum size for an object header. */
35
-#define MAX_HEADER_LEN 32
36
-
37
-static struct oidtree *odb_source_loose_cache(struct odb_source *source,
38
- const struct object_id *oid);
39
-
33
static int get_conv_flags(unsigned flags)
34
{
35
if (flags & INDEX_RENORMALIZE)
@@ -164,12 +157,6 @@ int stream_object_signature(struct repository *r,
157
return !oideq(oid, &real_oid) ? -1 : 0;
158
}
159
167
-static int quick_has_loose(struct odb_source_loose *loose,
168
- const struct object_id *oid)
169
-{
170
- return !!oidtree_contains(odb_source_loose_cache(&loose->files->base, oid), oid);
171
-}
172
-
160
/*
161
* Map and close the given loose object fd. The path argument is used for
162
* error reporting.
@@ -227,9 +214,9 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
214
return ULHR_TOO_LONG;
215
}
216
230
-static void *unpack_loose_rest(git_zstream *stream,
231
- void *buffer, unsigned long size,
232
- const struct object_id *oid)
217
+void *unpack_loose_rest(git_zstream *stream,
218
+ void *buffer, unsigned long size,
219
+ const struct object_id *oid)
220
{
221
size_t bytes = strlen(buffer) + 1, n;
222
unsigned char *buf = xmallocz(size);
@@ -343,149 +330,6 @@ int parse_loose_header(const char *hdr, struct object_info *oi)
330
return 0;
331
}
332
346
-int read_object_info_from_path(struct odb_source_loose *loose,
347
- const char *path,
348
- const struct object_id *oid,
349
- struct object_info *oi,
350
- enum object_info_flags flags)
351
-{
352
- int ret;
353
- int fd;
354
- unsigned long mapsize;
355
- void *map = NULL;
356
- git_zstream stream, *stream_to_end = NULL;
357
- char hdr[MAX_HEADER_LEN];
358
- unsigned long size_scratch;
359
- enum object_type type_scratch;
360
- struct stat st;
361
-
362
- /*
363
- * If we don't care about type or size, then we don't
364
- * need to look inside the object at all. Note that we
365
- * do not optimize out the stat call, even if the
366
- * caller doesn't care about the disk-size, since our
367
- * return value implicitly indicates whether the
368
- * object even exists.
369
- */
370
- if (!oi || (!oi->typep && !oi->sizep && !oi->contentp)) {
371
- struct stat st;
372
-
373
- if ((!oi || (!oi->disk_sizep && !oi->mtimep)) && (flags & OBJECT_INFO_QUICK)) {
374
- ret = quick_has_loose(loose, oid) ? 0 : -1;
375
- goto out;
376
- }
377
-
378
- if (lstat(path, &st) < 0) {
379
- ret = -1;
380
- goto out;
381
- }
382
-
383
- if (oi) {
384
- if (oi->disk_sizep)
385
- *oi->disk_sizep = st.st_size;
386
- if (oi->mtimep)
387
- *oi->mtimep = st.st_mtime;
388
- }
389
-
390
- ret = 0;
391
- goto out;
392
- }
393
-
394
- fd = git_open(path);
395
- if (fd < 0) {
396
- if (errno != ENOENT)
397
- error_errno(_("unable to open loose object %s"), oid_to_hex(oid));
398
- ret = -1;
399
- goto out;
400
- }
401
-
402
- if (fstat(fd, &st)) {
403
- close(fd);
404
- ret = -1;
405
- goto out;
406
- }
407
-
408
- mapsize = xsize_t(st.st_size);
409
- if (!mapsize) {
410
- close(fd);
411
- ret = error(_("object file %s is empty"), path);
412
- goto out;
413
- }
414
-
415
- map = xmmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
416
- close(fd);
417
- if (!map) {
418
- ret = -1;
419
- goto out;
420
- }
421
-
422
- if (oi->disk_sizep)
423
- *oi->disk_sizep = mapsize;
424
- if (oi->mtimep)
425
- *oi->mtimep = st.st_mtime;
426
-
427
- stream_to_end = &stream;
428
-
429
- switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr))) {
430
- case ULHR_OK:
431
- if (!oi->sizep)
432
- oi->sizep = &size_scratch;
433
- if (!oi->typep)
434
- oi->typep = &type_scratch;
435
-
436
- if (parse_loose_header(hdr, oi) < 0) {
437
- ret = error(_("unable to parse %s header"), oid_to_hex(oid));
438
- goto corrupt;
439
- }
440
-
441
- if (*oi->typep < 0)
442
- die(_("invalid object type"));
443
-
444
- if (oi->contentp) {
445
- *oi->contentp = unpack_loose_rest(&stream, hdr, *oi->sizep, oid);
446
- if (!*oi->contentp) {
447
- ret = -1;
448
- goto corrupt;
449
- }
450
- }
451
-
452
- break;
453
- case ULHR_BAD:
454
- ret = error(_("unable to unpack %s header"),
455
- oid_to_hex(oid));
456
- goto corrupt;
457
- case ULHR_TOO_LONG:
458
- ret = error(_("header for %s too long, exceeds %d bytes"),
459
- oid_to_hex(oid), MAX_HEADER_LEN);
460
- goto corrupt;
461
- }
462
-
463
- ret = 0;
464
-
465
-corrupt:
466
- if (ret && (flags & OBJECT_INFO_DIE_IF_CORRUPT))
467
- die(_("loose object %s (stored in %s) is corrupt"),
468
- oid_to_hex(oid), path);
469
-
470
-out:
471
- if (stream_to_end)
472
- git_inflate_end(stream_to_end);
473
- if (map)
474
- munmap(map, mapsize);
475
- if (oi) {
476
- if (oi->sizep == &size_scratch)
477
- oi->sizep = NULL;
478
- if (oi->typep == &type_scratch)
479
- oi->typep = NULL;
480
- if (oi->delta_base_oid)
481
- oidclr(oi->delta_base_oid, loose->base.odb->repo->hash_algo);
482
- if (!ret)
483
- oi->whence = OI_LOOSE;
484
- }
485
-
486
- return ret;
487
-}
488
-
333
static void hash_object_body(const struct git_hash_algo *algo, struct git_hash_ctx *c,
334
const void *buf, unsigned long len,
335
struct object_id *oid,
@@ -1667,13 +1511,13 @@ int read_pack_header(int fd, struct pack_header *header)
1511
return 0;
1512
}
1513
1670
-static int for_each_file_in_obj_subdir(unsigned int subdir_nr,
1671
- struct strbuf *path,
1672
- const struct git_hash_algo *algop,
1673
- each_loose_object_fn obj_cb,
1674
- each_loose_cruft_fn cruft_cb,
1675
- each_loose_subdir_fn subdir_cb,
1676
- void *data)
1514
+int for_each_file_in_obj_subdir(unsigned int subdir_nr,
1515
+ struct strbuf *path,
1516
+ const struct git_hash_algo *algop,
1517
+ each_loose_object_fn obj_cb,
1518
+ each_loose_cruft_fn cruft_cb,
1519
+ each_loose_subdir_fn subdir_cb,
1520
+ void *data)
1521
{
1522
size_t origlen, baselen;
1523
DIR *dir;
@@ -1758,78 +1602,6 @@ int for_each_loose_file_in_source(struct odb_source *source,
1602
return r;
1603
}
1604
1761
-struct for_each_object_wrapper_data {
1762
- struct odb_source_loose *loose;
1763
- const struct object_info *request;
1764
- odb_for_each_object_cb cb;
1765
- void *cb_data;
1766
-};
1767
-
1768
-static int for_each_object_wrapper_cb(const struct object_id *oid,
1769
- const char *path,
1770
- void *cb_data)
1771
-{
1772
- struct for_each_object_wrapper_data *data = cb_data;
1773
-
1774
- if (data->request) {
1775
- struct object_info oi = *data->request;
1776
-
1777
- if (read_object_info_from_path(data->loose, path, oid, &oi, 0) < 0)
1778
- return -1;
1779
-
1780
- return data->cb(oid, &oi, data->cb_data);
1781
- } else {
1782
- return data->cb(oid, NULL, data->cb_data);
1783
- }
1784
-}
1785
-
1786
-static int for_each_prefixed_object_wrapper_cb(const struct object_id *oid,
1787
- void *node_data UNUSED,
1788
- void *cb_data)
1789
-{
1790
- struct for_each_object_wrapper_data *data = cb_data;
1791
- if (data->request) {
1792
- struct object_info oi = *data->request;
1793
-
1794
- if (odb_source_read_object_info(&data->loose->base,
1795
- oid, &oi, 0) < 0)
1796
- return -1;
1797
-
1798
- return data->cb(oid, &oi, data->cb_data);
1799
- } else {
1800
- return data->cb(oid, NULL, data->cb_data);
1801
- }
1802
-}
1803
-
1804
-int odb_source_loose_for_each_object(struct odb_source *source,
1805
- const struct object_info *request,
1806
- odb_for_each_object_cb cb,
1807
- void *cb_data,
1808
- const struct odb_for_each_object_options *opts)
1809
-{
1810
- struct odb_source_files *files = odb_source_files_downcast(source);
1811
- struct for_each_object_wrapper_data data = {
1812
- .loose = files->loose,
1813
- .request = request,
1814
- .cb = cb,
1815
- .cb_data = cb_data,
1816
- };
1817
-
1818
- /* There are no loose promisor objects, so we can return immediately. */
1819
- if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY))
1820
- return 0;
1821
- if ((opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !source->local)
1822
- return 0;
1823
-
1824
- if (opts->prefix)
1825
- return oidtree_each(odb_source_loose_cache(source, opts->prefix),
1826
- opts->prefix, opts->prefix_hex_len,
1827
- for_each_prefixed_object_wrapper_cb, &data);
1828
-
1829
- return for_each_loose_file_in_source(source, for_each_object_wrapper_cb,
1830
- NULL, NULL, &data);
1831
-}
1832
-
1605
static int count_loose_object(const struct object_id *oid UNUSED,
1606
struct object_info *oi UNUSED,
1607
void *payload)
@@ -1843,6 +1615,7 @@ int odb_source_loose_count_objects(struct odb_source *source,
1615
enum odb_count_objects_flags flags,
1616
unsigned long *out)
1617
{
1618
+ struct odb_source_files *files = odb_source_files_downcast(source);
1619
const unsigned hexsz = source->odb->repo->hash_algo->hexsz - 2;
1620
char *path = NULL;
1621
DIR *dir = NULL;
@@ -1878,8 +1651,8 @@ int odb_source_loose_count_objects(struct odb_source *source,
1651
} else {
1652
struct odb_for_each_object_options opts = { 0 };
1653
*out = 0;
1881
- ret = odb_source_loose_for_each_object(source, NULL, count_loose_object,
1882
- out, &opts);
1654
+ ret = odb_source_for_each_object(&files->loose->base, NULL, count_loose_object,
1655
+ out, &opts);
1656
}
1657
1658
out:
@@ -1910,6 +1683,7 @@ int odb_source_loose_find_abbrev_len(struct odb_source *source,
1683
unsigned min_len,
1684
unsigned *out)
1685
{
1686
+ struct odb_source_files *files = odb_source_files_downcast(source);
1687
struct odb_for_each_object_options opts = {
1688
.prefix = oid,
1689
.prefix_hex_len = min_len,
@@ -1920,54 +1694,13 @@ int odb_source_loose_find_abbrev_len(struct odb_source *source,
1694
};
1695
int ret;
1696
1923
- ret = odb_source_loose_for_each_object(source, NULL, find_abbrev_len_cb,
1924
- &data, &opts);
1697
+ ret = odb_source_for_each_object(&files->loose->base, NULL, find_abbrev_len_cb,
1698
+ &data, &opts);
1699
*out = data.len;
1700
1701
return ret;
1702
}
1703
1930
-static int append_loose_object(const struct object_id *oid,
1931
- const char *path UNUSED,
1932
- void *data)
1933
-{
1934
- oidtree_insert(data, oid, NULL);
1935
- return 0;
1936
-}
1937
-
1938
-static struct oidtree *odb_source_loose_cache(struct odb_source *source,
1939
- const struct object_id *oid)
1940
-{
1941
- struct odb_source_files *files = odb_source_files_downcast(source);
1942
- int subdir_nr = oid->hash[0];
1943
- struct strbuf buf = STRBUF_INIT;
1944
- size_t word_bits = bitsizeof(files->loose->subdir_seen[0]);
1945
- size_t word_index = subdir_nr / word_bits;
1946
- size_t mask = (size_t)1u << (subdir_nr % word_bits);
1947
- uint32_t *bitmap;
1948
-
1949
- if (subdir_nr < 0 ||
1950
- (size_t) subdir_nr >= bitsizeof(files->loose->subdir_seen))
1951
- BUG("subdir_nr out of range");
1952
-
1953
- bitmap = &files->loose->subdir_seen[word_index];
1954
- if (*bitmap & mask)
1955
- return files->loose->cache;
1956
- if (!files->loose->cache) {
1957
- ALLOC_ARRAY(files->loose->cache, 1);
1958
- oidtree_init(files->loose->cache);
1959
- }
1960
- strbuf_addstr(&buf, source->path);
1961
- for_each_file_in_obj_subdir(subdir_nr, &buf,
1962
- source->odb->repo->hash_algo,
1963
- append_loose_object,
1964
- NULL, NULL,
1965
- files->loose->cache);
1966
- *bitmap |= mask;
1967
- strbuf_release(&buf);
1968
- return files->loose->cache;
1969
-}
1970
-
1704
static int check_stream_oid(git_zstream *stream,
1705
const char *hdr,
1706
unsigned long size,
object-file.h
+13
-19
@@ -6,6 +6,9 @@
6
#include "odb.h"
7
#include "odb/source-loose.h"
8
9
+/* The maximum size for an object header. */
10
+#define MAX_HEADER_LEN 32
11
+
12
struct index_state;
13
14
enum {
@@ -85,19 +88,13 @@ int for_each_loose_file_in_source(struct odb_source *source,
88
each_loose_cruft_fn cruft_cb,
89
each_loose_subdir_fn subdir_cb,
90
void *data);
88
-
89
-/*
90
- * Iterate through all loose objects in the given object database source and
91
- * invoke the callback function for each of them. If an object info request is
92
- * given, then the object info will be read for every individual object and
93
- * passed to the callback as if `odb_source_loose_read_object_info()` was
94
- * called for the object.
95
- */
96
-int odb_source_loose_for_each_object(struct odb_source *source,
97
- const struct object_info *request,
98
- odb_for_each_object_cb cb,
99
- void *cb_data,
100
- const struct odb_for_each_object_options *opts);
91
+int for_each_file_in_obj_subdir(unsigned int subdir_nr,
92
+ struct strbuf *path,
93
+ const struct git_hash_algo *algop,
94
+ each_loose_object_fn obj_cb,
95
+ each_loose_cruft_fn cruft_cb,
96
+ each_loose_subdir_fn subdir_cb,
97
+ void *data);
98
99
/*
100
* Count the number of loose objects in this source.
@@ -188,12 +185,6 @@ int read_loose_object(struct repository *repo,
185
void **contents,
186
struct object_info *oi);
187
191
-int read_object_info_from_path(struct odb_source_loose *loose,
192
- const char *path,
193
- const struct object_id *oid,
194
- struct object_info *oi,
195
- enum object_info_flags flags);
196
-
188
enum unpack_loose_header_result {
189
ULHR_OK,
190
ULHR_BAD,
@@ -217,6 +208,9 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
208
unsigned long mapsize,
209
void *buffer,
210
unsigned long bufsiz);
211
+void *unpack_loose_rest(git_zstream *stream,
212
+ void *buffer, unsigned long size,
213
+ const struct object_id *oid);
214
215
int parse_loose_header(const char *hdr, struct object_info *oi);
216
odb/source-files.c
+1
-1
@@ -82,7 +82,7 @@ static int odb_source_files_for_each_object(struct odb_source *source,
82
int ret;
83
84
if (!(opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY)) {
85
- ret = odb_source_loose_for_each_object(source, request, cb, cb_data, opts);
85
+ ret = odb_source_for_each_object(&files->loose->base, request, cb, cb_data, opts);
86
if (ret)
87
return ret;
88
}
odb/source-loose.c
+264
@@ -2,6 +2,7 @@
2
#include "abspath.h"
3
#include "chdir-notify.h"
4
#include "gettext.h"
5
+#include "hex.h"
6
#include "loose.h"
7
#include "object-file.h"
8
#include "odb.h"
@@ -9,8 +10,198 @@
10
#include "odb/source-loose.h"
11
#include "odb/streaming.h"
12
#include "oidtree.h"
13
+#include "repository.h"
14
#include "strbuf.h"
15
16
+static int append_loose_object(const struct object_id *oid,
17
+ const char *path UNUSED,
18
+ void *data)
19
+{
20
+ oidtree_insert(data, oid, NULL);
21
+ return 0;
22
+}
23
+
24
+static struct oidtree *odb_source_loose_cache(struct odb_source_loose *loose,
25
+ const struct object_id *oid)
26
+{
27
+ int subdir_nr = oid->hash[0];
28
+ struct strbuf buf = STRBUF_INIT;
29
+ size_t word_bits = bitsizeof(loose->subdir_seen[0]);
30
+ size_t word_index = subdir_nr / word_bits;
31
+ size_t mask = (size_t)1u << (subdir_nr % word_bits);
32
+ uint32_t *bitmap;
33
+
34
+ if (subdir_nr < 0 ||
35
+ (size_t) subdir_nr >= bitsizeof(loose->subdir_seen))
36
+ BUG("subdir_nr out of range");
37
+
38
+ bitmap = &loose->subdir_seen[word_index];
39
+ if (*bitmap & mask)
40
+ return loose->cache;
41
+ if (!loose->cache) {
42
+ ALLOC_ARRAY(loose->cache, 1);
43
+ oidtree_init(loose->cache);
44
+ }
45
+ strbuf_addstr(&buf, loose->base.path);
46
+ for_each_file_in_obj_subdir(subdir_nr, &buf,
47
+ loose->base.odb->repo->hash_algo,
48
+ append_loose_object,
49
+ NULL, NULL,
50
+ loose->cache);
51
+ *bitmap |= mask;
52
+ strbuf_release(&buf);
53
+ return loose->cache;
54
+}
55
+
56
+static int quick_has_loose(struct odb_source_loose *loose,
57
+ const struct object_id *oid)
58
+{
59
+ return !!oidtree_contains(odb_source_loose_cache(loose, oid), oid);
60
+}
61
+
62
+static int read_object_info_from_path(struct odb_source_loose *loose,
63
+ const char *path,
64
+ const struct object_id *oid,
65
+ struct object_info *oi,
66
+ enum object_info_flags flags)
67
+{
68
+ int ret;
69
+ int fd;
70
+ unsigned long mapsize;
71
+ void *map = NULL;
72
+ git_zstream stream, *stream_to_end = NULL;
73
+ char hdr[MAX_HEADER_LEN];
74
+ unsigned long size_scratch;
75
+ enum object_type type_scratch;
76
+ struct stat st;
77
+
78
+ /*
79
+ * If we don't care about type or size, then we don't
80
+ * need to look inside the object at all. Note that we
81
+ * do not optimize out the stat call, even if the
82
+ * caller doesn't care about the disk-size, since our
83
+ * return value implicitly indicates whether the
84
+ * object even exists.
85
+ */
86
+ if (!oi || (!oi->typep && !oi->sizep && !oi->contentp)) {
87
+ struct stat st;
88
+
89
+ if ((!oi || (!oi->disk_sizep && !oi->mtimep)) && (flags & OBJECT_INFO_QUICK)) {
90
+ ret = quick_has_loose(loose, oid) ? 0 : -1;
91
+ goto out;
92
+ }
93
+
94
+ if (lstat(path, &st) < 0) {
95
+ ret = -1;
96
+ goto out;
97
+ }
98
+
99
+ if (oi) {
100
+ if (oi->disk_sizep)
101
+ *oi->disk_sizep = st.st_size;
102
+ if (oi->mtimep)
103
+ *oi->mtimep = st.st_mtime;
104
+ }
105
+
106
+ ret = 0;
107
+ goto out;
108
+ }
109
+
110
+ fd = git_open(path);
111
+ if (fd < 0) {
112
+ if (errno != ENOENT)
113
+ error_errno(_("unable to open loose object %s"), oid_to_hex(oid));
114
+ ret = -1;
115
+ goto out;
116
+ }
117
+
118
+ if (fstat(fd, &st)) {
119
+ close(fd);
120
+ ret = -1;
121
+ goto out;
122
+ }
123
+
124
+ mapsize = xsize_t(st.st_size);
125
+ if (!mapsize) {
126
+ close(fd);
127
+ ret = error(_("object file %s is empty"), path);
128
+ goto out;
129
+ }
130
+
131
+ map = xmmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
132
+ close(fd);
133
+ if (!map) {
134
+ ret = -1;
135
+ goto out;
136
+ }
137
+
138
+ if (oi->disk_sizep)
139
+ *oi->disk_sizep = mapsize;
140
+ if (oi->mtimep)
141
+ *oi->mtimep = st.st_mtime;
142
+
143
+ stream_to_end = &stream;
144
+
145
+ switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr))) {
146
+ case ULHR_OK:
147
+ if (!oi->sizep)
148
+ oi->sizep = &size_scratch;
149
+ if (!oi->typep)
150
+ oi->typep = &type_scratch;
151
+
152
+ if (parse_loose_header(hdr, oi) < 0) {
153
+ ret = error(_("unable to parse %s header"), oid_to_hex(oid));
154
+ goto corrupt;
155
+ }
156
+
157
+ if (*oi->typep < 0)
158
+ die(_("invalid object type"));
159
+
160
+ if (oi->contentp) {
161
+ *oi->contentp = unpack_loose_rest(&stream, hdr, *oi->sizep, oid);
162
+ if (!*oi->contentp) {
163
+ ret = -1;
164
+ goto corrupt;
165
+ }
166
+ }
167
+
168
+ break;
169
+ case ULHR_BAD:
170
+ ret = error(_("unable to unpack %s header"),
171
+ oid_to_hex(oid));
172
+ goto corrupt;
173
+ case ULHR_TOO_LONG:
174
+ ret = error(_("header for %s too long, exceeds %d bytes"),
175
+ oid_to_hex(oid), MAX_HEADER_LEN);
176
+ goto corrupt;
177
+ }
178
+
179
+ ret = 0;
180
+
181
+corrupt:
182
+ if (ret && (flags & OBJECT_INFO_DIE_IF_CORRUPT))
183
+ die(_("loose object %s (stored in %s) is corrupt"),
184
+ oid_to_hex(oid), path);
185
+
186
+out:
187
+ if (stream_to_end)
188
+ git_inflate_end(stream_to_end);
189
+ if (map)
190
+ munmap(map, mapsize);
191
+ if (oi) {
192
+ if (oi->sizep == &size_scratch)
193
+ oi->sizep = NULL;
194
+ if (oi->typep == &type_scratch)
195
+ oi->typep = NULL;
196
+ if (oi->delta_base_oid)
197
+ oidclr(oi->delta_base_oid, loose->base.odb->repo->hash_algo);
198
+ if (!ret)
199
+ oi->whence = OI_LOOSE;
200
+ }
201
+
202
+ return ret;
203
+}
204
+
205
static int odb_source_loose_read_object_info(struct odb_source *source,
206
const struct object_id *oid,
207
struct object_info *oi,
@@ -218,6 +409,78 @@ error:
409
return -1;
410
}
411
412
+struct for_each_object_wrapper_data {
413
+ struct odb_source_loose *loose;
414
+ const struct object_info *request;
415
+ odb_for_each_object_cb cb;
416
+ void *cb_data;
417
+};
418
+
419
+static int for_each_object_wrapper_cb(const struct object_id *oid,
420
+ const char *path,
421
+ void *cb_data)
422
+{
423
+ struct for_each_object_wrapper_data *data = cb_data;
424
+
425
+ if (data->request) {
426
+ struct object_info oi = *data->request;
427
+
428
+ if (read_object_info_from_path(data->loose, path, oid, &oi, 0) < 0)
429
+ return -1;
430
+
431
+ return data->cb(oid, &oi, data->cb_data);
432
+ } else {
433
+ return data->cb(oid, NULL, data->cb_data);
434
+ }
435
+}
436
+
437
+static int for_each_prefixed_object_wrapper_cb(const struct object_id *oid,
438
+ void *node_data UNUSED,
439
+ void *cb_data)
440
+{
441
+ struct for_each_object_wrapper_data *data = cb_data;
442
+ if (data->request) {
443
+ struct object_info oi = *data->request;
444
+
445
+ if (odb_source_read_object_info(&data->loose->base,
446
+ oid, &oi, 0) < 0)
447
+ return -1;
448
+
449
+ return data->cb(oid, &oi, data->cb_data);
450
+ } else {
451
+ return data->cb(oid, NULL, data->cb_data);
452
+ }
453
+}
454
+
455
+static int odb_source_loose_for_each_object(struct odb_source *source,
456
+ const struct object_info *request,
457
+ odb_for_each_object_cb cb,
458
+ void *cb_data,
459
+ const struct odb_for_each_object_options *opts)
460
+{
461
+ struct odb_source_loose *loose = odb_source_loose_downcast(source);
462
+ struct for_each_object_wrapper_data data = {
463
+ .loose = loose,
464
+ .request = request,
465
+ .cb = cb,
466
+ .cb_data = cb_data,
467
+ };
468
+
469
+ /* There are no loose promisor objects, so we can return immediately. */
470
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_PROMISOR_ONLY))
471
+ return 0;
472
+ if ((opts->flags & ODB_FOR_EACH_OBJECT_LOCAL_ONLY) && !source->local)
473
+ return 0;
474
+
475
+ if (opts->prefix)
476
+ return oidtree_each(odb_source_loose_cache(loose, opts->prefix),
477
+ opts->prefix, opts->prefix_hex_len,
478
+ for_each_prefixed_object_wrapper_cb, &data);
479
+
480
+ return for_each_loose_file_in_source(source, for_each_object_wrapper_cb,
481
+ NULL, NULL, &data);
482
+}
483
+
484
static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
485
{
486
oidtree_clear(loose->cache);
@@ -273,6 +536,7 @@ struct odb_source_loose *odb_source_loose_new(struct odb_source_files *files)
536
loose->base.reprepare = odb_source_loose_reprepare;
537
loose->base.read_object_info = odb_source_loose_read_object_info;
538
loose->base.read_object_stream = odb_source_loose_read_object_stream;
539
+ loose->base.for_each_object = odb_source_loose_for_each_object;
540
541
if (!is_absolute_path(loose->base.path))
542
chdir_notify_register(NULL, odb_source_loose_reparent, loose);