builtin/repo: add inflated object info to structure table

Update the table output format for the git-repo(1) structure command to
begin printing the total inflated object size info by object type. To be
more human-friendly, larger values are scaled down and displayed with
the appropriate unit prefix. Output for the keyvalue and nul formats
remains unchanged.

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-09 16:58:18 -06:00
committed by Junio C Hamano
parent d76924cf90
commit 7697f89150
2 changed files with 90 additions and 29 deletions

View File

@@ -315,6 +315,44 @@ static void stats_table_count_addf(struct stats_table *table, size_t value,
va_end(ap);
}
static const char *unit_B = "B";
static const char *unit_KiB = "KiB";
static const char *unit_MiB = "MiB";
static const char *unit_GiB = "GiB";
static void stats_table_size_addf(struct stats_table *table, size_t value,
const char *format, ...)
{
struct stats_table_entry *entry;
va_list ap;
CALLOC_ARRAY(entry, 1);
if (value > 1 << 30) {
uintmax_t x = (uintmax_t)value + 5368709;
entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX, x >> 30,
((x & ((1 << 30) - 1)) * 100) >> 30);
entry->unit = unit_GiB;
} else if (value > 1 << 20) {
uintmax_t x = (uintmax_t)value + 5243;
entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX, x >> 20,
((x & ((1 << 20) - 1)) * 100) >> 20);
entry->unit = unit_MiB;
} else if (value > 1 << 10) {
uintmax_t x = (uintmax_t)value + 5;
entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX, x >> 10,
((x & ((1 << 10) - 1)) * 100) >> 10);
entry->unit = unit_KiB;
} else {
entry->value = xstrfmt("%" PRIuMAX, (uintmax_t)value);
entry->unit = unit_B;
}
va_start(ap, format);
stats_table_vaddf(table, entry, format, ap);
va_end(ap);
}
static inline size_t get_total_reference_count(struct ref_stats *stats)
{
return stats->branches + stats->remotes + stats->tags + stats->others;
@@ -330,7 +368,8 @@ static void stats_table_setup_structure(struct stats_table *table,
{
struct object_stats *objects = &stats->objects;
struct ref_stats *refs = &stats->refs;
size_t object_total;
size_t inflated_object_total;
size_t object_count_total;
size_t ref_total;
ref_total = get_total_reference_count(refs);
@@ -341,10 +380,10 @@ static void stats_table_setup_structure(struct stats_table *table,
stats_table_count_addf(table, refs->remotes, " * %s", _("Remotes"));
stats_table_count_addf(table, refs->others, " * %s", _("Others"));
object_total = get_total_object_values(&objects->type_counts);
object_count_total = get_total_object_values(&objects->type_counts);
stats_table_addf(table, "");
stats_table_addf(table, "* %s", _("Reachable objects"));
stats_table_count_addf(table, object_total, " * %s", _("Count"));
stats_table_count_addf(table, object_count_total, " * %s", _("Count"));
stats_table_count_addf(table, objects->type_counts.commits,
" * %s", _("Commits"));
stats_table_count_addf(table, objects->type_counts.trees,
@@ -353,6 +392,18 @@ static void stats_table_setup_structure(struct stats_table *table,
" * %s", _("Blobs"));
stats_table_count_addf(table, objects->type_counts.tags,
" * %s", _("Tags"));
inflated_object_total = get_total_object_values(&objects->inflated_sizes);
stats_table_size_addf(table, inflated_object_total,
" * %s", _("Inflated size"));
stats_table_size_addf(table, objects->inflated_sizes.commits,
" * %s", _("Commits"));
stats_table_size_addf(table, objects->inflated_sizes.trees,
" * %s", _("Trees"));
stats_table_size_addf(table, objects->inflated_sizes.blobs,
" * %s", _("Blobs"));
stats_table_size_addf(table, objects->inflated_sizes.tags,
" * %s", _("Tags"));
}
static void stats_table_print_structure(const struct stats_table *table)

View File

@@ -13,18 +13,23 @@ test_expect_success 'empty repository' '
| Repository structure | Value |
| -------------------- | ------ |
| * References | |
| * Count | 0 |
| * Branches | 0 |
| * Tags | 0 |
| * Remotes | 0 |
| * Others | 0 |
| * Count | 0 |
| * Branches | 0 |
| * Tags | 0 |
| * Remotes | 0 |
| * Others | 0 |
| | |
| * Reachable objects | |
| * Count | 0 |
| * Commits | 0 |
| * Trees | 0 |
| * Blobs | 0 |
| * Tags | 0 |
| * Count | 0 |
| * Commits | 0 |
| * Trees | 0 |
| * Blobs | 0 |
| * Tags | 0 |
| * Inflated size | 0 B |
| * Commits | 0 B |
| * Trees | 0 B |
| * Blobs | 0 B |
| * Tags | 0 B |
EOF
git repo structure >out 2>err &&
@@ -34,7 +39,7 @@ test_expect_success 'empty repository' '
)
'
test_expect_success 'repository with references and objects' '
test_expect_success SHA1 'repository with references and objects' '
test_when_finished "rm -rf repo" &&
git init repo &&
(
@@ -49,21 +54,26 @@ test_expect_success 'repository with references and objects' '
git notes add -m foo &&
cat >expect <<-\EOF &&
| Repository structure | Value |
| -------------------- | ------ |
| * References | |
| * Count | 4 |
| * Branches | 1 |
| * Tags | 1 |
| * Remotes | 1 |
| * Others | 1 |
| | |
| * Reachable objects | |
| * Count | 3.02 k |
| * Commits | 1.01 k |
| * Trees | 1.01 k |
| * Blobs | 1.01 k |
| * Tags | 1 |
| Repository structure | Value |
| -------------------- | ---------- |
| * References | |
| * Count | 4 |
| * Branches | 1 |
| * Tags | 1 |
| * Remotes | 1 |
| * Others | 1 |
| | |
| * Reachable objects | |
| * Count | 3.02 k |
| * Commits | 1.01 k |
| * Trees | 1.01 k |
| * Blobs | 1.01 k |
| * Tags | 1 |
| * Inflated size | 16.03 MiB |
| * Commits | 217.92 KiB |
| * Trees | 15.81 MiB |
| * Blobs | 11.68 KiB |
| * Tags | 132 B |
EOF
git repo structure >out 2>err &&