diff options
context:
space:
mode:
Diffstat (limited to 'source/ui-stats.c')
-rw-r--r--source/ui-stats.c105
1 file changed, 56 insertions, 49 deletions
diff --git a/source/ui-stats.c b/source/ui-stats.c
index d0fcfd8..20e9a30 100644
--- a/source/ui-stats.c
+++ b/source/ui-stats.c
@@ -275,40 +275,57 @@ static struct string_list collect_stats(const struct cgit_period *period)
return authors;
}
-static void print_combined_authorrow(struct string_list *authors, int from,
- int to, const char *name,
- const char *leftclass,
- const char *centerclass,
- const char *rightclass,
- const struct cgit_period *period)
+/*
+ * The column labels for the displayed window, oldest first. Every table below
+ * walks the same period, and each step of that walk converts a struct tm to a
+ * time_t and back, so the labels are worked out once and shared. It also frees
+ * the callers from pretty() handing back a buffer it reuses.
+ */
+static struct string_list build_period_labels(const struct cgit_period *period)
{
- struct string_list_item *author;
- struct authorstat *authorstat;
- struct string_list *items;
- struct string_list_item *date;
- time_t now;
- long i, j, total, subtotal;
+ struct string_list labels = STRING_LIST_INIT_DUP;
struct tm tm;
- char *tmp;
+ time_t now;
+ int i;
time(&now);
gmtime_r(&now, &tm);
period->trunc(&tm);
for (i = 1; i < period->count; i++)
period->dec(&tm);
+ for (i = 0; i < period->count; i++) {
+ string_list_append(&labels, period->pretty(&tm));
+ period->inc(&tm);
+ }
+ return labels;
+}
+
+/* Sum one row across a run of authors. Taking a count rather than an end index
+ * keeps an empty author list from describing a run that wraps. */
+static void print_combined_authorrow(struct string_list *authors, size_t from,
+ size_t count, const char *name,
+ const char *leftclass,
+ const char *centerclass,
+ const char *rightclass,
+ const struct string_list *labels)
+{
+ struct string_list_item *author;
+ struct authorstat *authorstat;
+ struct string_list *items;
+ struct string_list_item *date;
+ size_t i, j;
+ long total, subtotal;
total = 0;
htmlf("<tr><td class='%s'>%s</td>", leftclass,
- cgit_fmt(name, to - from + 1));
- for (j = 0; j < period->count; j++) {
- tmp = period->pretty(&tm);
- period->inc(&tm);
+ cgit_fmt(name, (long)count));
+ for (j = 0; j < labels->nr; j++) {
subtotal = 0;
- for (i = from; i <= to; i++) {
+ for (i = from; i < from + count; i++) {
author = &authors->items[i];
authorstat = author->util;
items = &authorstat->list;
- date = string_list_lookup(items, tmp);
+ date = string_list_lookup(items, labels->items[j].string);
if (date)
subtotal += (uintptr_t)date->util;
}
@@ -318,34 +335,24 @@ static void print_combined_authorrow(struct string_list *authors, int from,
htmlf("<td class='%s'>%ld</td></tr>", rightclass, total);
}
-static void print_authors(struct string_list *authors, int top,
- const struct cgit_period *period)
+static void print_authors(struct string_list *authors, int requested_top,
+ const struct string_list *labels)
{
struct string_list_item *author;
struct authorstat *authorstat;
struct string_list *items;
struct string_list_item *date;
- time_t now;
- long i, j, total;
- struct tm tm;
- char *tmp;
-
- time(&now);
- gmtime_r(&now, &tm);
- period->trunc(&tm);
- for (i = 1; i < period->count; i++)
- period->dec(&tm);
+ size_t i, j, top;
+ long total;
html("<table class='stats'><tr><th>Author</th>");
- for (j = 0; j < period->count; j++) {
- tmp = period->pretty(&tm);
- htmlf("<th>%s</th>", tmp);
- period->inc(&tm);
- }
+ for (j = 0; j < labels->nr; j++)
+ htmlf("<th>%s</th>", labels->items[j].string);
html("<th>Total</th></tr>\n");
- if (top <= 0 || top > authors->nr)
- top = authors->nr;
+ // The author count arrives through ofs, which carries -1 for "all".
+ top = (requested_top <= 0 || (size_t)requested_top > authors->nr)
+ ? authors->nr : (size_t)requested_top;
for (i = 0; i < top; i++) {
author = &authors->items[i];
@@ -355,12 +362,8 @@ static void print_authors(struct string_list *authors, int top,
authorstat = author->util;
items = &authorstat->list;
total = 0;
- for (j = 0; j < period->count; j++)
- period->dec(&tm);
- for (j = 0; j < period->count; j++) {
- tmp = period->pretty(&tm);
- period->inc(&tm);
- date = string_list_lookup(items, tmp);
+ for (j = 0; j < labels->nr; j++) {
+ date = string_list_lookup(items, labels->items[j].string);
if (!date)
html("<td>0</td>");
else {
@@ -372,11 +375,11 @@ static void print_authors(struct string_list *authors, int top,
}
if (top < authors->nr)
- print_combined_authorrow(authors, top, authors->nr - 1,
- "Others (%ld)", "left", "", "sum", period);
+ print_combined_authorrow(authors, top, authors->nr - top,
+ "Others (%ld)", "left", "", "sum", labels);
- print_combined_authorrow(authors, 0, authors->nr - 1, "Total",
- "total", "sum", "sum", period);
+ print_combined_authorrow(authors, 0, authors->nr, "Total",
+ "total", "sum", "sum", labels);
html("</table>");
}
@@ -606,7 +609,11 @@ void cgit_show_stats(void)
html("')");
}
html("</h2>");
- print_authors(&authors, top, period);
+ {
+ struct string_list labels = build_period_labels(period);
+ print_authors(&authors, top, &labels);
+ string_list_clear(&labels, 0);
+ }
print_languages(&lw);
string_list_clear(&lw.langs, 0);