Subject: [PATCH v3 0/6] builtin/repo: include largest object information

From: Justin Tobler <[email-masked]>
Date: Mon, 2 Mar 2026 15:45:20 -0600

Greetings,

The "structure" output for git-repo(1) currently provides count
information for references/objects as well as total inflated/disk sizes
of objects by type. Info regarding the largest individual objects in the
repository is not yet collected, but would be useful to users wishing to
identify such large objects.

This patch series adds the following data points:
- The OID and size of the largest objects by object type
- The OID and parent count of the commit with the most parents
- The OID and entries count of the tree with the most entries

Changes from V2:
- When checking for largest objects, zero valued objects were not
  recorded even if they were the "largest" object. In this version, if
  an object ID has not been recorded yet, it is always added even if its
  value is zero.
- Added some helper functions for printing keyvalue info to cut down on
  duplicate code and hopefully make it a bit easier on the eyes.
- Moved the for-each loop that printed table OID annoations inside the
  preceding if-block making it a bit easier to reason about.

Changes from V1:
- Avoided duplicating the annotation string by handing over ownership.
- I decided to leave the `struct object_stats` structure alone for now
  as storing the various object values per-type does make it convenient
  to calulate the various totals. I may revisit this in a future series
  though.

Thanks,
-Justin

Justin Tobler (6):
  builtin/repo: update stats for each object
  builtin/repo: add helper for printing keyvalue output
  builtin/repo: collect largest inflated objects
  builtin/repo: add OID annotations to table output
  builtin/repo: find commit with most parents
  builtin/repo: find tree with most entries

 Documentation/git-repo.adoc |   1 +
 builtin/repo.c              | 323 ++++++++++++++++++++++++++++--------
 t/t1901-repo-structure.sh   | 143 ++++++++++------
 3 files changed, 352 insertions(+), 115 deletions(-)

Range-diff against v2:
1:  94a44e0e0f = 1:  94a44e0e0f builtin/repo: update stats for each object
-:  ---------- > 2:  36c11351ae builtin/repo: add helper for printing keyvalue output
2:  92dbf34f2c ! 3:  90e71c058d builtin/repo: collect largest inflated objects
    @@ builtin/repo.c: static void stats_table_setup_structure(struct stats_table *tabl
      }
      
      static void stats_table_print_structure(const struct stats_table *table)
    +@@ builtin/repo.c: static inline void print_keyvalue(const char *key, char key_delim, size_t value,
    + 	       value_delim);
    + }
    + 
    ++static void print_object_data(const char *key, char key_delim,
    ++			      struct object_data *data, char value_delim)
    ++{
    ++	print_keyvalue(key, key_delim, data->value, value_delim);
    ++	printf("%s_oid%c%s%c", key, key_delim, oid_to_hex(&data->oid),
    ++	       value_delim);
    ++}
    ++
    + static void structure_keyvalue_print(struct repo_structure *stats,
    + 				     char key_delim, char value_delim)
    + {
     @@ builtin/repo.c: static void structure_keyvalue_print(struct repo_structure *stats,
    - 	printf("objects.tags.disk_size%c%" PRIuMAX "%c", key_delim,
    - 	       (uintmax_t)stats->objects.disk_sizes.tags, value_delim);
    + 	print_keyvalue("objects.tags.disk_size", key_delim,
    + 		       stats->objects.disk_sizes.tags, value_delim);
      
    -+	printf("objects.commits.max_size%c%" PRIuMAX "%c", key_delim,
    -+	       (uintmax_t)stats->objects.largest.commit_size.value, value_delim);
    -+	printf("objects.commits.max_size_oid%c%s%c", key_delim,
    -+	       oid_to_hex(&stats->objects.largest.commit_size.oid), value_delim);
    -+	printf("objects.trees.max_size%c%" PRIuMAX "%c", key_delim,
    -+	       (uintmax_t)stats->objects.largest.tree_size.value, value_delim);
    -+	printf("objects.trees.max_size_oid%c%s%c", key_delim,
    -+	       oid_to_hex(&stats->objects.largest.tree_size.oid), value_delim);
    -+	printf("objects.blobs.max_size%c%" PRIuMAX "%c", key_delim,
    -+	       (uintmax_t)stats->objects.largest.blob_size.value, value_delim);
    -+	printf("objects.blobs.max_size_oid%c%s%c", key_delim,
    -+	       oid_to_hex(&stats->objects.largest.blob_size.oid), value_delim);
    -+	printf("objects.tags.max_size%c%" PRIuMAX "%c", key_delim,
    -+	       (uintmax_t)stats->objects.largest.tag_size.value, value_delim);
    -+	printf("objects.tags.max_size_oid%c%s%c", key_delim,
    -+	       oid_to_hex(&stats->objects.largest.tag_size.oid), value_delim);
    ++	print_object_data("objects.commits.max_size", key_delim,
    ++			  &stats->objects.largest.commit_size, value_delim);
    ++	print_object_data("objects.trees.max_size", key_delim,
    ++			  &stats->objects.largest.tree_size, value_delim);
    ++	print_object_data("objects.blobs.max_size", key_delim,
    ++			  &stats->objects.largest.blob_size, value_delim);
    ++	print_object_data("objects.tags.max_size", key_delim,
    ++			  &stats->objects.largest.tag_size, value_delim);
     +
      	fflush(stdout);
      }
    @@ builtin/repo.c: struct count_objects_data {
     +static void check_largest(struct object_data *data, struct object_id *oid,
     +			  size_t value)
     +{
    -+	if (value > data->value) {
    ++	if (value > data->value || is_null_oid(&data->oid)) {
     +		oidcpy(&data->oid, oid);
     +		data->value = value;
     +	}
3:  1457d5d59c ! 4:  938c36df91 builtin/repo: add OID annotations to table output
    @@ builtin/repo.c: static void stats_table_print_structure(const struct stats_table
      		printf("%s\n", buf.buf);
      	}
      
    -+	if (table->annotations.nr)
    ++	if (table->annotations.nr) {
     +		printf("\n");
    -+	for_each_string_list_item(item, &table->annotations)
    -+		printf("%s\n", item->string);
    ++		for_each_string_list_item(item, &table->annotations)
    ++			printf("%s\n", item->string);
    ++	}
     +
      	strbuf_release(&buf);
      }
    @@ builtin/repo.c: static void stats_table_clear(struct stats_table *table)
     +	string_list_clear(&table->annotations, 1);
      }
      
    - static void structure_keyvalue_print(struct repo_structure *stats,
    + static inline void print_keyvalue(const char *key, char key_delim, size_t value,
     @@ builtin/repo.c: static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
      {
      	struct stats_table table = {
4:  f4e92e3f09 ! 5:  ab9870f06e builtin/repo: find commit with most parents
    @@ builtin/repo.c: static void stats_table_setup_structure(struct stats_table *tabl
      	stats_table_object_size_addf(table,
      				     &objects->largest.tree_size.oid,
     @@ builtin/repo.c: static void structure_keyvalue_print(struct repo_structure *stats,
    - 	printf("objects.tags.max_size_oid%c%s%c", key_delim,
    - 	       oid_to_hex(&stats->objects.largest.tag_size.oid), value_delim);
    + 	print_object_data("objects.tags.max_size", key_delim,
    + 			  &stats->objects.largest.tag_size, value_delim);
      
    -+	printf("objects.commits.max_parents%c%" PRIuMAX "%c", key_delim,
    -+	       (uintmax_t)stats->objects.largest.parent_count.value, value_delim);
    -+	printf("objects.commits.max_parents_oid%c%s%c", key_delim,
    -+	       oid_to_hex(&stats->objects.largest.parent_count.oid), value_delim);
    ++	print_object_data("objects.commits.max_parents", key_delim,
    ++			  &stats->objects.largest.parent_count, value_delim);
     +
      	fflush(stdout);
      }
5:  af404fcc6c ! 6:  2884cb451c builtin/repo: find tree with most entries
    @@ builtin/repo.c: static void stats_table_setup_structure(struct stats_table *tabl
      	stats_table_object_size_addf(table,
      				     &objects->largest.blob_size.oid,
     @@ builtin/repo.c: static void structure_keyvalue_print(struct repo_structure *stats,
    - 	       (uintmax_t)stats->objects.largest.parent_count.value, value_delim);
    - 	printf("objects.commits.max_parents_oid%c%s%c", key_delim,
    - 	       oid_to_hex(&stats->objects.largest.parent_count.oid), value_delim);
    -+	printf("objects.trees.max_entries%c%" PRIuMAX "%c", key_delim,
    -+	       (uintmax_t)stats->objects.largest.tree_entries.value, value_delim);
    -+	printf("objects.trees.max_entries_oid%c%s%c", key_delim,
    -+	       oid_to_hex(&stats->objects.largest.tree_entries.oid), value_delim);
    + 
    + 	print_object_data("objects.commits.max_parents", key_delim,
    + 			  &stats->objects.largest.parent_count, value_delim);
    ++	print_object_data("objects.trees.max_entries", key_delim,
    ++			  &stats->objects.largest.tree_entries, value_delim);
      
      	fflush(stdout);
      }

base-commit: 67ad42147a7acc2af6074753ebd03d904476118f
-- 
2.53.0