[PATCH 2/6] builtin/repo: humanise count values in structure output
- From
Justin Tobler <jltobler@gmail.com>
- Date
- Dec 9, 2025, 22:58 UTC
- Message-ID
- <20251209225820.2861276-3-jltobler@gmail.com>
- In-Reply-To
- <20251209225820.2861276-1-jltobler@gmail.com>
The table output format for the git-repo(1) structure subcommand is used by default and intended to provide output to users in a human-friendly manner. When the reference/object count values in a repository are large, it becomes more cumbersome for users to read the values.
For larger values, update the table output format to instead produce more human-friendly count values that are scaled down with the appropriate unit prefix. Output for the keyvalue and nul formats remains unchanged.
Signed-off-by: Justin Tobler <jltobler@gmail.com> --- builtin/repo.c | 61 +++++++++++++++++++++++++++++++------- t/t1901-repo-structure.sh | 62 +++++++++++++++++++-------------------- 2 files changed, 82 insertions(+), 41 deletions(-)
diff --git a/builtin/repo.c b/builtin/repo.c index a69699857a..8fb728b3a5 100644 --- a/builtin/repo.c +++ b/builtin/repo.c @@ -223,6 +223,7 @@ struct stats_table { int name_col_width; int value_col_width; + int unit_col_width; }; /* @@ -230,6 +231,7 @@ struct stats_table { */ struct stats_table_entry { char *value; + const char *unit; }; static void stats_table_vaddf(struct stats_table *table, @@ -250,11 +252,18 @@ static void stats_table_vaddf(struct stats_table *table, if (name_width > table->name_col_width) table->name_col_width = name_width; - if (entry) { + if (!entry) + return; + if (entry->value) { int value_width = utf8_strwidth(entry->value); if (value_width > table->value_col_width) table->value_col_width = value_width; } + if (entry->unit) { + int unit_width = utf8_strwidth(entry->unit); + if (unit_width > table->unit_col_width) + table->unit_col_width = unit_width; + } } static void stats_table_addf(struct stats_table *table, const char *format, ...) @@ -266,6 +275,10 @@ static void stats_table_addf(struct stats_table *table, const char *format, ...) va_end(ap); } +static const char *unit_k = "k"; +static const char *unit_M = "M"; +static const char *unit_G = "G"; + static void stats_table_count_addf(struct stats_table *table, size_t value, const char *format, ...) { @@ -273,7 +286,26 @@ static void stats_table_count_addf(struct stats_table *table, size_t value, va_list ap; CALLOC_ARRAY(entry, 1); - entry->value = xstrfmt("%" PRIuMAX, (uintmax_t)value); + + if (value >= 1000000000) { + uintmax_t x = (uintmax_t)value + 5000000; + entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX, + x / 1000000000, + x % 1000000000 / 10000000); + entry->unit = unit_G; + } else if (value >= 1000000) { + uintmax_t x = (uintmax_t)value + 5000; + entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX, + x / 1000000, x % 1000000 / 10000); + entry->unit = unit_M; + } else if (value >= 1000) { + uintmax_t x = (uintmax_t)value + 5; + entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX, + x / 1000, x % 1000 / 10); + entry->unit = unit_k; + } else { + entry->value = xstrfmt("%" PRIuMAX, (uintmax_t)value); + } va_start(ap, format); stats_table_vaddf(table, entry, format, ap); @@ -324,20 +356,24 @@ static void stats_table_print_structure(const struct stats_table *table) { const char *name_col_title = _("Repository structure"); const char *value_col_title = _("Value"); - int name_col_width = utf8_strwidth(name_col_title); - int value_col_width = utf8_strwidth(value_col_title); + int title_name_width = utf8_strwidth(name_col_title); + int title_value_width = utf8_strwidth(value_col_title); + int name_col_width = table->name_col_width; + int value_col_width = table->value_col_width; + int unit_col_width = table->unit_col_width; struct string_list_item *item; struct strbuf buf = STRBUF_INIT; - if (table->name_col_width > name_col_width) - name_col_width = table->name_col_width; - if (table->value_col_width > value_col_width) - value_col_width = table->value_col_width; + if (title_name_width > name_col_width) + name_col_width = title_name_width; + if (title_value_width > value_col_width + unit_col_width + 1) + value_col_width = title_value_width - unit_col_width; strbuf_addstr(&buf, "| "); strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, name_col_title); strbuf_addstr(&buf, " | "); - strbuf_utf8_align(&buf, ALIGN_LEFT, value_col_width, value_col_title); + strbuf_utf8_align(&buf, ALIGN_LEFT, + value_col_width + unit_col_width + 1, value_col_title); strbuf_addstr(&buf, " |"); printf("%s\n", buf.buf); @@ -345,17 +381,20 @@ static void stats_table_print_structure(const struct stats_table *table) for (int i = 0; i < name_col_width; i++) putchar('-'); printf(" | "); - for (int i = 0; i < value_col_width; i++) + for (int i = 0; i < value_col_width + unit_col_width + 1; i++) putchar('-'); printf(" |\n"); for_each_string_list_item(item, &table->rows) { struct stats_table_entry *entry = item->util; const char *value = ""; + const char *unit = ""; if (entry) { struct stats_table_entry *entry = item->util; value = entry->value; + if (entry->unit) + unit = entry->unit; } strbuf_reset(&buf); @@ -363,6 +402,8 @@ static void stats_table_print_structure(const struct stats_table *table) strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, item->string); strbuf_addstr(&buf, " | "); strbuf_utf8_align(&buf, ALIGN_RIGHT, value_col_width, value); + strbuf_addch(&buf, ' '); + strbuf_utf8_align(&buf, ALIGN_LEFT, unit_col_width, unit); strbuf_addstr(&buf, " |"); printf("%s\n", buf.buf); } diff --git a/t/t1901-repo-structure.sh b/t/t1901-repo-structure.sh index 36a71a144e..55fd13ad1b 100755 --- a/t/t1901-repo-structure.sh +++ b/t/t1901-repo-structure.sh @@ -10,21 +10,21 @@ test_expect_success 'empty repository' ' ( cd repo && cat >expect <<-\EOF && - | Repository structure | Value | - | -------------------- | ----- | - | * References | | - | * Count | 0 | - | * Branches | 0 | - | * Tags | 0 | - | * Remotes | 0 | - | * Others | 0 | - | | | - | * Reachable objects | | - | * Count | 0 | - | * Commits | 0 | - | * Trees | 0 | - | * Blobs | 0 | - | * Tags | 0 | + | Repository structure | Value | + | -------------------- | ------ | + | * References | | + | * Count | 0 | + | * Branches | 0 | + | * Tags | 0 | + | * Remotes | 0 | + | * Others | 0 | + | | | + | * Reachable objects | | + | * Count | 0 | + | * Commits | 0 | + | * Trees | 0 | + | * Blobs | 0 | + | * Tags | 0 | EOF git repo structure >out 2>err && @@ -39,7 +39,7 @@ test_expect_success 'repository with references and objects' ' git init repo && ( cd repo && - test_commit_bulk 42 && + test_commit_bulk 1005 && git tag -a foo -m bar && oid="$(git rev-parse HEAD)" && @@ -49,21 +49,21 @@ 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 | 130 | - | * Commits | 43 | - | * Trees | 43 | - | * Blobs | 43 | - | * 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 | EOF git repo structure >out 2>err &&
-- 2.52.0.209.ge85ae279b0