diff --git a/builtin/survey.c b/builtin/survey.c index fed7f2fb426b0d..0a79881eb9746a 100644 --- a/builtin/survey.c +++ b/builtin/survey.c @@ -13,6 +13,7 @@ #include "revision.h" #include "run-command.h" #include "strbuf.h" +#include "strmap.h" #include "strvec.h" #include "trace2.h" #include "tree.h" @@ -280,6 +281,8 @@ struct survey_stats_refs { size_t len_sum_local_refnames; size_t len_max_remote_refname; size_t len_sum_remote_refnames; + + struct strintmap refsmap; }; /* @@ -1046,8 +1049,11 @@ static void do_treewalk_reachable(struct ref_array *ref_array) static void do_calc_stats_refs(struct ref_array *ref_array) { struct survey_stats_refs *prs = &survey_stats.refs; + struct strbuf buf = STRBUF_INIT; int k; + strintmap_init(&prs->refsmap, 0); + for (k = 0; k < ref_array->nr; k++) { struct ref_array_item *p = ref_array->items[k]; struct object_id peeled; @@ -1065,18 +1071,65 @@ static void do_calc_stats_refs(struct ref_array *ref_array) */ switch (p->kind) { case FILTER_REFS_TAGS: + strintmap_incr(&prs->refsmap, "refs/tags/", 1); + if (!peel_iterated_oid(&p->objectname, &peeled)) prs->cnt_annotated_tags++; else prs->cnt_lightweight_tags++; break; + case FILTER_REFS_BRANCHES: + strintmap_incr(&prs->refsmap, "refs/heads/", 1); + prs->cnt_branches++; break; + case FILTER_REFS_REMOTES: + /* + * For the refsmap, group them by the "refs/remotes//". + * For example: + * "refs/remotes/origin/..." + */ + if (starts_with(p->refname, "refs/remotes/")) { + int begin = strlen("refs/remotes/"); + size_t j; + strbuf_reset(&buf); + strbuf_addstr(&buf, p->refname); + for (j = begin; j < buf.len; j++) { + if (buf.buf[j] == '/') { + strbuf_setlen(&buf, j+1); + break; + } + } + strintmap_incr(&prs->refsmap, buf.buf, 1); + } + prs->cnt_remotes++; break; + case FILTER_REFS_OTHERS: + /* + * For the refsmap, group them by their "refs//". + * For example: + * "refs/notes/..." + * "refs/stash/..." + * "refs//..." + */ + if (starts_with(p->refname, "refs/")) { + int begin = strlen("refs/"); + size_t j; + strbuf_reset(&buf); + strbuf_addstr(&buf, p->refname); + for (j = begin; j < buf.len; j++) { + if (buf.buf[j] == '/') { + strbuf_setlen(&buf, j+1); + break; + } + } + strintmap_incr(&prs->refsmap, buf.buf, 1); + } + if (starts_with(p->refname, "refs/prefetch/")) prs->cnt_prefetch++; else if (starts_with(p->refname, "refs/pull/")) @@ -1084,10 +1137,15 @@ static void do_calc_stats_refs(struct ref_array *ref_array) else prs->cnt_other++; break; + case FILTER_REFS_DETACHED_HEAD: + strintmap_incr(&prs->refsmap, p->refname, 1); + prs->cnt_detached++; break; + default: + strintmap_incr(&prs->refsmap, p->refname, 1); /* probably "HEAD" */ break; } @@ -1416,6 +1474,26 @@ static void survey_json(struct json_writer *jw, int pretty) jw_array_string(jw, survey_vec_refs_wanted.v[k]); } jw_end(jw); + + jw_object_inline_begin_array(jw, "observed"); + { + struct hashmap_iter iter; + struct strmap_entry *entry; + int value; + + strintmap_for_each_entry(&prs->refsmap, &iter, entry) { + const char *key = entry->key; + intptr_t count = (intptr_t)entry->value; + int value = count; + jw_array_inline_begin_object(jw); + { + jw_object_string(jw, "class", key); + jw_object_intmax(jw, "count", value); + } + jw_end(jw); + } + } + jw_end(jw); } jw_end(jw); @@ -1977,6 +2055,22 @@ static void pretty_print_refs(int indent) fmt_txt_pair_ui64(&buf, indent3, "pull", prs->cnt_pull); } + strbuf_addch(&buf, '\n'); + fmt_txt_pair_ui64(&buf, indent1, "Observed Reference Classes", strintmap_get_size(&prs->refsmap)); + { + struct hashmap_iter iter; + struct strmap_entry *entry; + int value; + + strintmap_for_each_entry(&prs->refsmap, &iter, entry) { + const char *key = entry->key; + intptr_t count = (intptr_t)entry->value; + int value = count; + + fmt_txt_pair_ui64(&buf, indent2, key, value); + } + } + strbuf_addch(&buf, '\n'); fmt_txt_line(&buf, indent1, "Reference Count by Storage Location"); fmt_txt_pair_ui64(&buf, indent2, "Loose", prs->cnt_loose); @@ -1995,11 +2089,6 @@ static void pretty_print_refs(int indent) fmt_txt_pair_ui64(&buf, indent3, "Sum", prs->len_sum_local_refnames); } - /* - * NEEDSWORK: Do we want to print the set of "refs/" - * patterns that we requested to be in the set? - */ - strbuf_addch(&buf, '\n'); fwrite(buf.buf, 1, buf.len, stdout); strbuf_release(&buf);