]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/repo: add inflated object info to keyvalue structure output
authorJustin Tobler <jltobler@gmail.com>
Wed, 17 Dec 2025 17:54:01 +0000 (11:54 -0600)
committerJunio C Hamano <gitster@pobox.com>
Thu, 18 Dec 2025 00:02:31 +0000 (09:02 +0900)
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>
Documentation/git-repo.adoc
builtin/repo.c
t/t1901-repo-structure.sh

index 70f0a6d2e472917e160cacedc5a013cc603d0599..287eee4b93de5a9b52e53edec14ec558b866df18 100644 (file)
@@ -50,6 +50,7 @@ supported:
 +
 * Reference counts categorized by type
 * Reachable object counts categorized by type
+* Total inflated size of reachable objects by type
 
 +
 The output format can be chosen through the flag `--format`. Three formats are
index 9c61bc3e173a940a28b45c1c3268194efe3c1664..8da321a3866077c3fe361b756dbb0727a389897f 100644 (file)
@@ -2,6 +2,8 @@
 
 #include "builtin.h"
 #include "environment.h"
+#include "hex.h"
+#include "odb.h"
 #include "parse-options.h"
 #include "path-walk.h"
 #include "progress.h"
@@ -211,6 +213,7 @@ struct object_values {
 
 struct object_stats {
        struct object_values type_counts;
+       struct object_values inflated_sizes;
 };
 
 struct repo_structure {
@@ -423,6 +426,15 @@ static void structure_keyvalue_print(struct repo_structure *stats,
        printf("objects.tags.count%c%" PRIuMAX "%c", key_delim,
               (uintmax_t)stats->objects.type_counts.tags, value_delim);
 
+       printf("objects.commits.inflated_size%c%" PRIuMAX "%c", key_delim,
+              (uintmax_t)stats->objects.inflated_sizes.commits, value_delim);
+       printf("objects.trees.inflated_size%c%" PRIuMAX "%c", key_delim,
+              (uintmax_t)stats->objects.inflated_sizes.trees, value_delim);
+       printf("objects.blobs.inflated_size%c%" PRIuMAX "%c", key_delim,
+              (uintmax_t)stats->objects.inflated_sizes.blobs, value_delim);
+       printf("objects.tags.inflated_size%c%" PRIuMAX "%c", key_delim,
+              (uintmax_t)stats->objects.inflated_sizes.tags, value_delim);
+
        fflush(stdout);
 }
 
@@ -486,6 +498,7 @@ static void structure_count_references(struct ref_stats *stats,
 }
 
 struct count_objects_data {
+       struct object_database *odb;
        struct object_stats *stats;
        struct progress *progress;
 };
@@ -495,20 +508,39 @@ static int count_objects(const char *path UNUSED, struct oid_array *oids,
 {
        struct count_objects_data *data = cb_data;
        struct object_stats *stats = data->stats;
+       size_t inflated_total = 0;
        size_t object_count;
 
+       for (size_t i = 0; i < oids->nr; i++) {
+               struct object_info oi = OBJECT_INFO_INIT;
+               unsigned long inflated;
+
+               oi.sizep = &inflated;
+
+               if (odb_read_object_info_extended(data->odb, &oids->oid[i], &oi,
+                                                 OBJECT_INFO_SKIP_FETCH_OBJECT |
+                                                 OBJECT_INFO_QUICK) < 0)
+                       continue;
+
+               inflated_total += inflated;
+       }
+
        switch (type) {
        case OBJ_TAG:
                stats->type_counts.tags += oids->nr;
+               stats->inflated_sizes.tags += inflated_total;
                break;
        case OBJ_COMMIT:
                stats->type_counts.commits += oids->nr;
+               stats->inflated_sizes.commits += inflated_total;
                break;
        case OBJ_TREE:
                stats->type_counts.trees += oids->nr;
+               stats->inflated_sizes.trees += inflated_total;
                break;
        case OBJ_BLOB:
                stats->type_counts.blobs += oids->nr;
+               stats->inflated_sizes.blobs += inflated_total;
                break;
        default:
                BUG("invalid object type");
@@ -526,6 +558,7 @@ static void structure_count_objects(struct object_stats *stats,
 {
        struct path_walk_info info = PATH_WALK_INFO_INIT;
        struct count_objects_data data = {
+               .odb = repo->objects,
                .stats = stats,
        };
 
index 55fd13ad1b9c4c4b5e016e232a4b2ce665a4aba2..33237822fd551eb0c6fd56aa767525e81a0e6898 100755 (executable)
@@ -73,7 +73,7 @@ test_expect_success 'repository with references and objects' '
        )
 '
 
-test_expect_success 'keyvalue and nul format' '
+test_expect_success SHA1 'keyvalue and nul format' '
        test_when_finished "rm -rf repo" &&
        git init repo &&
        (
@@ -90,6 +90,10 @@ test_expect_success 'keyvalue and nul format' '
                objects.trees.count=42
                objects.blobs.count=42
                objects.tags.count=1
+               objects.commits.inflated_size=9225
+               objects.trees.inflated_size=28554
+               objects.blobs.inflated_size=453
+               objects.tags.inflated_size=132
                EOF
 
                git repo structure --format=keyvalue >out 2>err &&