builtin/repo: add inflated object info to keyvalue structure output

The structure subcommand for git-repo(1) outputs basic count information for objects and references. Extend this output to also provide information regarding total size of inflated objects by object type. For now, object size by object type info is only added to the keyvalue and nul output formats. In a subsequent commit, this info is also added to the table format. 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 3e114496e48e665d2bb9e0c0917e6051d60392ea
3 files changed +39 -1
Documentation/git-repo.adoc
+1
@@ -50,6 +50,7 @@ supported:
50 +
51 * Reference counts categorized by type
52 * Reachable object counts categorized by type
53 +* Total inflated size of reachable objects by type
54
55 +
56 The output format can be chosen through the flag `--format`. Three formats are
builtin/repo.c
+33
@@ -2,6 +2,8 @@
2
3 #include "builtin.h"
4 #include "environment.h"
5 +#include "hex.h"
6 +#include "odb.h"
7 #include "parse-options.h"
8 #include "path-walk.h"
9 #include "progress.h"
@@ -211,6 +213,7 @@ struct object_values {
213
214 struct object_stats {
215 struct object_values type_counts;
216 + struct object_values inflated_sizes;
217 };
218
219 struct repo_structure {
@@ -423,6 +426,15 @@ static void structure_keyvalue_print(struct repo_structure *stats,
426 printf("objects.tags.count%c%" PRIuMAX "%c", key_delim,
427 (uintmax_t)stats->objects.type_counts.tags, value_delim);
428
429 + printf("objects.commits.inflated_size%c%" PRIuMAX "%c", key_delim,
430 + (uintmax_t)stats->objects.inflated_sizes.commits, value_delim);
431 + printf("objects.trees.inflated_size%c%" PRIuMAX "%c", key_delim,
432 + (uintmax_t)stats->objects.inflated_sizes.trees, value_delim);
433 + printf("objects.blobs.inflated_size%c%" PRIuMAX "%c", key_delim,
434 + (uintmax_t)stats->objects.inflated_sizes.blobs, value_delim);
435 + printf("objects.tags.inflated_size%c%" PRIuMAX "%c", key_delim,
436 + (uintmax_t)stats->objects.inflated_sizes.tags, value_delim);
437 +
438 fflush(stdout);
439 }
440
@@ -486,6 +498,7 @@ static void structure_count_references(struct ref_stats *stats,
498 }
499
500 struct count_objects_data {
501 + struct object_database *odb;
502 struct object_stats *stats;
503 struct progress *progress;
504 };
@@ -495,20 +508,39 @@ static int count_objects(const char *path UNUSED, struct oid_array *oids,
508 {
509 struct count_objects_data *data = cb_data;
510 struct object_stats *stats = data->stats;
511 + size_t inflated_total = 0;
512 size_t object_count;
513
514 + for (size_t i = 0; i < oids->nr; i++) {
515 + struct object_info oi = OBJECT_INFO_INIT;
516 + unsigned long inflated;
517 +
518 + oi.sizep = &inflated;
519 +
520 + if (odb_read_object_info_extended(data->odb, &oids->oid[i], &oi,
521 + OBJECT_INFO_SKIP_FETCH_OBJECT |
522 + OBJECT_INFO_QUICK) < 0)
523 + continue;
524 +
525 + inflated_total += inflated;
526 + }
527 +
528 switch (type) {
529 case OBJ_TAG:
530 stats->type_counts.tags += oids->nr;
531 + stats->inflated_sizes.tags += inflated_total;
532 break;
533 case OBJ_COMMIT:
534 stats->type_counts.commits += oids->nr;
535 + stats->inflated_sizes.commits += inflated_total;
536 break;
537 case OBJ_TREE:
538 stats->type_counts.trees += oids->nr;
539 + stats->inflated_sizes.trees += inflated_total;
540 break;
541 case OBJ_BLOB:
542 stats->type_counts.blobs += oids->nr;
543 + stats->inflated_sizes.blobs += inflated_total;
544 break;
545 default:
546 BUG("invalid object type");
@@ -526,6 +558,7 @@ static void structure_count_objects(struct object_stats *stats,
558 {
559 struct path_walk_info info = PATH_WALK_INFO_INIT;
560 struct count_objects_data data = {
561 + .odb = repo->objects,
562 .stats = stats,
563 };
564
t/t1901-repo-structure.sh
+5 -1
@@ -73,7 +73,7 @@ test_expect_success 'repository with references and objects' '
73 )
74 '
75
76 -test_expect_success 'keyvalue and nul format' '
76 +test_expect_success SHA1 'keyvalue and nul format' '
77 test_when_finished "rm -rf repo" &&
78 git init repo &&
79 (
@@ -90,6 +90,10 @@ test_expect_success 'keyvalue and nul format' '
90 objects.trees.count=42
91 objects.blobs.count=42
92 objects.tags.count=1
93 + objects.commits.inflated_size=9225
94 + objects.trees.inflated_size=28554
95 + objects.blobs.inflated_size=453
96 + objects.tags.inflated_size=132
97 EOF
98
99 git repo structure --format=keyvalue >out 2>err &&