Skip to content

Commit dc4a5f7

Browse files
derrickstoleedscho
authored andcommitted
survey: add object count summary
At the moment, nothing is obvious about the reason for the use of the path-walk API, but this will become more prevelant in future iterations. For now, use the path-walk API to sum up the counts of each kind of object. For example, this is the reachable object summary output for my local repo: REACHABLE OBJECT SUMMARY ======================== Object Type | Count ------------+------- Tags | 1343 Commits | 179344 Trees | 314350 Blobs | 184030 Signed-off-by: Derrick Stolee <[email protected]>
1 parent 3c9a3dd commit dc4a5f7

File tree

3 files changed

+149
-11
lines changed

3 files changed

+149
-11
lines changed

Documentation/git-survey.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ The references summary includes a count of each kind of reference,
7272
including branches, remote refs, and tags (split by "all" and
7373
"annotated").
7474

75+
Reachable Object Summary
76+
~~~~~~~~~~~~~~~~~~~~~~~~
77+
78+
The reachable object summary shows the total number of each kind of Git
79+
object, including tags, commits, trees, and blobs.
80+
7581
GIT
7682
---
7783
Part of the linkgit:git[1] suite

builtin/survey.c

Lines changed: 124 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,20 @@
22

33
#include "builtin.h"
44
#include "config.h"
5+
#include "environment.h"
6+
#include "hex.h"
57
#include "object.h"
8+
#include "object-name.h"
69
#include "object-store-ll.h"
710
#include "parse-options.h"
11+
#include "path-walk.h"
812
#include "progress.h"
913
#include "ref-filter.h"
14+
#include "refs.h"
15+
#include "revision.h"
1016
#include "strbuf.h"
1117
#include "strvec.h"
18+
#include "tag.h"
1219
#include "trace2.h"
1320

1421
static const char * const survey_usage[] = {
@@ -46,12 +53,20 @@ struct survey_report_ref_summary {
4653
size_t unknown_nr;
4754
};
4855

56+
struct survey_report_object_summary {
57+
size_t commits_nr;
58+
size_t tags_nr;
59+
size_t trees_nr;
60+
size_t blobs_nr;
61+
};
62+
4963
/**
5064
* This struct contains all of the information that needs to be printed
5165
* at the end of the exploration of the repository and its references.
5266
*/
5367
struct survey_report {
5468
struct survey_report_ref_summary refs;
69+
struct survey_report_object_summary reachable_objects;
5570
};
5671

5772
struct survey_context {
@@ -74,10 +89,12 @@ struct survey_context {
7489
size_t progress_total;
7590

7691
struct strvec refs;
92+
struct ref_array ref_array;
7793
};
7894

7995
static void clear_survey_context(struct survey_context *ctx)
8096
{
97+
ref_array_clear(&ctx->ref_array);
8198
strvec_clear(&ctx->refs);
8299
}
83100

@@ -128,10 +145,14 @@ static const size_t section_len = 4 * SECTION_SEGMENT_LEN;
128145
static void print_table_title(const char *name, size_t *widths, size_t nr)
129146
{
130147
size_t width = 3 * (nr - 1);
148+
size_t min_width = strlen(name);
131149

132150
for (size_t i = 0; i < nr; i++)
133151
width += widths[i];
134152

153+
if (width < min_width)
154+
width = min_width;
155+
135156
if (width > section_len)
136157
width = section_len;
137158

@@ -228,11 +249,43 @@ static void survey_report_plaintext_refs(struct survey_context *ctx)
228249
clear_table(&table);
229250
}
230251

252+
static void survey_report_plaintext_reachable_object_summary(struct survey_context *ctx)
253+
{
254+
struct survey_report_object_summary *objs = &ctx->report.reachable_objects;
255+
struct survey_table table = SURVEY_TABLE_INIT;
256+
char *fmt;
257+
258+
table.table_name = _("REACHABLE OBJECT SUMMARY");
259+
260+
strvec_push(&table.header, _("Object Type"));
261+
strvec_push(&table.header, _("Count"));
262+
263+
fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)objs->tags_nr);
264+
insert_table_rowv(&table, _("Tags"), fmt, NULL);
265+
free(fmt);
266+
267+
fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)objs->commits_nr);
268+
insert_table_rowv(&table, _("Commits"), fmt, NULL);
269+
free(fmt);
270+
271+
fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)objs->trees_nr);
272+
insert_table_rowv(&table, _("Trees"), fmt, NULL);
273+
free(fmt);
274+
275+
fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)objs->blobs_nr);
276+
insert_table_rowv(&table, _("Blobs"), fmt, NULL);
277+
free(fmt);
278+
279+
print_table_plaintext(&table);
280+
clear_table(&table);
281+
}
282+
231283
static void survey_report_plaintext(struct survey_context *ctx)
232284
{
233285
printf("GIT SURVEY for \"%s\"\n", ctx->repo->worktree);
234286
printf("-----------------------------------------------------\n");
235287
survey_report_plaintext_refs(ctx);
288+
survey_report_plaintext_reachable_object_summary(ctx);
236289
}
237290

238291
/*
@@ -380,15 +433,13 @@ static void do_load_refs(struct survey_context *ctx,
380433
*/
381434
static void survey_phase_refs(struct survey_context *ctx)
382435
{
383-
struct ref_array ref_array = { 0 };
384-
385436
trace2_region_enter("survey", "phase/refs", ctx->repo);
386-
do_load_refs(ctx, &ref_array);
437+
do_load_refs(ctx, &ctx->ref_array);
387438

388-
ctx->report.refs.refs_nr = ref_array.nr;
389-
for (size_t i = 0; i < ref_array.nr; i++) {
439+
ctx->report.refs.refs_nr = ctx->ref_array.nr;
440+
for (size_t i = 0; i < ctx->ref_array.nr; i++) {
390441
unsigned long size;
391-
struct ref_array_item *item = ref_array.items[i];
442+
struct ref_array_item *item = ctx->ref_array.items[i];
392443

393444
switch (item->kind) {
394445
case FILTER_REFS_TAGS:
@@ -418,8 +469,72 @@ static void survey_phase_refs(struct survey_context *ctx)
418469
}
419470

420471
trace2_region_leave("survey", "phase/refs", ctx->repo);
472+
}
473+
474+
static void increment_object_counts(
475+
struct survey_report_object_summary *summary,
476+
enum object_type type,
477+
size_t nr)
478+
{
479+
switch (type) {
480+
case OBJ_COMMIT:
481+
summary->commits_nr += nr;
482+
break;
421483

422-
ref_array_clear(&ref_array);
484+
case OBJ_TREE:
485+
summary->trees_nr += nr;
486+
break;
487+
488+
case OBJ_BLOB:
489+
summary->blobs_nr += nr;
490+
break;
491+
492+
case OBJ_TAG:
493+
summary->tags_nr += nr;
494+
break;
495+
496+
default:
497+
break;
498+
}
499+
}
500+
501+
static int survey_objects_path_walk_fn(const char *path,
502+
struct oid_array *oids,
503+
enum object_type type,
504+
void *data)
505+
{
506+
struct survey_context *ctx = data;
507+
508+
increment_object_counts(&ctx->report.reachable_objects,
509+
type, oids->nr);
510+
511+
return 0;
512+
}
513+
514+
static void survey_phase_objects(struct survey_context *ctx)
515+
{
516+
struct rev_info revs = REV_INFO_INIT;
517+
struct path_walk_info info = PATH_WALK_INFO_INIT;
518+
unsigned int add_flags = 0;
519+
520+
trace2_region_enter("survey", "phase/objects", ctx->repo);
521+
522+
info.revs = &revs;
523+
info.path_fn = survey_objects_path_walk_fn;
524+
info.path_fn_data = ctx;
525+
526+
repo_init_revisions(ctx->repo, &revs, "");
527+
revs.tag_objects = 1;
528+
529+
for (size_t i = 0; i < ctx->ref_array.nr; i++) {
530+
struct ref_array_item *item = ctx->ref_array.items[i];
531+
add_pending_oid(&revs, NULL, &item->objectname, add_flags);
532+
}
533+
534+
walk_objects_by_path(&info);
535+
536+
release_revisions(&revs);
537+
trace2_region_leave("survey", "phase/objects", ctx->repo);
423538
}
424539

425540
int cmd_survey(int argc, const char **argv, const char *prefix, struct repository *repo)
@@ -472,6 +587,8 @@ int cmd_survey(int argc, const char **argv, const char *prefix, struct repositor
472587

473588
survey_phase_refs(&ctx);
474589

590+
survey_phase_objects(&ctx);
591+
475592
survey_report_plaintext(&ctx);
476593

477594
clear_survey_context(&ctx);

t/t8100-git-survey.sh

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,17 @@ test_expect_success 'git survey -h shows experimental warning' '
1616
'
1717

1818
test_expect_success 'create a semi-interesting repo' '
19-
test_commit_bulk 10
19+
test_commit_bulk 10 &&
20+
git tag -a -m one one HEAD~5 &&
21+
git tag -a -m two two HEAD~3 &&
22+
git tag -a -m three three two &&
23+
git tag -a -m four four three &&
24+
git update-ref -d refs/tags/three &&
25+
git update-ref -d refs/tags/two
2026
'
2127

2228
test_expect_success 'git survey (default)' '
23-
git survey >out 2>err &&
29+
git survey --all-refs >out 2>err &&
2430
test_line_count = 0 err &&
2531
2632
tr , " " >expect <<-EOF &&
@@ -33,8 +39,17 @@ test_expect_success 'git survey (default)' '
3339
-----------------+------
3440
, Branches | 1
3541
Remote refs | 0
36-
Tags (all) | 0
37-
Tags (annotated) | 0
42+
Tags (all) | 2
43+
Tags (annotated) | 2
44+
45+
REACHABLE OBJECT SUMMARY
46+
========================
47+
Object Type | Count
48+
------------+------
49+
Tags | 4
50+
Commits | 10
51+
Trees | 10
52+
Blobs | 10
3853
EOF
3954
4055
test_cmp expect out

0 commit comments

Comments
 (0)