From: Lars Hjemli Date: Tue, 27 Jan 2009 19:16:37 +0000 (+0100) Subject: Merge branch 'lh/stats' X-Git-Url: https://gitweb.ps.run/ps-cgit/commitdiff_plain/7710178e45dee61e85ea77c4221309ce8c086f95?ds=sidebyside;hp=-c Merge branch 'lh/stats' Conflicts: cgit.c cgit.css cgit.h ui-tree.c Signed-off-by: Lars Hjemli --- 7710178e45dee61e85ea77c4221309ce8c086f95 diff --combined Makefile index 7793c0b,f426f98..a52285e --- a/Makefile +++ b/Makefile @@@ -1,33 -1,11 +1,33 @@@ CGIT_VERSION = v0.8.1 CGIT_SCRIPT_NAME = cgit.cgi CGIT_SCRIPT_PATH = /var/www/htdocs/cgit +CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH) CGIT_CONFIG = /etc/cgitrc CACHE_ROOT = /var/cache/cgit SHA1_HEADER = -GIT_VER = 1.6.0.2 +GIT_VER = 1.6.1 GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2 +INSTALL = install + +# Define NO_STRCASESTR if you don't have strcasestr. +# +# Define NEEDS_LIBICONV if linking with libc is not enough (eg. Darwin). +# + +#-include config.mak + +# +# Platform specific tweaks +# + +uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') +uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not') +uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') + +ifeq ($(uname_O),Cygwin) + NO_STRCASESTR = YesPlease + NEEDS_LIBICONV = YesPlease +endif # # Let the user override the above settings. @@@ -90,6 -68,7 +90,7 @@@ OBJECTS += ui-refs. 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 @@@ -118,9 -97,6 +119,9 @@@ CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_R ifdef NO_ICONV CFLAGS += -DNO_ICONV endif +ifdef NO_STRCASESTR + CFLAGS += -DNO_STRCASESTR +endif cgit: $(OBJECTS) libgit $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS) @@@ -130,23 -106,22 +131,23 @@@ cgit.o: VERSIO -include $(OBJECTS:.o=.d) libgit: - $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) libgit.a - $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) xdiff/lib.a + $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 libgit.a + $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 xdiff/lib.a test: all $(QUIET_SUBDIR0)tests $(QUIET_SUBDIR1) all install: all - mkdir -p $(DESTDIR)$(CGIT_SCRIPT_PATH) - install cgit $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) - install cgit.css $(DESTDIR)$(CGIT_SCRIPT_PATH)/cgit.css - install cgit.png $(DESTDIR)$(CGIT_SCRIPT_PATH)/cgit.png + $(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_SCRIPT_PATH) + $(INSTALL) -m 0755 cgit $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) + $(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_DATA_PATH) + $(INSTALL) -m 0644 cgit.css $(DESTDIR)$(CGIT_DATA_PATH)/cgit.css + $(INSTALL) -m 0644 cgit.png $(DESTDIR)$(CGIT_DATA_PATH)/cgit.png uninstall: rm -f $(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) - rm -f $(CGIT_SCRIPT_PATH)/cgit.css - rm -f $(CGIT_SCRIPT_PATH)/cgit.png + rm -f $(CGIT_DATA_PATH)/cgit.css + rm -f $(CGIT_DATA_PATH)/cgit.png clean: rm -f cgit VERSION *.o *.d diff --combined cgit.c index f35f605,57e11cd..608cab6 --- a/cgit.c +++ b/cgit.c @@@ -12,6 -12,7 +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 +55,8 @@@ void config_cb(const char *name, const 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 +115,8 @@@ 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) { @@@ -154,10 -159,8 +159,12 @@@ static void querystring_cb(const char * ctx.qry.name = xstrdup(value); } else if (!strcmp(name, "mimetype")) { ctx.qry.mimetype = xstrdup(value); + } else if (!strcmp(name, "s")){ + 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 -184,7 +188,7 @@@ static void prepare_context(struct cgit 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"; @@@ -293,6 -297,7 +301,6 @@@ static void process_request(void *cbdat cmd = cgit_get_cmd(ctx); if (!cmd) { ctx->page.title = "cgit error"; - ctx->repo = NULL; cgit_print_http_headers(ctx); cgit_print_docstart(ctx); cgit_print_pageheader(ctx); @@@ -438,29 -443,28 +446,29 @@@ int main(int argc, const char **argv ctx.repo = NULL; http_parse_querystring(ctx.qry.raw, querystring_cb); - /* If virtual-root isn't specified in cgitrc and no url - * parameter is specified on the querystring, lets pretend - * that virtualroot equals SCRIPT_NAME and use PATH_INFO as - * url. This allows cgit to work with virtual urls without - * the need for rewriterules in the webserver (as long as - * PATH_INFO is included in the cache lookup key). + /* If virtual-root isn't specified in cgitrc, lets pretend + * that virtual-root equals SCRIPT_NAME. */ - if (!ctx.cfg.virtual_root && !ctx.qry.url) { + if (!ctx.cfg.virtual_root) ctx.cfg.virtual_root = ctx.cfg.script_name; - path = getenv("PATH_INFO"); - if (path) { - if (path[0] == '/') - path++; - ctx.qry.url = xstrdup(path); - if (ctx.qry.raw) { - qry = ctx.qry.raw; - ctx.qry.raw = xstrdup(fmt("%s?%s", path, qry)); - free(qry); - } else - ctx.qry.raw = ctx.qry.url; - cgit_parse_url(ctx.qry.url); - } + + /* If no url parameter is specified on the querystring, lets + * use PATH_INFO as url. This allows cgit to work with virtual + * urls without the need for rewriterules in the webserver (as + * long as PATH_INFO is included in the cache lookup key). + */ + path = getenv("PATH_INFO"); + if (!ctx.qry.url && path) { + if (path[0] == '/') + path++; + ctx.qry.url = xstrdup(path); + if (ctx.qry.raw) { + qry = ctx.qry.raw; + ctx.qry.raw = xstrdup(fmt("%s?%s", path, qry)); + free(qry); + } else + ctx.qry.raw = ctx.qry.url; + cgit_parse_url(ctx.qry.url); } ttl = calc_ttl(); diff --combined cgit.css index f19446d,ef30fbf..e8214de --- a/cgit.css +++ b/cgit.css @@@ -120,10 -120,6 +120,10 @@@ table.list tr background: white; } +table.list tr.logheader { + background: #eee; +} + table.list tr:hover { background: #eee; } @@@ -147,17 -143,6 +147,17 @@@ table.list td padding: 0.1em 0.5em 0.1em 0.5em; } +table.list td.logsubject { + font-family: monospace; + font-weight: bold; +} + +table.list td.logmsg { + font-family: monospace; + white-space: pre; + padding: 1em 0em 2em 0em; +} + table.list td a { color: black; } @@@ -471,27 -456,80 +471,103 @@@ div.footer font-size: 80%; color: #ccc; } +a.branch-deco { + margin: 0px 0.5em; + padding: 0px 0.25em; + background-color: #88ff88; + border: solid 1px #007700; +} +a.tag-deco { + margin: 0px 0.5em; + padding: 0px 0.25em; + background-color: #ffff88; + border: solid 1px #777700; +} +a.remote-deco { + margin: 0px 0.5em; + padding: 0px 0.25em; + background-color: #ccccff; + border: solid 1px #000077; +} +a.deco { + margin: 0px 0.5em; + padding: 0px 0.25em; + 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 --combined cgit.h index cb2f176,f2cb671..4fe94c6 --- a/cgit.h +++ b/cgit.h @@@ -61,7 -61,7 +61,8 @@@ struct cgit_repo int snapshots; int enable_log_filecount; int enable_log_linecount; + int max_stats; + time_t mtime; }; struct cgit_repolist { @@@ -120,10 -120,9 +121,11 @@@ struct cgit_query char *name; char *mimetype; char *url; + char *period; int ofs; int nohead; + char *sort; + int showmsg; }; struct cgit_config { @@@ -160,6 -159,7 +162,7 @@@ int max_lock_attempts; int max_msg_len; int max_repodesc_len; + int max_stats; int nocache; int renamelimit; int snapshots; @@@ -236,5 -236,11 +239,5 @@@ extern const char *cgit_repobasename(co extern int cgit_parse_snapshots_mask(const char *str); -/* libgit.a either links against or compiles its own implementation of - * strcasestr(), and we'd like to reuse it. Simply re-declaring it - * seems to do the trick. - */ -extern char *strcasestr(const char *haystack, const char *needle); - #endif /* CGIT_H */ diff --combined cgitrc.5.txt index ab9ab66,0bbbea3..09f56a6 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@@ -129,6 -129,11 +129,11 @@@ max-repodesc-lengt 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 +223,11 @@@ repo.enable-log-linecoun 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 +286,10 @@@ favicon=/favicon.ic 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 @@@ -288,8 -302,8 +302,8 @@@ root-desc=tracking the foobar developme root-readme=/var/www/htdocs/about.html -# Allow download of tar.gz, tar.bz and zip-files -snapshots=tar.gz tar.bz zip +# Allow download of tar.gz, tar.bz2 and zip-files +snapshots=tar.gz tar.bz2 zip ## @@@ -348,6 -362,9 +362,9 @@@ repo.snapshots= # 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 --combined cmd.c index 8914fa5,763a558..cf97da7 --- a/cmd.c +++ b/cmd.c @@@ -21,6 -21,7 +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" @@@ -104,10 -105,16 +105,15 @@@ static void refs_fn(struct cgit_contex static void snapshot_fn(struct cgit_context *ctx) { - cgit_print_snapshot(ctx->qry.head, ctx->qry.sha1, - cgit_repobasename(ctx->repo->url), ctx->qry.path, + cgit_print_snapshot(ctx->qry.head, ctx->qry.sha1, ctx->qry.path, 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 -151,7 +150,7 @@@ struct cgit_cmd *cgit_get_cmd(struct cg 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 --combined shared.c index a764c4d,7382609..578a544 --- a/shared.c +++ b/shared.c @@@ -58,9 -58,9 +58,10 @@@ struct cgit_repo *cgit_add_repo(const c 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; return ret; } @@@ -267,12 -267,10 +268,12 @@@ int cgit_diff_files(const unsigned cha if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) return 1; + memset(&diff_params, 0, sizeof(diff_params)); + memset(&emit_params, 0, sizeof(emit_params)); + memset(&emit_cb, 0, sizeof(emit_cb)); diff_params.flags = XDF_NEED_MINIMAL; emit_params.ctxlen = 3; emit_params.flags = XDL_EMIT_FUNCNAMES; - emit_params.find_func = NULL; emit_cb.outf = filediff_cb; emit_cb.priv = fn; xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); diff --combined ui-shared.c index fba1ba6,1bb30c2..4f28512 --- a/ui-shared.c +++ b/ui-shared.c @@@ -281,8 -281,7 +281,8 @@@ void cgit_plain_link(char *name, char * } void cgit_log_link(char *name, char *title, char *class, char *head, - char *rev, char *path, int ofs, char *grep, char *pattern) + char *rev, char *path, int ofs, char *grep, char *pattern, + int showmsg) { char *delim; @@@ -306,11 -305,6 +306,11 @@@ html(delim); html("ofs="); htmlf("%d", ofs); + delim = "&"; + } + if (showmsg) { + html(delim); + html("showmsg=1"); } html("'>"); html_txt(name); @@@ -369,16 -363,19 +369,22 @@@ void cgit_patch_link(char *name, char * 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, *rev, *name; + char *page, *shortrev, *fullrev, *name; + fullrev = sha1_to_hex(obj->sha1); + shortrev = xstrdup(fullrev); + shortrev[10] = '\0'; if (obj->type == OBJ_COMMIT) { - cgit_commit_link(fmt("commit %s", sha1_to_hex(obj->sha1)), NULL, NULL, - ctx.qry.head, sha1_to_hex(obj->sha1)); + cgit_commit_link(fmt("commit %s...", shortrev), NULL, NULL, + ctx.qry.head, fullrev); return; } else if (obj->type == OBJ_TREE) page = "tree"; @@@ -386,8 -383,9 +392,8 @@@ page = "tag"; else page = "blob"; - rev = sha1_to_hex(obj->sha1); - name = fmt("%s %s", typename(obj->type), rev); - reporevlink(page, name, NULL, NULL, ctx.qry.head, rev, NULL); + name = fmt("%s %s...", typename(obj->type), shortrev); + reporevlink(page, name, NULL, NULL, ctx.qry.head, fullrev, NULL); } void cgit_print_date(time_t secs, char *format, int local_time) @@@ -557,7 -555,7 +563,7 @@@ int print_archive_ref(const char *refna 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; @@@ -576,8 -574,6 +582,8 @@@ html_hidden("id", ctx.qry.sha1); if (ctx.qry.sha2) html_hidden("id2", ctx.qry.sha2); + if (ctx.qry.showmsg) + html_hidden("showmsg", "1"); if (incl_search) { if (ctx.qry.grep) @@@ -587,20 -583,15 +593,20 @@@ } } +const char *fallback_cmd = "repolist"; + char *hc(struct cgit_cmd *cmd, const char *page) { - return (strcmp(cmd->name, page) ? NULL : "active"); + return (strcmp(cmd ? cmd->name : fallback_cmd, page) ? NULL : "active"); } void cgit_print_pageheader(struct cgit_context *ctx) { struct cgit_cmd *cmd = cgit_get_cmd(ctx); + if (!cmd && ctx->repo) + fallback_cmd = "summary"; + html("\n"); html("\n"); html("\n"); html("\n"); } @@@ -108,7 -106,10 +108,10 @@@ static int ls_item(const unsigned char html(""); cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, - fullpath, 0, NULL, NULL); + 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;