mirror of
https://github.com/git-for-windows/git.git
synced 2026-02-04 03:33:01 -06:00
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 <stolee@gmail.com>
This commit is contained in:
parent
f16938703a
commit
7e2adefac9
@ -72,6 +72,12 @@ The references summary includes a count of each kind of reference,
|
||||
including branches, remote refs, and tags (split by "all" and
|
||||
"annotated").
|
||||
|
||||
Reachable Object Summary
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The reachable object summary shows the total number of each kind of Git
|
||||
object, including tags, commits, trees, and blobs.
|
||||
|
||||
GIT
|
||||
---
|
||||
Part of the linkgit:git[1] suite
|
||||
|
||||
131
builtin/survey.c
131
builtin/survey.c
@ -2,13 +2,20 @@
|
||||
|
||||
#include "builtin.h"
|
||||
#include "config.h"
|
||||
#include "environment.h"
|
||||
#include "hex.h"
|
||||
#include "object.h"
|
||||
#include "object-name.h"
|
||||
#include "object-store.h"
|
||||
#include "parse-options.h"
|
||||
#include "path-walk.h"
|
||||
#include "progress.h"
|
||||
#include "ref-filter.h"
|
||||
#include "refs.h"
|
||||
#include "revision.h"
|
||||
#include "strbuf.h"
|
||||
#include "strvec.h"
|
||||
#include "tag.h"
|
||||
#include "trace2.h"
|
||||
|
||||
static const char * const survey_usage[] = {
|
||||
@ -46,12 +53,20 @@ struct survey_report_ref_summary {
|
||||
size_t unknown_nr;
|
||||
};
|
||||
|
||||
struct survey_report_object_summary {
|
||||
size_t commits_nr;
|
||||
size_t tags_nr;
|
||||
size_t trees_nr;
|
||||
size_t blobs_nr;
|
||||
};
|
||||
|
||||
/**
|
||||
* This struct contains all of the information that needs to be printed
|
||||
* at the end of the exploration of the repository and its references.
|
||||
*/
|
||||
struct survey_report {
|
||||
struct survey_report_ref_summary refs;
|
||||
struct survey_report_object_summary reachable_objects;
|
||||
};
|
||||
|
||||
struct survey_context {
|
||||
@ -74,10 +89,12 @@ struct survey_context {
|
||||
size_t progress_total;
|
||||
|
||||
struct strvec refs;
|
||||
struct ref_array ref_array;
|
||||
};
|
||||
|
||||
static void clear_survey_context(struct survey_context *ctx)
|
||||
{
|
||||
ref_array_clear(&ctx->ref_array);
|
||||
strvec_clear(&ctx->refs);
|
||||
}
|
||||
|
||||
@ -128,10 +145,14 @@ static const size_t section_len = 4 * SECTION_SEGMENT_LEN;
|
||||
static void print_table_title(const char *name, size_t *widths, size_t nr)
|
||||
{
|
||||
size_t width = 3 * (nr - 1);
|
||||
size_t min_width = strlen(name);
|
||||
|
||||
for (size_t i = 0; i < nr; i++)
|
||||
width += widths[i];
|
||||
|
||||
if (width < min_width)
|
||||
width = min_width;
|
||||
|
||||
if (width > section_len)
|
||||
width = section_len;
|
||||
|
||||
@ -228,11 +249,43 @@ static void survey_report_plaintext_refs(struct survey_context *ctx)
|
||||
clear_table(&table);
|
||||
}
|
||||
|
||||
static void survey_report_plaintext_reachable_object_summary(struct survey_context *ctx)
|
||||
{
|
||||
struct survey_report_object_summary *objs = &ctx->report.reachable_objects;
|
||||
struct survey_table table = SURVEY_TABLE_INIT;
|
||||
char *fmt;
|
||||
|
||||
table.table_name = _("REACHABLE OBJECT SUMMARY");
|
||||
|
||||
strvec_push(&table.header, _("Object Type"));
|
||||
strvec_push(&table.header, _("Count"));
|
||||
|
||||
fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)objs->tags_nr);
|
||||
insert_table_rowv(&table, _("Tags"), fmt, NULL);
|
||||
free(fmt);
|
||||
|
||||
fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)objs->commits_nr);
|
||||
insert_table_rowv(&table, _("Commits"), fmt, NULL);
|
||||
free(fmt);
|
||||
|
||||
fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)objs->trees_nr);
|
||||
insert_table_rowv(&table, _("Trees"), fmt, NULL);
|
||||
free(fmt);
|
||||
|
||||
fmt = xstrfmt("%"PRIuMAX"", (uintmax_t)objs->blobs_nr);
|
||||
insert_table_rowv(&table, _("Blobs"), fmt, NULL);
|
||||
free(fmt);
|
||||
|
||||
print_table_plaintext(&table);
|
||||
clear_table(&table);
|
||||
}
|
||||
|
||||
static void survey_report_plaintext(struct survey_context *ctx)
|
||||
{
|
||||
printf("GIT SURVEY for \"%s\"\n", ctx->repo->worktree);
|
||||
printf("-----------------------------------------------------\n");
|
||||
survey_report_plaintext_refs(ctx);
|
||||
survey_report_plaintext_reachable_object_summary(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -381,15 +434,13 @@ static void do_load_refs(struct survey_context *ctx,
|
||||
*/
|
||||
static void survey_phase_refs(struct survey_context *ctx)
|
||||
{
|
||||
struct ref_array ref_array = { 0 };
|
||||
|
||||
trace2_region_enter("survey", "phase/refs", ctx->repo);
|
||||
do_load_refs(ctx, &ref_array);
|
||||
do_load_refs(ctx, &ctx->ref_array);
|
||||
|
||||
ctx->report.refs.refs_nr = ref_array.nr;
|
||||
for (int i = 0; i < ref_array.nr; i++) {
|
||||
ctx->report.refs.refs_nr = ctx->ref_array.nr;
|
||||
for (int i = 0; i < ctx->ref_array.nr; i++) {
|
||||
unsigned long size;
|
||||
struct ref_array_item *item = ref_array.items[i];
|
||||
struct ref_array_item *item = ctx->ref_array.items[i];
|
||||
|
||||
switch (item->kind) {
|
||||
case FILTER_REFS_TAGS:
|
||||
@ -419,8 +470,72 @@ static void survey_phase_refs(struct survey_context *ctx)
|
||||
}
|
||||
|
||||
trace2_region_leave("survey", "phase/refs", ctx->repo);
|
||||
}
|
||||
|
||||
ref_array_clear(&ref_array);
|
||||
static void increment_object_counts(
|
||||
struct survey_report_object_summary *summary,
|
||||
enum object_type type,
|
||||
size_t nr)
|
||||
{
|
||||
switch (type) {
|
||||
case OBJ_COMMIT:
|
||||
summary->commits_nr += nr;
|
||||
break;
|
||||
|
||||
case OBJ_TREE:
|
||||
summary->trees_nr += nr;
|
||||
break;
|
||||
|
||||
case OBJ_BLOB:
|
||||
summary->blobs_nr += nr;
|
||||
break;
|
||||
|
||||
case OBJ_TAG:
|
||||
summary->tags_nr += nr;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int survey_objects_path_walk_fn(const char *path,
|
||||
struct oid_array *oids,
|
||||
enum object_type type,
|
||||
void *data)
|
||||
{
|
||||
struct survey_context *ctx = data;
|
||||
|
||||
increment_object_counts(&ctx->report.reachable_objects,
|
||||
type, oids->nr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void survey_phase_objects(struct survey_context *ctx)
|
||||
{
|
||||
struct rev_info revs = REV_INFO_INIT;
|
||||
struct path_walk_info info = PATH_WALK_INFO_INIT;
|
||||
unsigned int add_flags = 0;
|
||||
|
||||
trace2_region_enter("survey", "phase/objects", ctx->repo);
|
||||
|
||||
info.revs = &revs;
|
||||
info.path_fn = survey_objects_path_walk_fn;
|
||||
info.path_fn_data = ctx;
|
||||
|
||||
repo_init_revisions(ctx->repo, &revs, "");
|
||||
revs.tag_objects = 1;
|
||||
|
||||
for (int i = 0; i < ctx->ref_array.nr; i++) {
|
||||
struct ref_array_item *item = ctx->ref_array.items[i];
|
||||
add_pending_oid(&revs, NULL, &item->objectname, add_flags);
|
||||
}
|
||||
|
||||
walk_objects_by_path(&info);
|
||||
|
||||
release_revisions(&revs);
|
||||
trace2_region_leave("survey", "phase/objects", ctx->repo);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
survey_phase_refs(&ctx);
|
||||
|
||||
survey_phase_objects(&ctx);
|
||||
|
||||
survey_report_plaintext(&ctx);
|
||||
|
||||
clear_survey_context(&ctx);
|
||||
|
||||
@ -16,11 +16,17 @@ test_expect_success 'git survey -h shows experimental warning' '
|
||||
'
|
||||
|
||||
test_expect_success 'create a semi-interesting repo' '
|
||||
test_commit_bulk 10
|
||||
test_commit_bulk 10 &&
|
||||
git tag -a -m one one HEAD~5 &&
|
||||
git tag -a -m two two HEAD~3 &&
|
||||
git tag -a -m three three two &&
|
||||
git tag -a -m four four three &&
|
||||
git update-ref -d refs/tags/three &&
|
||||
git update-ref -d refs/tags/two
|
||||
'
|
||||
|
||||
test_expect_success 'git survey (default)' '
|
||||
git survey >out 2>err &&
|
||||
git survey --all-refs >out 2>err &&
|
||||
test_line_count = 0 err &&
|
||||
|
||||
tr , " " >expect <<-EOF &&
|
||||
@ -33,8 +39,17 @@ test_expect_success 'git survey (default)' '
|
||||
-----------------+------
|
||||
, Branches | 1
|
||||
Remote refs | 0
|
||||
Tags (all) | 0
|
||||
Tags (annotated) | 0
|
||||
Tags (all) | 2
|
||||
Tags (annotated) | 2
|
||||
|
||||
REACHABLE OBJECT SUMMARY
|
||||
========================
|
||||
Object Type | Count
|
||||
------------+------
|
||||
Tags | 4
|
||||
Commits | 10
|
||||
Trees | 10
|
||||
Blobs | 10
|
||||
EOF
|
||||
|
||||
test_cmp expect out
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user