Skip to content

Commit cdd279d

Browse files
committed
Merge branch 'jt/repo-struct-more-objinfo' into seen
More object database related information are shown in "git repo structure" output. Comments? * jt/repo-struct-more-objinfo: builtin/repo: add object disk size info to structure table builtin/repo: add disk size info to keyvalue stucture output builtin/repo: add inflated object info to structure table builtin/repo: add inflated object info to keyvalue structure output builtin/repo: humanise count values in structure output builtin/repo: group per-type object values into struct
2 parents 52c6080 + b8cacab commit cdd279d

File tree

3 files changed

+301
-73
lines changed

3 files changed

+301
-73
lines changed

Documentation/git-repo.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ supported:
6161
+
6262
* Reference counts categorized by type
6363
* Reachable object counts categorized by type
64+
* Total inflated size of reachable objects by type
65+
* Total disk size of reachable objects by type
6466
+
6567
The output format can be chosen through the flag `--format`. Three formats are
6668
supported:

builtin/repo.c

Lines changed: 193 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#include "builtin.h"
44
#include "environment.h"
5+
#include "hex.h"
6+
#include "odb.h"
57
#include "parse-options.h"
68
#include "path-walk.h"
79
#include "progress.h"
@@ -241,13 +243,19 @@ struct ref_stats {
241243
size_t others;
242244
};
243245

244-
struct object_stats {
246+
struct object_values {
245247
size_t tags;
246248
size_t commits;
247249
size_t trees;
248250
size_t blobs;
249251
};
250252

253+
struct object_stats {
254+
struct object_values type_counts;
255+
struct object_values inflated_sizes;
256+
struct object_values disk_sizes;
257+
};
258+
251259
struct repo_structure {
252260
struct ref_stats refs;
253261
struct object_stats objects;
@@ -258,13 +266,15 @@ struct stats_table {
258266

259267
int name_col_width;
260268
int value_col_width;
269+
int unit_col_width;
261270
};
262271

263272
/*
264273
* Holds column data that gets stored for each row.
265274
*/
266275
struct stats_table_entry {
267276
char *value;
277+
const char *unit;
268278
};
269279

270280
static void stats_table_vaddf(struct stats_table *table,
@@ -285,11 +295,18 @@ static void stats_table_vaddf(struct stats_table *table,
285295

286296
if (name_width > table->name_col_width)
287297
table->name_col_width = name_width;
288-
if (entry) {
298+
if (!entry)
299+
return;
300+
if (entry->value) {
289301
int value_width = utf8_strwidth(entry->value);
290302
if (value_width > table->value_col_width)
291303
table->value_col_width = value_width;
292304
}
305+
if (entry->unit) {
306+
int unit_width = utf8_strwidth(entry->unit);
307+
if (unit_width > table->unit_col_width)
308+
table->unit_col_width = unit_width;
309+
}
293310
}
294311

295312
static void stats_table_addf(struct stats_table *table, const char *format, ...)
@@ -301,14 +318,75 @@ static void stats_table_addf(struct stats_table *table, const char *format, ...)
301318
va_end(ap);
302319
}
303320

321+
static const char *unit_k = "k";
322+
static const char *unit_M = "M";
323+
static const char *unit_G = "G";
324+
304325
static void stats_table_count_addf(struct stats_table *table, size_t value,
305326
const char *format, ...)
306327
{
307328
struct stats_table_entry *entry;
308329
va_list ap;
309330

310331
CALLOC_ARRAY(entry, 1);
311-
entry->value = xstrfmt("%" PRIuMAX, (uintmax_t)value);
332+
333+
if (value >= 1000000000) {
334+
uintmax_t x = (uintmax_t)value + 5000000;
335+
entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX,
336+
x / 1000000000,
337+
x % 1000000000 / 10000000);
338+
entry->unit = unit_G;
339+
} else if (value >= 1000000) {
340+
uintmax_t x = (uintmax_t)value + 5000;
341+
entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX,
342+
x / 1000000, x % 1000000 / 10000);
343+
entry->unit = unit_M;
344+
} else if (value >= 1000) {
345+
uintmax_t x = (uintmax_t)value + 5;
346+
entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX,
347+
x / 1000, x % 1000 / 10);
348+
entry->unit = unit_k;
349+
} else {
350+
entry->value = xstrfmt("%" PRIuMAX, (uintmax_t)value);
351+
}
352+
353+
va_start(ap, format);
354+
stats_table_vaddf(table, entry, format, ap);
355+
va_end(ap);
356+
}
357+
358+
static const char *unit_B = "B";
359+
static const char *unit_KiB = "KiB";
360+
static const char *unit_MiB = "MiB";
361+
static const char *unit_GiB = "GiB";
362+
363+
static void stats_table_size_addf(struct stats_table *table, size_t value,
364+
const char *format, ...)
365+
{
366+
struct stats_table_entry *entry;
367+
va_list ap;
368+
369+
CALLOC_ARRAY(entry, 1);
370+
371+
if (value > 1 << 30) {
372+
uintmax_t x = (uintmax_t)value + 5368709;
373+
entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX, x >> 30,
374+
((x & ((1 << 30) - 1)) * 100) >> 30);
375+
entry->unit = unit_GiB;
376+
} else if (value > 1 << 20) {
377+
uintmax_t x = (uintmax_t)value + 5243;
378+
entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX, x >> 20,
379+
((x & ((1 << 20) - 1)) * 100) >> 20);
380+
entry->unit = unit_MiB;
381+
} else if (value > 1 << 10) {
382+
uintmax_t x = (uintmax_t)value + 5;
383+
entry->value = xstrfmt("%" PRIuMAX ".%02" PRIuMAX, x >> 10,
384+
((x & ((1 << 10) - 1)) * 100) >> 10);
385+
entry->unit = unit_KiB;
386+
} else {
387+
entry->value = xstrfmt("%" PRIuMAX, (uintmax_t)value);
388+
entry->unit = unit_B;
389+
}
312390

313391
va_start(ap, format);
314392
stats_table_vaddf(table, entry, format, ap);
@@ -320,17 +398,19 @@ static inline size_t get_total_reference_count(struct ref_stats *stats)
320398
return stats->branches + stats->remotes + stats->tags + stats->others;
321399
}
322400

323-
static inline size_t get_total_object_count(struct object_stats *stats)
401+
static inline size_t get_total_object_values(struct object_values *values)
324402
{
325-
return stats->tags + stats->commits + stats->trees + stats->blobs;
403+
return values->tags + values->commits + values->trees + values->blobs;
326404
}
327405

328406
static void stats_table_setup_structure(struct stats_table *table,
329407
struct repo_structure *stats)
330408
{
331409
struct object_stats *objects = &stats->objects;
332410
struct ref_stats *refs = &stats->refs;
333-
size_t object_total;
411+
size_t inflated_object_total;
412+
size_t object_count_total;
413+
size_t disk_object_total;
334414
size_t ref_total;
335415

336416
ref_total = get_total_reference_count(refs);
@@ -341,59 +421,96 @@ static void stats_table_setup_structure(struct stats_table *table,
341421
stats_table_count_addf(table, refs->remotes, " * %s", _("Remotes"));
342422
stats_table_count_addf(table, refs->others, " * %s", _("Others"));
343423

344-
object_total = get_total_object_count(objects);
424+
object_count_total = get_total_object_values(&objects->type_counts);
345425
stats_table_addf(table, "");
346426
stats_table_addf(table, "* %s", _("Reachable objects"));
347-
stats_table_count_addf(table, object_total, " * %s", _("Count"));
348-
stats_table_count_addf(table, objects->commits, " * %s", _("Commits"));
349-
stats_table_count_addf(table, objects->trees, " * %s", _("Trees"));
350-
stats_table_count_addf(table, objects->blobs, " * %s", _("Blobs"));
351-
stats_table_count_addf(table, objects->tags, " * %s", _("Tags"));
427+
stats_table_count_addf(table, object_count_total, " * %s", _("Count"));
428+
stats_table_count_addf(table, objects->type_counts.commits,
429+
" * %s", _("Commits"));
430+
stats_table_count_addf(table, objects->type_counts.trees,
431+
" * %s", _("Trees"));
432+
stats_table_count_addf(table, objects->type_counts.blobs,
433+
" * %s", _("Blobs"));
434+
stats_table_count_addf(table, objects->type_counts.tags,
435+
" * %s", _("Tags"));
436+
437+
inflated_object_total = get_total_object_values(&objects->inflated_sizes);
438+
stats_table_size_addf(table, inflated_object_total,
439+
" * %s", _("Inflated size"));
440+
stats_table_size_addf(table, objects->inflated_sizes.commits,
441+
" * %s", _("Commits"));
442+
stats_table_size_addf(table, objects->inflated_sizes.trees,
443+
" * %s", _("Trees"));
444+
stats_table_size_addf(table, objects->inflated_sizes.blobs,
445+
" * %s", _("Blobs"));
446+
stats_table_size_addf(table, objects->inflated_sizes.tags,
447+
" * %s", _("Tags"));
448+
449+
disk_object_total = get_total_object_values(&objects->disk_sizes);
450+
stats_table_size_addf(table, disk_object_total,
451+
" * %s", _("Disk size"));
452+
stats_table_size_addf(table, objects->disk_sizes.commits,
453+
" * %s", _("Commits"));
454+
stats_table_size_addf(table, objects->disk_sizes.trees,
455+
" * %s", _("Trees"));
456+
stats_table_size_addf(table, objects->disk_sizes.blobs,
457+
" * %s", _("Blobs"));
458+
stats_table_size_addf(table, objects->disk_sizes.tags,
459+
" * %s", _("Tags"));
352460
}
353461

354462
static void stats_table_print_structure(const struct stats_table *table)
355463
{
356464
const char *name_col_title = _("Repository structure");
357465
const char *value_col_title = _("Value");
358-
int name_col_width = utf8_strwidth(name_col_title);
359-
int value_col_width = utf8_strwidth(value_col_title);
466+
int title_name_width = utf8_strwidth(name_col_title);
467+
int title_value_width = utf8_strwidth(value_col_title);
468+
int name_col_width = table->name_col_width;
469+
int value_col_width = table->value_col_width;
470+
int unit_col_width = table->unit_col_width;
360471
struct string_list_item *item;
361472
struct strbuf buf = STRBUF_INIT;
362473

363-
if (table->name_col_width > name_col_width)
364-
name_col_width = table->name_col_width;
365-
if (table->value_col_width > value_col_width)
366-
value_col_width = table->value_col_width;
474+
if (title_name_width > name_col_width)
475+
name_col_width = title_name_width;
476+
if (title_value_width > value_col_width + unit_col_width + 1)
477+
value_col_width = title_value_width - unit_col_width;
367478

368479
strbuf_addstr(&buf, "| ");
369480
strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, name_col_title);
370481
strbuf_addstr(&buf, " | ");
371-
strbuf_utf8_align(&buf, ALIGN_LEFT, value_col_width, value_col_title);
482+
strbuf_utf8_align(&buf, ALIGN_LEFT,
483+
value_col_width + unit_col_width + 1, value_col_title);
372484
strbuf_addstr(&buf, " |");
373485
printf("%s\n", buf.buf);
374486

375487
printf("| ");
376488
for (int i = 0; i < name_col_width; i++)
377489
putchar('-');
378490
printf(" | ");
379-
for (int i = 0; i < value_col_width; i++)
491+
for (int i = 0; i < value_col_width + unit_col_width + 1; i++)
380492
putchar('-');
381493
printf(" |\n");
382494

383495
for_each_string_list_item(item, &table->rows) {
384496
struct stats_table_entry *entry = item->util;
385497
const char *value = "";
498+
const char *unit = "";
386499

387500
if (entry) {
388501
struct stats_table_entry *entry = item->util;
389502
value = entry->value;
503+
if (entry->unit)
504+
unit = entry->unit;
390505
}
391506

392507
strbuf_reset(&buf);
393508
strbuf_addstr(&buf, "| ");
394509
strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, item->string);
395510
strbuf_addstr(&buf, " | ");
396511
strbuf_utf8_align(&buf, ALIGN_RIGHT, value_col_width, value);
512+
strbuf_addch(&buf, ' ');
513+
strbuf_utf8_align(&buf, ALIGN_LEFT, unit_col_width, unit);
397514
strbuf_addstr(&buf, " |");
398515
printf("%s\n", buf.buf);
399516
}
@@ -428,13 +545,31 @@ static void structure_keyvalue_print(struct repo_structure *stats,
428545
(uintmax_t)stats->refs.others, value_delim);
429546

430547
printf("objects.commits.count%c%" PRIuMAX "%c", key_delim,
431-
(uintmax_t)stats->objects.commits, value_delim);
548+
(uintmax_t)stats->objects.type_counts.commits, value_delim);
432549
printf("objects.trees.count%c%" PRIuMAX "%c", key_delim,
433-
(uintmax_t)stats->objects.trees, value_delim);
550+
(uintmax_t)stats->objects.type_counts.trees, value_delim);
434551
printf("objects.blobs.count%c%" PRIuMAX "%c", key_delim,
435-
(uintmax_t)stats->objects.blobs, value_delim);
552+
(uintmax_t)stats->objects.type_counts.blobs, value_delim);
436553
printf("objects.tags.count%c%" PRIuMAX "%c", key_delim,
437-
(uintmax_t)stats->objects.tags, value_delim);
554+
(uintmax_t)stats->objects.type_counts.tags, value_delim);
555+
556+
printf("objects.commits.inflated%c%" PRIuMAX "%c", key_delim,
557+
(uintmax_t)stats->objects.inflated_sizes.commits, value_delim);
558+
printf("objects.trees.inflated%c%" PRIuMAX "%c", key_delim,
559+
(uintmax_t)stats->objects.inflated_sizes.trees, value_delim);
560+
printf("objects.blobs.inflated%c%" PRIuMAX "%c", key_delim,
561+
(uintmax_t)stats->objects.inflated_sizes.blobs, value_delim);
562+
printf("objects.tags.inflated%c%" PRIuMAX "%c", key_delim,
563+
(uintmax_t)stats->objects.inflated_sizes.tags, value_delim);
564+
565+
printf("objects.commits.disk%c%" PRIuMAX "%c", key_delim,
566+
(uintmax_t)stats->objects.disk_sizes.commits, value_delim);
567+
printf("objects.trees.disk%c%" PRIuMAX "%c", key_delim,
568+
(uintmax_t)stats->objects.disk_sizes.trees, value_delim);
569+
printf("objects.blobs.disk%c%" PRIuMAX "%c", key_delim,
570+
(uintmax_t)stats->objects.disk_sizes.blobs, value_delim);
571+
printf("objects.tags.disk%c%" PRIuMAX "%c", key_delim,
572+
(uintmax_t)stats->objects.disk_sizes.tags, value_delim);
438573

439574
fflush(stdout);
440575
}
@@ -499,6 +634,7 @@ static void structure_count_references(struct ref_stats *stats,
499634
}
500635

501636
struct count_objects_data {
637+
struct object_database *odb;
502638
struct object_stats *stats;
503639
struct progress *progress;
504640
};
@@ -508,26 +644,53 @@ static int count_objects(const char *path UNUSED, struct oid_array *oids,
508644
{
509645
struct count_objects_data *data = cb_data;
510646
struct object_stats *stats = data->stats;
647+
size_t inflated_total = 0;
648+
size_t disk_total = 0;
511649
size_t object_count;
512650

651+
for (size_t i = 0; i < oids->nr; i++) {
652+
struct object_info oi = OBJECT_INFO_INIT;
653+
unsigned long inflated;
654+
off_t disk;
655+
656+
oi.sizep = &inflated;
657+
oi.disk_sizep = &disk;
658+
659+
if (odb_read_object_info_extended(data->odb, &oids->oid[i], &oi,
660+
OBJECT_INFO_FOR_PREFETCH) < 0)
661+
die(_("cannot read object for %s"),
662+
oid_to_hex(&oids->oid[i]));
663+
664+
inflated_total += inflated;
665+
disk_total += disk;
666+
}
667+
513668
switch (type) {
514669
case OBJ_TAG:
515-
stats->tags += oids->nr;
670+
stats->type_counts.tags += oids->nr;
671+
stats->inflated_sizes.tags += inflated_total;
672+
stats->disk_sizes.tags += disk_total;
516673
break;
517674
case OBJ_COMMIT:
518-
stats->commits += oids->nr;
675+
stats->type_counts.commits += oids->nr;
676+
stats->inflated_sizes.commits += inflated_total;
677+
stats->disk_sizes.commits += disk_total;
519678
break;
520679
case OBJ_TREE:
521-
stats->trees += oids->nr;
680+
stats->type_counts.trees += oids->nr;
681+
stats->inflated_sizes.trees += inflated_total;
682+
stats->disk_sizes.trees += disk_total;
522683
break;
523684
case OBJ_BLOB:
524-
stats->blobs += oids->nr;
685+
stats->type_counts.blobs += oids->nr;
686+
stats->inflated_sizes.blobs += inflated_total;
687+
stats->disk_sizes.blobs += disk_total;
525688
break;
526689
default:
527690
BUG("invalid object type");
528691
}
529692

530-
object_count = get_total_object_count(stats);
693+
object_count = get_total_object_values(&stats->type_counts);
531694
display_progress(data->progress, object_count);
532695

533696
return 0;
@@ -539,6 +702,7 @@ static void structure_count_objects(struct object_stats *stats,
539702
{
540703
struct path_walk_info info = PATH_WALK_INFO_INIT;
541704
struct count_objects_data data = {
705+
.odb = repo->objects,
542706
.stats = stats,
543707
};
544708

0 commit comments

Comments
 (0)