Subject: Re: [PATCH 4/6] builtin/repo: add inflated object info to structure table

From: Patrick Steinhardt <[email-masked]>
Date: Wed, 10 Dec 2025 07:28:34 +0100

On Tue, Dec 09, 2025 at 04:58:18PM -0600, Justin Tobler wrote:
> 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 <[email-masked]>
> ---
>  builtin/repo.c            | 57 +++++++++++++++++++++++++++++++++--
>  t/t1901-repo-structure.sh | 62 +++++++++++++++++++++++----------------
>  2 files changed, 90 insertions(+), 29 deletions(-)
> 
> diff --git a/builtin/repo.c b/builtin/repo.c
> index a67215ae31..5c37f4116f 100644
> --- a/builtin/repo.c
> +++ b/builtin/repo.c
> @@ -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";

Okay, nice, you already use KiB et al as I suggested in an earlier
comment. But I guess these should also be marked as translatable.

> +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;
> +	}

Euh. What kind of black magic is this? This block at least warrants a
comment how you came up with these incantations.

Also, git-rev-list(1) already has logic to output human-formatted disk
sizes via `git rev-list --disk-usage=human`. Can we share the logic?

> diff --git a/t/t1901-repo-structure.sh b/t/t1901-repo-structure.sh
> index cf5e252f10..0ae96e6bbf 100755
> --- a/t/t1901-repo-structure.sh
> +++ b/t/t1901-repo-structure.sh
> @@ -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

Nice, I like the end result.

Patrick