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>
This commit is contained in:
Justin Tobler 2025-12-17 11:54:03 -06:00 committed by Junio C Hamano
parent 4d279ae36b
commit 67cecc693f
3 changed files with 29 additions and 1 deletions

View File

@ -51,6 +51,7 @@ supported:
* Reference counts categorized by type
* Reachable object counts categorized by type
* Total inflated size of reachable objects by type
* Total disk size of reachable objects by type
+
The output format can be chosen through the flag `--format`. Three formats are

View File

@ -214,6 +214,7 @@ struct object_values {
struct object_stats {
struct object_values type_counts;
struct object_values inflated_sizes;
struct object_values disk_sizes;
};
struct repo_structure {
@ -462,6 +463,15 @@ static void structure_keyvalue_print(struct repo_structure *stats,
printf("objects.tags.inflated_size%c%" PRIuMAX "%c", key_delim,
(uintmax_t)stats->objects.inflated_sizes.tags, value_delim);
printf("objects.commits.disk_size%c%" PRIuMAX "%c", key_delim,
(uintmax_t)stats->objects.disk_sizes.commits, value_delim);
printf("objects.trees.disk_size%c%" PRIuMAX "%c", key_delim,
(uintmax_t)stats->objects.disk_sizes.trees, value_delim);
printf("objects.blobs.disk_size%c%" PRIuMAX "%c", key_delim,
(uintmax_t)stats->objects.disk_sizes.blobs, value_delim);
printf("objects.tags.disk_size%c%" PRIuMAX "%c", key_delim,
(uintmax_t)stats->objects.disk_sizes.tags, value_delim);
fflush(stdout);
}
@ -536,13 +546,16 @@ 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 disk_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;
off_t disk;
oi.sizep = &inflated;
oi.disk_sizep = &disk;
if (odb_read_object_info_extended(data->odb, &oids->oid[i], &oi,
OBJECT_INFO_SKIP_FETCH_OBJECT |
@ -550,24 +563,29 @@ static int count_objects(const char *path UNUSED, struct oid_array *oids,
continue;
inflated_total += inflated;
disk_total += disk;
}
switch (type) {
case OBJ_TAG:
stats->type_counts.tags += oids->nr;
stats->inflated_sizes.tags += inflated_total;
stats->disk_sizes.tags += disk_total;
break;
case OBJ_COMMIT:
stats->type_counts.commits += oids->nr;
stats->inflated_sizes.commits += inflated_total;
stats->disk_sizes.commits += disk_total;
break;
case OBJ_TREE:
stats->type_counts.trees += oids->nr;
stats->inflated_sizes.trees += inflated_total;
stats->disk_sizes.trees += disk_total;
break;
case OBJ_BLOB:
stats->type_counts.blobs += oids->nr;
stats->inflated_sizes.blobs += inflated_total;
stats->disk_sizes.blobs += disk_total;
break;
default:
BUG("invalid object type");

View File

@ -4,6 +4,11 @@ test_description='test git repo structure'
. ./test-lib.sh
object_type_disk_usage() {
git rev-list --all --objects --disk-usage --filter=object:type=$1 \
--filter-provided-objects
}
test_expect_success 'empty repository' '
test_when_finished "rm -rf repo" &&
git init repo &&
@ -91,7 +96,7 @@ test_expect_success SHA1 'keyvalue and nul format' '
test_commit_bulk 42 &&
git tag -a foo -m bar &&
cat >expect <<-\EOF &&
cat >expect <<-EOF &&
references.branches.count=1
references.tags.count=1
references.remotes.count=0
@ -104,6 +109,10 @@ test_expect_success SHA1 'keyvalue and nul format' '
objects.trees.inflated_size=28554
objects.blobs.inflated_size=453
objects.tags.inflated_size=132
objects.commits.disk_size=$(object_type_disk_usage commit)
objects.trees.disk_size=$(object_type_disk_usage tree)
objects.blobs.disk_size=$(object_type_disk_usage blob)
objects.tags.disk_size=$(object_type_disk_usage tag)
EOF
git repo structure --format=keyvalue >out 2>err &&