Skip to content

Commit d9345f4

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 163add3 commit d9345f4

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
/*
@@ -381,15 +434,13 @@ static void do_load_refs(struct survey_context *ctx,
381434
*/
382435
static void survey_phase_refs(struct survey_context *ctx)
383436
{
384-
struct ref_array ref_array = { 0 };
385-
386437
trace2_region_enter("survey", "phase/refs", ctx->repo);
387-
do_load_refs(ctx, &ref_array);
438+
do_load_refs(ctx, &ctx->ref_array);
388439

389-
ctx->report.refs.refs_nr = ref_array.nr;
390-
for (int i = 0; i < ref_array.nr; i++) {
440+
ctx->report.refs.refs_nr = ctx->ref_array.nr;
441+
for (int i = 0; i < ctx->ref_array.nr; i++) {
391442
unsigned long size;
392-
struct ref_array_item *item = ref_array.items[i];
443+
struct ref_array_item *item = ctx->ref_array.items[i];
393444

394445
switch (item->kind) {
395446
case FILTER_REFS_TAGS:
@@ -419,8 +470,72 @@ static void survey_phase_refs(struct survey_context *ctx)
419470
}
420471

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

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

426541
int cmd_survey(int argc, const char **argv, const char *prefix, struct repository *repo)
@@ -473,6 +588,8 @@ int cmd_survey(int argc, const char **argv, const char *prefix, struct repositor
473588

474589
survey_phase_refs(&ctx);
475590

591+
survey_phase_objects(&ctx);
592+
476593
survey_report_plaintext(&ctx);
477594

478595
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)