Skip to content

Commit 02e9bc3

Browse files
committed
Merge branch 'jt/repo-struct-more-objinfo'
More object database related information are shown in "git repo structure" output. * 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 strbuf: split out logic to humanise byte values builtin/repo: group per-type object values into struct
2 parents 7c7698a + df1b071 commit 02e9bc3

6 files changed

Lines changed: 331 additions & 98 deletions

File tree

Documentation/git-repo.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ supported:
5050
+
5151
* Reference counts categorized by type
5252
* Reachable object counts categorized by type
53+
* Total inflated size of reachable objects by type
54+
* Total disk size of reachable objects by type
5355
+
5456
The output format can be chosen through the flag `--format`. Three formats are
5557
supported:

builtin/repo.c

Lines changed: 146 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"
@@ -202,13 +204,19 @@ struct ref_stats {
202204
size_t others;
203205
};
204206

205-
struct object_stats {
207+
struct object_values {
206208
size_t tags;
207209
size_t commits;
208210
size_t trees;
209211
size_t blobs;
210212
};
211213

214+
struct object_stats {
215+
struct object_values type_counts;
216+
struct object_values inflated_sizes;
217+
struct object_values disk_sizes;
218+
};
219+
212220
struct repo_structure {
213221
struct ref_stats refs;
214222
struct object_stats objects;
@@ -219,13 +227,15 @@ struct stats_table {
219227

220228
int name_col_width;
221229
int value_col_width;
230+
int unit_col_width;
222231
};
223232

224233
/*
225234
* Holds column data that gets stored for each row.
226235
*/
227236
struct stats_table_entry {
228237
char *value;
238+
const char *unit;
229239
};
230240

231241
static void stats_table_vaddf(struct stats_table *table,
@@ -246,11 +256,18 @@ static void stats_table_vaddf(struct stats_table *table,
246256

247257
if (name_width > table->name_col_width)
248258
table->name_col_width = name_width;
249-
if (entry) {
259+
if (!entry)
260+
return;
261+
if (entry->value) {
250262
int value_width = utf8_strwidth(entry->value);
251263
if (value_width > table->value_col_width)
252264
table->value_col_width = value_width;
253265
}
266+
if (entry->unit) {
267+
int unit_width = utf8_strwidth(entry->unit);
268+
if (unit_width > table->unit_col_width)
269+
table->unit_col_width = unit_width;
270+
}
254271
}
255272

256273
static void stats_table_addf(struct stats_table *table, const char *format, ...)
@@ -269,7 +286,21 @@ static void stats_table_count_addf(struct stats_table *table, size_t value,
269286
va_list ap;
270287

271288
CALLOC_ARRAY(entry, 1);
272-
entry->value = xstrfmt("%" PRIuMAX, (uintmax_t)value);
289+
humanise_count(value, &entry->value, &entry->unit);
290+
291+
va_start(ap, format);
292+
stats_table_vaddf(table, entry, format, ap);
293+
va_end(ap);
294+
}
295+
296+
static void stats_table_size_addf(struct stats_table *table, size_t value,
297+
const char *format, ...)
298+
{
299+
struct stats_table_entry *entry;
300+
va_list ap;
301+
302+
CALLOC_ARRAY(entry, 1);
303+
humanise_bytes(value, &entry->value, &entry->unit, HUMANISE_COMPACT);
273304

274305
va_start(ap, format);
275306
stats_table_vaddf(table, entry, format, ap);
@@ -281,17 +312,19 @@ static inline size_t get_total_reference_count(struct ref_stats *stats)
281312
return stats->branches + stats->remotes + stats->tags + stats->others;
282313
}
283314

284-
static inline size_t get_total_object_count(struct object_stats *stats)
315+
static inline size_t get_total_object_values(struct object_values *values)
285316
{
286-
return stats->tags + stats->commits + stats->trees + stats->blobs;
317+
return values->tags + values->commits + values->trees + values->blobs;
287318
}
288319

289320
static void stats_table_setup_structure(struct stats_table *table,
290321
struct repo_structure *stats)
291322
{
292323
struct object_stats *objects = &stats->objects;
293324
struct ref_stats *refs = &stats->refs;
294-
size_t object_total;
325+
size_t inflated_object_total;
326+
size_t object_count_total;
327+
size_t disk_object_total;
295328
size_t ref_total;
296329

297330
ref_total = get_total_reference_count(refs);
@@ -302,59 +335,96 @@ static void stats_table_setup_structure(struct stats_table *table,
302335
stats_table_count_addf(table, refs->remotes, " * %s", _("Remotes"));
303336
stats_table_count_addf(table, refs->others, " * %s", _("Others"));
304337

305-
object_total = get_total_object_count(objects);
338+
object_count_total = get_total_object_values(&objects->type_counts);
306339
stats_table_addf(table, "");
307340
stats_table_addf(table, "* %s", _("Reachable objects"));
308-
stats_table_count_addf(table, object_total, " * %s", _("Count"));
309-
stats_table_count_addf(table, objects->commits, " * %s", _("Commits"));
310-
stats_table_count_addf(table, objects->trees, " * %s", _("Trees"));
311-
stats_table_count_addf(table, objects->blobs, " * %s", _("Blobs"));
312-
stats_table_count_addf(table, objects->tags, " * %s", _("Tags"));
341+
stats_table_count_addf(table, object_count_total, " * %s", _("Count"));
342+
stats_table_count_addf(table, objects->type_counts.commits,
343+
" * %s", _("Commits"));
344+
stats_table_count_addf(table, objects->type_counts.trees,
345+
" * %s", _("Trees"));
346+
stats_table_count_addf(table, objects->type_counts.blobs,
347+
" * %s", _("Blobs"));
348+
stats_table_count_addf(table, objects->type_counts.tags,
349+
" * %s", _("Tags"));
350+
351+
inflated_object_total = get_total_object_values(&objects->inflated_sizes);
352+
stats_table_size_addf(table, inflated_object_total,
353+
" * %s", _("Inflated size"));
354+
stats_table_size_addf(table, objects->inflated_sizes.commits,
355+
" * %s", _("Commits"));
356+
stats_table_size_addf(table, objects->inflated_sizes.trees,
357+
" * %s", _("Trees"));
358+
stats_table_size_addf(table, objects->inflated_sizes.blobs,
359+
" * %s", _("Blobs"));
360+
stats_table_size_addf(table, objects->inflated_sizes.tags,
361+
" * %s", _("Tags"));
362+
363+
disk_object_total = get_total_object_values(&objects->disk_sizes);
364+
stats_table_size_addf(table, disk_object_total,
365+
" * %s", _("Disk size"));
366+
stats_table_size_addf(table, objects->disk_sizes.commits,
367+
" * %s", _("Commits"));
368+
stats_table_size_addf(table, objects->disk_sizes.trees,
369+
" * %s", _("Trees"));
370+
stats_table_size_addf(table, objects->disk_sizes.blobs,
371+
" * %s", _("Blobs"));
372+
stats_table_size_addf(table, objects->disk_sizes.tags,
373+
" * %s", _("Tags"));
313374
}
314375

315376
static void stats_table_print_structure(const struct stats_table *table)
316377
{
317378
const char *name_col_title = _("Repository structure");
318379
const char *value_col_title = _("Value");
319-
int name_col_width = utf8_strwidth(name_col_title);
320-
int value_col_width = utf8_strwidth(value_col_title);
380+
int title_name_width = utf8_strwidth(name_col_title);
381+
int title_value_width = utf8_strwidth(value_col_title);
382+
int name_col_width = table->name_col_width;
383+
int value_col_width = table->value_col_width;
384+
int unit_col_width = table->unit_col_width;
321385
struct string_list_item *item;
322386
struct strbuf buf = STRBUF_INIT;
323387

324-
if (table->name_col_width > name_col_width)
325-
name_col_width = table->name_col_width;
326-
if (table->value_col_width > value_col_width)
327-
value_col_width = table->value_col_width;
388+
if (title_name_width > name_col_width)
389+
name_col_width = title_name_width;
390+
if (title_value_width > value_col_width + unit_col_width + 1)
391+
value_col_width = title_value_width - unit_col_width;
328392

329393
strbuf_addstr(&buf, "| ");
330394
strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, name_col_title);
331395
strbuf_addstr(&buf, " | ");
332-
strbuf_utf8_align(&buf, ALIGN_LEFT, value_col_width, value_col_title);
396+
strbuf_utf8_align(&buf, ALIGN_LEFT,
397+
value_col_width + unit_col_width + 1, value_col_title);
333398
strbuf_addstr(&buf, " |");
334399
printf("%s\n", buf.buf);
335400

336401
printf("| ");
337402
for (int i = 0; i < name_col_width; i++)
338403
putchar('-');
339404
printf(" | ");
340-
for (int i = 0; i < value_col_width; i++)
405+
for (int i = 0; i < value_col_width + unit_col_width + 1; i++)
341406
putchar('-');
342407
printf(" |\n");
343408

344409
for_each_string_list_item(item, &table->rows) {
345410
struct stats_table_entry *entry = item->util;
346411
const char *value = "";
412+
const char *unit = "";
347413

348414
if (entry) {
349415
struct stats_table_entry *entry = item->util;
350416
value = entry->value;
417+
if (entry->unit)
418+
unit = entry->unit;
351419
}
352420

353421
strbuf_reset(&buf);
354422
strbuf_addstr(&buf, "| ");
355423
strbuf_utf8_align(&buf, ALIGN_LEFT, name_col_width, item->string);
356424
strbuf_addstr(&buf, " | ");
357425
strbuf_utf8_align(&buf, ALIGN_RIGHT, value_col_width, value);
426+
strbuf_addch(&buf, ' ');
427+
strbuf_utf8_align(&buf, ALIGN_LEFT, unit_col_width, unit);
358428
strbuf_addstr(&buf, " |");
359429
printf("%s\n", buf.buf);
360430
}
@@ -389,13 +459,31 @@ static void structure_keyvalue_print(struct repo_structure *stats,
389459
(uintmax_t)stats->refs.others, value_delim);
390460

391461
printf("objects.commits.count%c%" PRIuMAX "%c", key_delim,
392-
(uintmax_t)stats->objects.commits, value_delim);
462+
(uintmax_t)stats->objects.type_counts.commits, value_delim);
393463
printf("objects.trees.count%c%" PRIuMAX "%c", key_delim,
394-
(uintmax_t)stats->objects.trees, value_delim);
464+
(uintmax_t)stats->objects.type_counts.trees, value_delim);
395465
printf("objects.blobs.count%c%" PRIuMAX "%c", key_delim,
396-
(uintmax_t)stats->objects.blobs, value_delim);
466+
(uintmax_t)stats->objects.type_counts.blobs, value_delim);
397467
printf("objects.tags.count%c%" PRIuMAX "%c", key_delim,
398-
(uintmax_t)stats->objects.tags, value_delim);
468+
(uintmax_t)stats->objects.type_counts.tags, value_delim);
469+
470+
printf("objects.commits.inflated_size%c%" PRIuMAX "%c", key_delim,
471+
(uintmax_t)stats->objects.inflated_sizes.commits, value_delim);
472+
printf("objects.trees.inflated_size%c%" PRIuMAX "%c", key_delim,
473+
(uintmax_t)stats->objects.inflated_sizes.trees, value_delim);
474+
printf("objects.blobs.inflated_size%c%" PRIuMAX "%c", key_delim,
475+
(uintmax_t)stats->objects.inflated_sizes.blobs, value_delim);
476+
printf("objects.tags.inflated_size%c%" PRIuMAX "%c", key_delim,
477+
(uintmax_t)stats->objects.inflated_sizes.tags, value_delim);
478+
479+
printf("objects.commits.disk_size%c%" PRIuMAX "%c", key_delim,
480+
(uintmax_t)stats->objects.disk_sizes.commits, value_delim);
481+
printf("objects.trees.disk_size%c%" PRIuMAX "%c", key_delim,
482+
(uintmax_t)stats->objects.disk_sizes.trees, value_delim);
483+
printf("objects.blobs.disk_size%c%" PRIuMAX "%c", key_delim,
484+
(uintmax_t)stats->objects.disk_sizes.blobs, value_delim);
485+
printf("objects.tags.disk_size%c%" PRIuMAX "%c", key_delim,
486+
(uintmax_t)stats->objects.disk_sizes.tags, value_delim);
399487

400488
fflush(stdout);
401489
}
@@ -460,6 +548,7 @@ static void structure_count_references(struct ref_stats *stats,
460548
}
461549

462550
struct count_objects_data {
551+
struct object_database *odb;
463552
struct object_stats *stats;
464553
struct progress *progress;
465554
};
@@ -469,26 +558,53 @@ static int count_objects(const char *path UNUSED, struct oid_array *oids,
469558
{
470559
struct count_objects_data *data = cb_data;
471560
struct object_stats *stats = data->stats;
561+
size_t inflated_total = 0;
562+
size_t disk_total = 0;
472563
size_t object_count;
473564

565+
for (size_t i = 0; i < oids->nr; i++) {
566+
struct object_info oi = OBJECT_INFO_INIT;
567+
unsigned long inflated;
568+
off_t disk;
569+
570+
oi.sizep = &inflated;
571+
oi.disk_sizep = &disk;
572+
573+
if (odb_read_object_info_extended(data->odb, &oids->oid[i], &oi,
574+
OBJECT_INFO_SKIP_FETCH_OBJECT |
575+
OBJECT_INFO_QUICK) < 0)
576+
continue;
577+
578+
inflated_total += inflated;
579+
disk_total += disk;
580+
}
581+
474582
switch (type) {
475583
case OBJ_TAG:
476-
stats->tags += oids->nr;
584+
stats->type_counts.tags += oids->nr;
585+
stats->inflated_sizes.tags += inflated_total;
586+
stats->disk_sizes.tags += disk_total;
477587
break;
478588
case OBJ_COMMIT:
479-
stats->commits += oids->nr;
589+
stats->type_counts.commits += oids->nr;
590+
stats->inflated_sizes.commits += inflated_total;
591+
stats->disk_sizes.commits += disk_total;
480592
break;
481593
case OBJ_TREE:
482-
stats->trees += oids->nr;
594+
stats->type_counts.trees += oids->nr;
595+
stats->inflated_sizes.trees += inflated_total;
596+
stats->disk_sizes.trees += disk_total;
483597
break;
484598
case OBJ_BLOB:
485-
stats->blobs += oids->nr;
599+
stats->type_counts.blobs += oids->nr;
600+
stats->inflated_sizes.blobs += inflated_total;
601+
stats->disk_sizes.blobs += disk_total;
486602
break;
487603
default:
488604
BUG("invalid object type");
489605
}
490606

491-
object_count = get_total_object_count(stats);
607+
object_count = get_total_object_values(&stats->type_counts);
492608
display_progress(data->progress, object_count);
493609

494610
return 0;
@@ -500,6 +616,7 @@ static void structure_count_objects(struct object_stats *stats,
500616
{
501617
struct path_walk_info info = PATH_WALK_INFO_INIT;
502618
struct count_objects_data data = {
619+
.odb = repo->objects,
503620
.stats = stats,
504621
};
505622

0 commit comments

Comments
 (0)