object-file: generalize counting objects
Generalize the function introduced in the preceding commit to not only be able to approximate the number of loose objects, but to also provide an accurate count. The behaviour can be toggled via a new flag. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Mar 12, 2026 at 09:42 UTC
2b24db1110150138ac1e09bc60d9ae5245909625
4 files changed
+53
-25
builtin/gc.c
+3
-2
@@ -474,8 +474,9 @@ static int too_many_loose_objects(int limit)
474
int auto_threshold = DIV_ROUND_UP(limit, 256) * 256;
475
unsigned long loose_count;
476
477
- if (odb_source_loose_approximate_object_count(the_repository->objects->sources,
478
- &loose_count) < 0)
477
+ if (odb_source_loose_count_objects(the_repository->objects->sources,
478
+ ODB_COUNT_OBJECTS_APPROXIMATE,
479
+ &loose_count) < 0)
480
return 0;
481
482
return loose_count > auto_threshold;
object-file.c
+38
-21
@@ -1868,40 +1868,57 @@ int odb_source_loose_for_each_object(struct odb_source *source,
1868
NULL, NULL, &data);
1869
}
1870
1871
-int odb_source_loose_approximate_object_count(struct odb_source *source,
1872
- unsigned long *out)
1871
+static int count_loose_object(const struct object_id *oid UNUSED,
1872
+ struct object_info *oi UNUSED,
1873
+ void *payload)
1874
+{
1875
+ unsigned long *count = payload;
1876
+ (*count)++;
1877
+ return 0;
1878
+}
1879
+
1880
+int odb_source_loose_count_objects(struct odb_source *source,
1881
+ enum odb_count_objects_flags flags,
1882
+ unsigned long *out)
1883
{
1884
const unsigned hexsz = source->odb->repo->hash_algo->hexsz - 2;
1875
- unsigned long count = 0;
1876
- struct dirent *ent;
1885
char *path = NULL;
1886
DIR *dir = NULL;
1887
int ret;
1888
1881
- path = xstrfmt("%s/17", source->path);
1889
+ if (flags & ODB_COUNT_OBJECTS_APPROXIMATE) {
1890
+ unsigned long count = 0;
1891
+ struct dirent *ent;
1892
1883
- dir = opendir(path);
1884
- if (!dir) {
1885
- if (errno == ENOENT) {
1886
- *out = 0;
1887
- ret = 0;
1893
+ path = xstrfmt("%s/17", source->path);
1894
+
1895
+ dir = opendir(path);
1896
+ if (!dir) {
1897
+ if (errno == ENOENT) {
1898
+ *out = 0;
1899
+ ret = 0;
1900
+ goto out;
1901
+ }
1902
+
1903
+ ret = error_errno("cannot open object shard '%s'", path);
1904
goto out;
1905
}
1906
1891
- ret = error_errno("cannot open object shard '%s'", path);
1892
- goto out;
1893
- }
1907
+ while ((ent = readdir(dir)) != NULL) {
1908
+ if (strspn(ent->d_name, "0123456789abcdef") != hexsz ||
1909
+ ent->d_name[hexsz] != '\0')
1910
+ continue;
1911
+ count++;
1912
+ }
1913
1895
- while ((ent = readdir(dir)) != NULL) {
1896
- if (strspn(ent->d_name, "0123456789abcdef") != hexsz ||
1897
- ent->d_name[hexsz] != '\0')
1898
- continue;
1899
- count++;
1914
+ *out = count * 256;
1915
+ ret = 0;
1916
+ } else {
1917
+ *out = 0;
1918
+ ret = odb_source_loose_for_each_object(source, NULL, count_loose_object,
1919
+ out, 0);
1920
}
1921
1902
- *out = count * 256;
1903
- ret = 0;
1904
-
1922
out:
1923
if (dir)
1924
closedir(dir);
object-file.h
+3
-2
@@ -149,8 +149,9 @@ int odb_source_loose_for_each_object(struct odb_source *source,
149
*
150
* Returns 0 on success, a negative error code otherwise.
151
*/
152
-int odb_source_loose_approximate_object_count(struct odb_source *source,
153
- unsigned long *out);
152
+int odb_source_loose_count_objects(struct odb_source *source,
153
+ enum odb_count_objects_flags flags,
154
+ unsigned long *out);
155
156
/**
157
* format_object_header() is a thin wrapper around s xsnprintf() that
odb.h
+9
@@ -500,6 +500,15 @@ int odb_for_each_object(struct object_database *odb,
500
void *cb_data,
501
unsigned flags);
502
503
+enum odb_count_objects_flags {
504
+ /*
505
+ * Instead of providing an accurate count, allow the number of objects
506
+ * to be approximated. Details of how this approximation works are
507
+ * subject to the specific source's implementation.
508
+ */
509
+ ODB_COUNT_OBJECTS_APPROXIMATE = (1 << 0),
510
+};
511
+
512
enum {
513
/*
514
* By default, `odb_write_object()` does not actually write anything