builtin/repo: add disk size info to keyvalue stucture output

Similar to a prior commit, extend the keyvalue and nul output formats of the git-repo(1) structure command to additionally provide info regarding total object disk sizes by object type. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Justin Tobler committed Dec 17, 2025 at 11:54 UTC 67cecc693f511321b9d96eead24fd42e6a5c0cdc
3 files changed +29 -1
Documentation/git-repo.adoc
+1
@@ -51,6 +51,7 @@ supported:
51 * Reference counts categorized by type
52 * Reachable object counts categorized by type
53 * Total inflated size of reachable objects by type
54 +* Total disk size of reachable objects by type
55
56 +
57 The output format can be chosen through the flag `--format`. Three formats are
builtin/repo.c
+18
@@ -214,6 +214,7 @@ struct object_values {
214 struct object_stats {
215 struct object_values type_counts;
216 struct object_values inflated_sizes;
217 + struct object_values disk_sizes;
218 };
219
220 struct repo_structure {
@@ -462,6 +463,15 @@ static void structure_keyvalue_print(struct repo_structure *stats,
463 printf("objects.tags.inflated_size%c%" PRIuMAX "%c", key_delim,
464 (uintmax_t)stats->objects.inflated_sizes.tags, value_delim);
465
466 + printf("objects.commits.disk_size%c%" PRIuMAX "%c", key_delim,
467 + (uintmax_t)stats->objects.disk_sizes.commits, value_delim);
468 + printf("objects.trees.disk_size%c%" PRIuMAX "%c", key_delim,
469 + (uintmax_t)stats->objects.disk_sizes.trees, value_delim);
470 + printf("objects.blobs.disk_size%c%" PRIuMAX "%c", key_delim,
471 + (uintmax_t)stats->objects.disk_sizes.blobs, value_delim);
472 + printf("objects.tags.disk_size%c%" PRIuMAX "%c", key_delim,
473 + (uintmax_t)stats->objects.disk_sizes.tags, value_delim);
474 +
475 fflush(stdout);
476 }
477
@@ -536,13 +546,16 @@ static int count_objects(const char *path UNUSED, struct oid_array *oids,
546 struct count_objects_data *data = cb_data;
547 struct object_stats *stats = data->stats;
548 size_t inflated_total = 0;
549 + size_t disk_total = 0;
550 size_t object_count;
551
552 for (size_t i = 0; i < oids->nr; i++) {
553 struct object_info oi = OBJECT_INFO_INIT;
554 unsigned long inflated;
555 + off_t disk;
556
557 oi.sizep = &inflated;
558 + oi.disk_sizep = &disk;
559
560 if (odb_read_object_info_extended(data->odb, &oids->oid[i], &oi,
561 OBJECT_INFO_SKIP_FETCH_OBJECT |
@@ -550,24 +563,29 @@ static int count_objects(const char *path UNUSED, struct oid_array *oids,
563 continue;
564
565 inflated_total += inflated;
566 + disk_total += disk;
567 }
568
569 switch (type) {
570 case OBJ_TAG:
571 stats->type_counts.tags += oids->nr;
572 stats->inflated_sizes.tags += inflated_total;
573 + stats->disk_sizes.tags += disk_total;
574 break;
575 case OBJ_COMMIT:
576 stats->type_counts.commits += oids->nr;
577 stats->inflated_sizes.commits += inflated_total;
578 + stats->disk_sizes.commits += disk_total;
579 break;
580 case OBJ_TREE:
581 stats->type_counts.trees += oids->nr;
582 stats->inflated_sizes.trees += inflated_total;
583 + stats->disk_sizes.trees += disk_total;
584 break;
585 case OBJ_BLOB:
586 stats->type_counts.blobs += oids->nr;
587 stats->inflated_sizes.blobs += inflated_total;
588 + stats->disk_sizes.blobs += disk_total;
589 break;
590 default:
591 BUG("invalid object type");
t/t1901-repo-structure.sh
+10 -1
@@ -4,6 +4,11 @@ test_description='test git repo structure'
4
5 . ./test-lib.sh
6
7 +object_type_disk_usage() {
8 + git rev-list --all --objects --disk-usage --filter=object:type=$1 \
9 + --filter-provided-objects
10 +}
11 +
12 test_expect_success 'empty repository' '
13 test_when_finished "rm -rf repo" &&
14 git init repo &&
@@ -91,7 +96,7 @@ test_expect_success SHA1 'keyvalue and nul format' '
96 test_commit_bulk 42 &&
97 git tag -a foo -m bar &&
98
94 - cat >expect <<-\EOF &&
99 + cat >expect <<-EOF &&
100 references.branches.count=1
101 references.tags.count=1
102 references.remotes.count=0
@@ -104,6 +109,10 @@ test_expect_success SHA1 'keyvalue and nul format' '
109 objects.trees.inflated_size=28554
110 objects.blobs.inflated_size=453
111 objects.tags.inflated_size=132
112 + objects.commits.disk_size=$(object_type_disk_usage commit)
113 + objects.trees.disk_size=$(object_type_disk_usage tree)
114 + objects.blobs.disk_size=$(object_type_disk_usage blob)
115 + objects.tags.disk_size=$(object_type_disk_usage tag)
116 EOF
117
118 git repo structure --format=keyvalue >out 2>err &&