From 7710178e45dee61e85ea77c4221309ce8c086f95 Mon Sep 17 00:00:00 2001 From: Lars Hjemli Date: Tue, 27 Jan 2009 19:16:37 +0000 Subject: Merge branch 'lh/stats' Conflicts: cgit.c cgit.css cgit.h ui-tree.c Signed-off-by: Lars Hjemli --- diff --git a/Makefile b/Makefile index 7793c0b..a52285e 100644 --- a/Makefile +++ b/Makefile @@ -90,6 +90,7 @@ OBJECTS += ui-refs.o OBJECTS += ui-repolist.o OBJECTS += ui-shared.o OBJECTS += ui-snapshot.o +OBJECTS += ui-stats.o OBJECTS += ui-summary.o OBJECTS += ui-tag.o OBJECTS += ui-tree.o diff --git a/cgit.c b/cgit.c index f35f605..608cab6 100644 --- a/cgit.c +++ b/cgit.c @@ -12,6 +12,7 @@ #include "configfile.h" #include "html.h" #include "ui-shared.h" +#include "ui-stats.h" #include "scan-tree.h" const char *cgit_version = CGIT_VERSION; @@ -54,6 +55,8 @@ void config_cb(const char *name, const char *value) ctx.cfg.enable_log_filecount = atoi(value); else if (!strcmp(name, "enable-log-linecount")) ctx.cfg.enable_log_linecount = atoi(value); + else if (!strcmp(name, "max-stats")) + ctx.cfg.max_stats = cgit_find_stats_period(value, NULL); else if (!strcmp(name, "cache-size")) ctx.cfg.cache_size = atoi(value); else if (!strcmp(name, "cache-root")) @@ -112,6 +115,8 @@ void config_cb(const char *name, const char *value) ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value); else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount")) ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); + else if (ctx.repo && !strcmp(name, "repo.max-stats")) + ctx.repo->max_stats = cgit_find_stats_period(value, NULL); else if (ctx.repo && !strcmp(name, "repo.module-link")) ctx.repo->module_link= xstrdup(value); else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) { @@ -158,6 +163,8 @@ static void querystring_cb(const char *name, const char *value) ctx.qry.sort = xstrdup(value); } else if (!strcmp(name, "showmsg")) { ctx.qry.showmsg = atoi(value); + } else if (!strcmp(name, "period")) { + ctx.qry.period = xstrdup(value); } } @@ -181,6 +188,7 @@ static void prepare_context(struct cgit_context *ctx) ctx->cfg.max_lock_attempts = 5; ctx->cfg.max_msg_len = 80; ctx->cfg.max_repodesc_len = 80; + ctx->cfg.max_stats = 0; ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s"; ctx->cfg.renamelimit = -1; ctx->cfg.robots = "index, nofollow"; diff --git a/cgit.css b/cgit.css index f19446d..e8214de 100644 --- a/cgit.css +++ b/cgit.css @@ -495,3 +495,79 @@ a.deco { background-color: #ff8888; border: solid 1px #770000; } +table.stats { + border: solid 1px black; + border-collapse: collapse; +} + +table.stats th { + text-align: left; + padding: 1px 0.5em; + background-color: #eee; + border: solid 1px black; +} + +table.stats td { + text-align: right; + padding: 1px 0.5em; + border: solid 1px black; +} + +table.stats td.total { + font-weight: bold; + text-align: left; +} + +table.stats td.sum { + color: #c00; + font-weight: bold; +/* background-color: #eee; */ +} + +table.stats td.left { + text-align: left; +} + +table.vgraph { + border-collapse: separate; + border: solid 1px black; + height: 200px; +} + +table.vgraph th { + background-color: #eee; + font-weight: bold; + border: solid 1px white; + padding: 1px 0.5em; +} + +table.vgraph td { + vertical-align: bottom; + padding: 0px 10px; +} + +table.vgraph div.bar { + background-color: #eee; +} + +table.hgraph { + border: solid 1px black; + width: 800px; +} + +table.hgraph th { + background-color: #eee; + font-weight: bold; + border: solid 1px black; + padding: 1px 0.5em; +} + +table.hgraph td { + vertical-align: center; + padding: 2px 2px; +} + +table.hgraph div.bar { + background-color: #eee; + height: 1em; +} diff --git a/cgit.h b/cgit.h index cb2f176..4fe94c6 100644 --- a/cgit.h +++ b/cgit.h @@ -61,6 +61,7 @@ struct cgit_repo { int snapshots; int enable_log_filecount; int enable_log_linecount; + int max_stats; time_t mtime; }; @@ -120,6 +121,7 @@ struct cgit_query { char *name; char *mimetype; char *url; + char *period; int ofs; int nohead; char *sort; @@ -160,6 +162,7 @@ struct cgit_config { int max_lock_attempts; int max_msg_len; int max_repodesc_len; + int max_stats; int nocache; int renamelimit; int snapshots; diff --git a/cgitrc.5.txt b/cgitrc.5.txt index ab9ab66..09f56a6 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@ -129,6 +129,11 @@ max-repodesc-length Specifies the maximum number of repo description characters to display on the repository index page. Default value: "80". +max-stats + Set the default maximum statistics period. Valid values are "week", + "month", "quarter" and "year". If unspecified, statistics are + disabled. Default value: none. See also: "repo.max-stats". + module-link Text which will be used as the formatstring for a hyperlink when a submodule is printed in a directory listing. The arguments for the @@ -218,6 +223,11 @@ repo.enable-log-linecount A flag which can be used to disable the global setting `enable-log-linecount'. Default value: none. +repo.max-stats + Override the default maximum statistics period. Valid values are equal + to the values specified for the global "max-stats" setting. Default + value: none. + repo.name The value to show as repository name. Default value: . @@ -276,6 +286,10 @@ favicon=/favicon.ico logo=/img/mylogo.png +# Enable statistics per week, month and quarter +max-stats=quarter + + # Set the title and heading of the repository index page root-title=foobar.com git repositories @@ -348,6 +362,9 @@ repo.snapshots=0 # Disable line-counts for this repo repo.enable-log-linecount=0 +# Restrict the max statistics period for this repo +repo.max-stats=month + BUGS ---- diff --git a/cmd.c b/cmd.c index 8914fa5..cf97da7 100644 --- a/cmd.c +++ b/cmd.c @@ -21,6 +21,7 @@ #include "ui-refs.h" #include "ui-repolist.h" #include "ui-snapshot.h" +#include "ui-stats.h" #include "ui-summary.h" #include "ui-tag.h" #include "ui-tree.h" @@ -108,6 +109,11 @@ static void snapshot_fn(struct cgit_context *ctx) ctx->repo->snapshots, ctx->qry.nohead); } +static void stats_fn(struct cgit_context *ctx) +{ + cgit_show_stats(ctx); +} + static void summary_fn(struct cgit_context *ctx) { cgit_print_summary(); @@ -144,6 +150,7 @@ struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx) def_cmd(refs, 1, 1), def_cmd(repolist, 0, 0), def_cmd(snapshot, 1, 0), + def_cmd(stats, 1, 1), def_cmd(summary, 1, 1), def_cmd(tag, 1, 1), def_cmd(tree, 1, 1), diff --git a/shared.c b/shared.c index a764c4d..578a544 100644 --- a/shared.c +++ b/shared.c @@ -58,6 +58,7 @@ struct cgit_repo *cgit_add_repo(const char *url) ret->snapshots = ctx.cfg.snapshots; ret->enable_log_filecount = ctx.cfg.enable_log_filecount; ret->enable_log_linecount = ctx.cfg.enable_log_linecount; + ret->max_stats = ctx.cfg.max_stats; ret->module_link = ctx.cfg.module_link; ret->readme = NULL; ret->mtime = -1; diff --git a/ui-shared.c b/ui-shared.c index fba1ba6..4f28512 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -369,6 +369,12 @@ void cgit_patch_link(char *name, char *title, char *class, char *head, reporevlink("patch", name, title, class, head, rev, NULL); } +void cgit_stats_link(char *name, char *title, char *class, char *head, + char *path) +{ + reporevlink("stats", name, title, class, head, NULL, path); +} + void cgit_object_link(struct object *obj) { char *page, *shortrev, *fullrev, *name; @@ -557,7 +563,7 @@ int print_archive_ref(const char *refname, const unsigned char *sha1, return 0; } -void add_hidden_formfields(int incl_head, int incl_search, char *page) +void cgit_add_hidden_formfields(int incl_head, int incl_search, char *page) { char *url; @@ -619,7 +625,7 @@ void cgit_print_pageheader(struct cgit_context *ctx) cgit_summary_link(ctx->repo->name, ctx->repo->name, NULL, NULL); html(""); html("
\n"); - add_hidden_formfields(0, 1, ctx->qry.page); + cgit_add_hidden_formfields(0, 1, ctx->qry.page); html(" "); @@ -656,6 +662,9 @@ void cgit_print_pageheader(struct cgit_context *ctx) ctx->qry.head, ctx->qry.sha1); cgit_diff_link("diff", NULL, hc(cmd, "diff"), ctx->qry.head, ctx->qry.sha1, ctx->qry.sha2, NULL); + if (ctx->repo->max_stats) + cgit_stats_link("stats", NULL, hc(cmd, "stats"), + ctx->qry.head, NULL); if (ctx->repo->readme) reporevlink("about", "about", NULL, hc(cmd, "about"), ctx->qry.head, NULL, @@ -666,7 +675,7 @@ void cgit_print_pageheader(struct cgit_context *ctx) html_url_path(cgit_fileurl(ctx->qry.repo, "log", ctx->qry.path, NULL)); html("'>\n"); - add_hidden_formfields(1, 0, "log"); + cgit_add_hidden_formfields(1, 0, "log"); html(""); + for (i = 0; i < ctx->repo->max_stats; i++) + htmlf("", + periods[i].code, + period == &periods[i] ? " selected" : "", + periods[i].name); + html("

"); + } + html("Authors: "); + html(""); + html(""); + html(""); + html("
"); + print_authors(&authors, top, period); +} + diff --git a/ui-stats.h b/ui-stats.h new file mode 100644 index 0000000..4f13dba --- a/dev/null +++ b/ui-stats.h @@ -0,0 +1,27 @@ +#ifndef UI_STATS_H +#define UI_STATS_H + +#include "cgit.h" + +struct cgit_period { + const char code; + const char *name; + int max_periods; + int count; + + /* Convert a tm value to the first day in the period */ + void (*trunc)(struct tm *tm); + + /* Update tm value to start of next/previous period */ + void (*dec)(struct tm *tm); + void (*inc)(struct tm *tm); + + /* Pretty-print a tm value */ + char *(*pretty)(struct tm *tm); +}; + +extern int cgit_find_stats_period(const char *expr, struct cgit_period **period); + +extern void cgit_show_stats(struct cgit_context *ctx); + +#endif /* UI_STATS_H */ diff --git a/ui-tree.c b/ui-tree.c index 9876c99..4b8e7a0 100644 --- a/ui-tree.c +++ b/ui-tree.c @@ -109,6 +109,9 @@ static int ls_item(const unsigned char *sha1, const char *base, int baselen, html(""); cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, fullpath, 0, NULL, NULL, ctx.qry.showmsg); + if (ctx.repo->max_stats) + cgit_stats_link("stats", NULL, "button", ctx.qry.head, + fullpath); html("\n"); free(name); return 0; -- cgit v0.9.0.2