diff options
author | lookshe <github@lookshe.org> | 2016-07-12 09:22:30 +0200 |
---|---|---|
committer | lookshe <github@lookshe.org> | 2016-07-12 09:22:30 +0200 |
commit | 1787404b6a618d07200db241c004d1bedc92f874 (patch) | |
tree | aff8c654e8f3190210f80b4c886ee5a8e88e26fd | |
parent | 2209fe5157b431cf57898deb889acdcc704dda64 (diff) | |
parent | 40fbefba0514b33988d453aea05aa2b956e98f84 (diff) |
Merge branch 'master' into lookshe/masterlookshe/master
Conflicts:
filters/html-converters/md2html
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | README | 4 | ||||
-rw-r--r-- | cgit.c | 6 | ||||
-rw-r--r-- | cgit.css | 29 | ||||
-rw-r--r-- | cgit.h | 11 | ||||
-rw-r--r-- | cgit.mk | 12 | ||||
-rw-r--r-- | cgitrc.5.txt | 19 | ||||
-rw-r--r-- | cmd.c | 14 | ||||
-rw-r--r-- | filters/gentoo-ldap-authentication.lua | 2 | ||||
m--------- | git | 0 | ||||
-rw-r--r-- | parsing.c | 10 | ||||
-rw-r--r-- | scan-tree.c | 4 | ||||
-rw-r--r-- | shared.c | 1 | ||||
-rw-r--r-- | ui-atom.c | 6 | ||||
-rw-r--r-- | ui-commit.c | 6 | ||||
-rw-r--r-- | ui-diff.c | 2 | ||||
-rw-r--r-- | ui-log.c | 55 | ||||
-rw-r--r-- | ui-plain.c | 2 | ||||
-rw-r--r-- | ui-refs.c | 30 | ||||
-rw-r--r-- | ui-repolist.c | 2 | ||||
-rw-r--r-- | ui-shared.c | 97 | ||||
-rw-r--r-- | ui-shared.h | 6 | ||||
-rw-r--r-- | ui-stats.c | 21 | ||||
-rw-r--r-- | ui-tag.c | 3 |
24 files changed, 196 insertions, 150 deletions
@@ -1,6 +1,6 @@ all:: -CGIT_VERSION = v0.12 +CGIT_VERSION = v1.0 CGIT_SCRIPT_NAME = cgit.cgi CGIT_SCRIPT_PATH = /var/www/htdocs/cgit CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH) @@ -14,7 +14,7 @@ htmldir = $(docdir) pdfdir = $(docdir) mandir = $(prefix)/share/man SHA1_HEADER = <openssl/sha.h> -GIT_VER = 2.7.0 +GIT_VER = 2.9.0 GIT_URL = https://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.gz INSTALL = install COPYTREE = cp -r @@ -92,8 +92,8 @@ the HTTP headers `Modified` and `Expires`. Online presence --------------- -* The cgit homepage is hosted by cgit at <http://git.zx2c4.com/cgit/about/> +* The cgit homepage is hosted by cgit at <https://git.zx2c4.com/cgit/about/> * Patches, bug reports, discussions and support should go to the cgit mailing list: <cgit@lists.zx2c4.com>. To sign up, visit - <http://lists.zx2c4.com/mailman/listinfo/cgit> + <https://lists.zx2c4.com/mailman/listinfo/cgit> @@ -41,6 +41,8 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va repo->desc = xstrdup(value); else if (!strcmp(name, "owner")) repo->owner = xstrdup(value); + else if (!strcmp(name, "homepage")) + repo->homepage = xstrdup(value); else if (!strcmp(name, "defbranch")) repo->defbranch = xstrdup(value); else if (!strcmp(name, "snapshots")) @@ -795,6 +797,8 @@ static void print_repo(FILE *f, struct cgit_repo *repo) fprintf(f, "repo.module-link=%s\n", repo->module_link); if (repo->section) fprintf(f, "repo.section=%s\n", repo->section); + if (repo->homepage) + fprintf(f, "repo.homepage=%s\n", repo->homepage); if (repo->clone_url) fprintf(f, "repo.clone-url=%s\n", repo->clone_url); fprintf(f, "repo.enable-commit-graph=%d\n", @@ -939,7 +943,7 @@ static void cgit_parse_args(int argc, const char **argv) for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "--version")) { - printf("CGit %s | http://git.zx2c4.com/cgit/\n\nCompiled in features:\n", CGIT_VERSION); + printf("CGit %s | https://git.zx2c4.com/cgit/\n\nCompiled in features:\n", CGIT_VERSION); #ifdef NO_LUA printf("[-] "); #else @@ -18,7 +18,7 @@ div#cgit a:hover { } div#cgit table { - border-collapse: collapse; + border-collapse: collapse; } div#cgit table#header { @@ -85,6 +85,12 @@ div#cgit table.tabs td a.active { background-color: #ccc; } +div#cgit table.tabs a[href^="http://"]:after, div#cgit table.tabs a[href^="https://"]:after { + content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfgAhcJDQY+gm2TAAAAHWlUWHRDb21tZW50AAAAAABDcmVhdGVkIHdpdGggR0lNUGQuZQcAAABbSURBVAhbY2BABs4MU4CwhYHBh2Erww4wrGFQZHjI8B8IgUIscJWyDHcggltQhI4zGDCcRwhChPggHIggP1QoAVmQkSETrGoHsiAEsACtBYN0oDAMbgU6EBcAAL2eHUt4XUU4AAAAAElFTkSuQmCC); + opacity: 0.5; + margin: 0 0 0 5px; +} + div#cgit table.tabs td.form { text-align: right; } @@ -588,19 +594,31 @@ div#cgit span.age-months { div#cgit span.age-years { color: #bbb; } + +div#cgit span.insertions { + color: #080; +} + +div#cgit span.deletions { + color: #800; +} + div#cgit div.footer { margin-top: 0.5em; text-align: center; font-size: 80%; color: #ccc; } + div#cgit div.footer a { color: #ccc; text-decoration: none; } + div#cgit div.footer a:hover { text-decoration: underline; } + div#cgit a.branch-deco { color: #000; margin: 0px 0.5em; @@ -608,6 +626,7 @@ div#cgit a.branch-deco { background-color: #88ff88; border: solid 1px #007700; } + div#cgit a.tag-deco { color: #000; margin: 0px 0.5em; @@ -615,6 +634,7 @@ div#cgit a.tag-deco { background-color: #ffff88; border: solid 1px #777700; } + div#cgit a.remote-deco { color: #000; margin: 0px 0.5em; @@ -622,6 +642,7 @@ div#cgit a.remote-deco { background-color: #ccccff; border: solid 1px #000077; } + div#cgit a.deco { color: #000; margin: 0px 0.5em; @@ -801,9 +822,9 @@ div#cgit table.ssdiff td.head div.head { div#cgit table.ssdiff td.foot { border-top: solid 1px #aaa; - border-left: none; - border-right: none; - border-bottom: none; + border-left: none; + border-right: none; + border-bottom: none; } div#cgit table.ssdiff td.space { @@ -29,13 +29,6 @@ #undef isgraph #define isgraph(x) (isprint((x)) && !isspace((x))) -/* - * Dateformats used on misc. pages - */ -#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S (%Z)" -#define FMT_SHORTDATE "%Y-%m-%d" -#define FMT_ATOMDATE "%Y-%m-%dT%H:%M:%SZ" - /* * Limits used for relative dates @@ -88,6 +81,7 @@ struct cgit_repo { char *path; char *desc; char *owner; + char *homepage; char *defbranch; char *module_link; struct string_list readme; @@ -130,9 +124,11 @@ struct commitinfo { char *author; char *author_email; unsigned long author_date; + int author_tz; char *committer; char *committer_email; unsigned long committer_date; + int committer_tz; char *subject; char *msg; char *msg_encoding; @@ -142,6 +138,7 @@ struct taginfo { char *tagger; char *tagger_email; unsigned long tagger_date; + int tagger_tz; char *msg; }; @@ -21,6 +21,8 @@ CGIT_CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"' CGIT_CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"' CGIT_CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"' +PKG_CONFIG ?= pkg-config + ifdef NO_C99_FORMAT CFLAGS += -DNO_C99_FORMAT endif @@ -31,7 +33,7 @@ ifdef NO_LUA else ifeq ($(LUA_PKGCONFIG),) LUA_PKGCONFIG := $(shell for pc in luajit lua lua5.2 lua5.1; do \ - pkg-config --exists $$pc 2>/dev/null && echo $$pc && break; \ + $(PKG_CONFIG) --exists $$pc 2>/dev/null && echo $$pc && break; \ done) LUA_MODE := autodetected else @@ -39,8 +41,8 @@ else endif ifneq ($(LUA_PKGCONFIG),) LUA_MESSAGE := linking with $(LUA_MODE) $(LUA_PKGCONFIG) - LUA_LIBS := $(shell pkg-config --libs $(LUA_PKGCONFIG) 2>/dev/null) - LUA_CFLAGS := $(shell pkg-config --cflags $(LUA_PKGCONFIG) 2>/dev/null) + LUA_LIBS := $(shell $(PKG_CONFIG) --libs $(LUA_PKGCONFIG) 2>/dev/null) + LUA_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(LUA_PKGCONFIG) 2>/dev/null) CGIT_LIBS += $(LUA_LIBS) CGIT_CFLAGS += $(LUA_CFLAGS) else @@ -51,8 +53,8 @@ endif endif -# Add -ldl to linker flags on non-BSD systems. -ifeq ($(findstring BSD,$(uname_S)),) +# Add -ldl to linker flags on systems that commonly use GNU libc. +ifneq (,$(filter $(uname_S),Linux GNU/kFreeBSD)) CGIT_LIBS += -ldl endif diff --git a/cgitrc.5.txt b/cgitrc.5.txt index 47850a8..9fcf445 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@ -205,11 +205,11 @@ enable-git-config:: Flag which, when set to "1", will allow cgit to use git config to set any repo specific settings. This option is used in conjunction with "scan-path", and must be defined prior, to augment repo-specific - settings. The keys gitweb.owner, gitweb.category, and gitweb.description - will map to the cgit keys repo.owner, repo.section, and repo.desc, - respectively. All git config keys that begin with "cgit." will be mapped - to the corresponding "repo." key in cgit. Default value: "0". See also: - scan-path, section-from-path. + settings. The keys gitweb.owner, gitweb.category, gitweb.description, + and gitweb.homepage will map to the cgit keys repo.owner, repo.section, + repo.desc, and repo.homepage respectively. All git config keys that begin + with "cgit." will be mapped to the corresponding "repo." key in cgit. + Default value: "0". See also: scan-path, section-from-path. favicon:: Url used as link to a shortcut icon for cgit. It is suggested to use @@ -496,6 +496,9 @@ repo.defbranch:: repo.desc:: The value to show as repository description. Default value: none. +repo.homepage:: + The value to show as repository homepage. Default value: none. + repo.email-filter:: Override the default email-filter. Default value: none. See also: "enable-filter-overrides". See also: "FILTER API". @@ -520,7 +523,7 @@ repo.enable-subject-links:: A flag which can be used to override the global setting `enable-subject-links'. Default value: none. -enable-html-serving:: +repo.enable-html-serving:: A flag which can be used to override the global setting `enable-html-serving`. Default value: none. @@ -673,14 +676,14 @@ commit filter:: expected on standard output. email filter:: - This filter is given two parameters: the email address of the relevent + This filter is given two parameters: the email address of the relevant author and a string indicating the originating page. The filter will then receive the text string to format on standard input and is expected to write to standard output the formatted text to be included in the page. owner filter:: - This filter is given no arguments. The owner text is avilable on + This filter is given no arguments. The owner text is available on standard input and the filter is expected to write to standard output. The output is included in the Owner column. @@ -39,16 +39,26 @@ static void atom_fn(void) static void about_fn(void) { if (ctx.repo) { + size_t path_info_len = ctx.env.path_info ? strlen(ctx.env.path_info) : 0; if (!ctx.qry.path && ctx.qry.url[strlen(ctx.qry.url) - 1] != '/' && - ctx.env.path_info[strlen(ctx.env.path_info) - 1] != '/') { + (!path_info_len || ctx.env.path_info[path_info_len - 1] != '/')) { char *currenturl = cgit_currenturl(); char *redirect = fmtalloc("%s/", currenturl); cgit_redirect(redirect, true); free(currenturl); free(redirect); - } else + } else if (ctx.repo->readme.nr) cgit_print_repo_readme(ctx.qry.path); + else if (ctx.repo->homepage) + cgit_redirect(ctx.repo->homepage, false); + else { + char *currenturl = cgit_currenturl(); + char *redirect = fmtalloc("%s../", currenturl); + cgit_redirect(redirect, false); + free(currenturl); + free(redirect); + } } else cgit_print_site_readme(); } diff --git a/filters/gentoo-ldap-authentication.lua b/filters/gentoo-ldap-authentication.lua index fce5632..6d8eb3e 100644 --- a/filters/gentoo-ldap-authentication.lua +++ b/filters/gentoo-ldap-authentication.lua @@ -4,7 +4,7 @@ -- luacrypto >= 0.3 -- <http://mkottman.github.io/luacrypto/> -- lualdap >= 1.2 --- <http://git.zx2c4.com/lualdap/about/> +-- <https://git.zx2c4.com/lualdap/about/> -- diff --git a/git b/git -Subproject 754884255bb580df159e58defa81cdd30b5c430 +Subproject 05219a1276341e72d8082d76b7f5ed394b7437a @@ -69,7 +69,7 @@ static char *substr(const char *head, const char *tail) return buf; } -static void parse_user(const char *t, char **name, char **email, unsigned long *date) +static void parse_user(const char *t, char **name, char **email, unsigned long *date, int *tz) { struct ident_split ident; unsigned email_len; @@ -83,6 +83,8 @@ static void parse_user(const char *t, char **name, char **email, unsigned long * if (ident.date_begin) *date = strtoul(ident.date_begin, NULL, 10); + if (ident.tz_begin) + *tz = atoi(ident.tz_begin); } } @@ -147,13 +149,13 @@ struct commitinfo *cgit_parse_commit(struct commit *commit) if (p && skip_prefix(p, "author ", &p)) { parse_user(p, &ret->author, &ret->author_email, - &ret->author_date); + &ret->author_date, &ret->author_tz); p = next_header_line(p); } if (p && skip_prefix(p, "committer ", &p)) { parse_user(p, &ret->committer, &ret->committer_email, - &ret->committer_date); + &ret->committer_date, &ret->committer_tz); p = next_header_line(p); } @@ -208,7 +210,7 @@ struct taginfo *cgit_parse_tag(struct tag *tag) for (p = data; !end_of_header(p); p = next_header_line(p)) { if (skip_prefix(p, "tagger ", &p)) { parse_user(p, &ret->tagger, &ret->tagger_email, - &ret->tagger_date); + &ret->tagger_date, &ret->tagger_tz); } } diff --git a/scan-tree.c b/scan-tree.c index b5a10ff..1cb4e5d 100644 --- a/scan-tree.c +++ b/scan-tree.c @@ -61,6 +61,8 @@ static int gitconfig_config(const char *key, const char *value, void *cb) config_fn(repo, "desc", value); else if (!strcmp(key, "gitweb.category")) config_fn(repo, "section", value); + else if (!strcmp(key, "gitweb.homepage")) + config_fn(repo, "homepage", value); else if (starts_with(key, "cgit.")) config_fn(repo, key + 5, value); @@ -244,7 +246,7 @@ void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn projectsfile, strerror(errno), errno); return; } - while (strbuf_getline(&line, projects, '\n') != EOF) { + while (strbuf_getline(&line, projects) != EOF) { if (!line.len) continue; strbuf_insert(&line, 0, "/", 1); @@ -54,6 +54,7 @@ struct cgit_repo *cgit_add_repo(const char *url) ret->path = NULL; ret->desc = cgit_default_repo_desc; ret->owner = NULL; + ret->homepage = NULL; ret->section = ctx.cfg.section; ret->snapshots = ctx.cfg.snapshots; ret->enable_commit_graph = ctx.cfg.enable_commit_graph; @@ -25,7 +25,8 @@ static void add_entry(struct commit *commit, const char *host) html_txt(info->subject); html("</title>\n"); html("<updated>"); - cgit_print_date(info->committer_date, FMT_ATOMDATE, 0); + html_txt(show_date(info->committer_date, 0, + date_mode_from_type(DATE_ISO8601_STRICT))); html("</updated>\n"); html("<author>\n"); if (info->author) { @@ -50,7 +51,8 @@ static void add_entry(struct commit *commit, const char *host) } html("</author>\n"); html("<published>"); - cgit_print_date(info->author_date, FMT_ATOMDATE, 0); + html_txt(show_date(info->author_date, 0, + date_mode_from_type(DATE_ISO8601_STRICT))); html("</published>\n"); if (host) { char *pageurl; diff --git a/ui-commit.c b/ui-commit.c index d3f7922..e0b4297 100644 --- a/ui-commit.c +++ b/ui-commit.c @@ -55,7 +55,8 @@ void cgit_print_commit(char *hex, const char *prefix) } cgit_close_filter(ctx.repo->email_filter); html("</td><td class='right'>"); - cgit_print_date(info->author_date, FMT_LONGDATE, ctx.cfg.local_time); + html_txt(show_date(info->author_date, info->author_tz, + cgit_date_mode(DATE_ISO8601))); html("</td></tr>\n"); html("<tr><th>committer</th><td>"); cgit_open_filter(ctx.repo->email_filter, info->committer_email, "commit"); @@ -66,7 +67,8 @@ void cgit_print_commit(char *hex, const char *prefix) } cgit_close_filter(ctx.repo->email_filter); html("</td><td class='right'>"); - cgit_print_date(info->committer_date, FMT_LONGDATE, ctx.cfg.local_time); + html_txt(show_date(info->committer_date, info->committer_tz, + cgit_date_mode(DATE_ISO8601))); html("</td></tr>\n"); html("<tr><th>commit</th><td colspan='2' class='sha1'>"); tmp = oid_to_hex(&commit->object.oid); @@ -340,7 +340,7 @@ void cgit_print_diff_ctrls(void) html("<div class='cgit-panel'>"); html("<b>diff options</b>"); - html("<form method='get' action='.'>"); + html("<form method='get'>"); cgit_add_hidden_formfields(1, 0, ctx.qry.page); html("<table>"); html("<tr><td colspan='2'/></tr>"); @@ -61,38 +61,38 @@ void show_commit_decorations(struct commit *commit) buf[sizeof(buf) - 1] = 0; deco = get_name_decoration(&commit->object); + if (!deco) + return; html("<span class='decoration'>"); while (deco) { - if (starts_with(deco->name, "refs/heads/")) { - strncpy(buf, deco->name + 11, sizeof(buf) - 1); + strncpy(buf, prettify_refname(deco->name), sizeof(buf) - 1); + switch(deco->type) { + case DECORATION_NONE: + /* If the git-core doesn't recognize it, + * don't display anything. */ + break; + case DECORATION_REF_LOCAL: cgit_log_link(buf, NULL, "branch-deco", buf, NULL, - ctx.qry.vpath, 0, NULL, NULL, - ctx.qry.showmsg, 0); - } - else if (starts_with(deco->name, "tag: refs/tags/")) { - strncpy(buf, deco->name + 15, sizeof(buf) - 1); - cgit_tag_link(buf, NULL, "tag-deco", buf); - } - else if (starts_with(deco->name, "refs/tags/")) { - strncpy(buf, deco->name + 10, sizeof(buf) - 1); + ctx.qry.vpath, 0, NULL, NULL, + ctx.qry.showmsg, 0); + break; + case DECORATION_REF_TAG: cgit_tag_link(buf, NULL, "tag-deco", buf); - } - else if (starts_with(deco->name, "refs/remotes/")) { + break; + case DECORATION_REF_REMOTE: if (!ctx.repo->enable_remote_branches) - goto next; - strncpy(buf, deco->name + 13, sizeof(buf) - 1); + break; cgit_log_link(buf, NULL, "remote-deco", NULL, - oid_to_hex(&commit->object.oid), - ctx.qry.vpath, 0, NULL, NULL, - ctx.qry.showmsg, 0); - } - else { - strncpy(buf, deco->name, sizeof(buf) - 1); + oid_to_hex(&commit->object.oid), + ctx.qry.vpath, 0, NULL, NULL, + ctx.qry.showmsg, 0); + break; + default: cgit_commit_link(buf, NULL, "deco", ctx.qry.head, - oid_to_hex(&commit->object.oid), - ctx.qry.vpath); + oid_to_hex(&commit->object.oid), + ctx.qry.vpath); + break; } -next: deco = deco->next; } html("</span>"); @@ -204,7 +204,7 @@ static void print_commit(struct commit *commit, struct rev_info *revs) } else { html("<td>"); - cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); + cgit_print_age(info->committer_date, info->committer_tz, TM_WEEK * 2); html("</td>"); } @@ -244,7 +244,7 @@ static void print_commit(struct commit *commit, struct rev_info *revs) if (revs->graph) { html("</td><td>"); - cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); + cgit_print_age(info->committer_date, info->committer_tz, TM_WEEK * 2); } if (!lines_counted && (ctx.repo->enable_log_filecount || @@ -258,7 +258,8 @@ static void print_commit(struct commit *commit, struct rev_info *revs) if (ctx.repo->enable_log_filecount) htmlf("</td><td>%d", files); if (ctx.repo->enable_log_linecount) - htmlf("</td><td>-%d/+%d", rem_lines, add_lines); + htmlf("</td><td><span class='deletions'>-%d</span>/" + "<span class='insertions'>+%d</span>", rem_lines, add_lines); html("</td></tr>\n"); @@ -143,7 +143,7 @@ static int walk_tree(const unsigned char *sha1, struct strbuf *base, walk_tree_ctx->match = 2; return READ_TREE_RECURSIVE; } - } else if (base->len > walk_tree_ctx->match_baselen) { + } else if (base->len < INT_MAX && (int)base->len > walk_tree_ctx->match_baselen) { print_dir_entry(sha1, base->buf, base->len, pathname, mode); walk_tree_ctx->match = 2; } else if (S_ISDIR(mode)) { @@ -73,7 +73,7 @@ static int print_branch(struct refinfo *ref) cgit_author_link(info->author, name); cgit_close_filter(ctx.repo->email_filter); html("</td><td colspan='2'>"); - cgit_print_age(info->commit->date, -1, NULL); + cgit_print_age(info->committer_date, info->committer_tz, -1); } else { html("</td><td></td><td>"); cgit_object_link(ref->object); @@ -93,34 +93,28 @@ static void print_tag_header(void) static void print_tag_downloads(const struct cgit_repo *repo, const char *ref) { const struct cgit_snapshot_format* f; - struct strbuf filename = STRBUF_INIT; const char *basename; - int free_ref = 0; + struct strbuf filename = STRBUF_INIT; + size_t prefixlen; if (!ref || strlen(ref) < 1) return; basename = cgit_repobasename(repo->url); - if (!starts_with(ref, basename)) { - if ((ref[0] == 'v' || ref[0] == 'V') && isdigit(ref[1])) - ref++; - if (isdigit(ref[0])) { - ref = fmtalloc("%s-%s", basename, ref); - free_ref = 1; - } - } - + if (starts_with(ref, basename)) + strbuf_addstr(&filename, ref); + else + cgit_compose_snapshot_prefix(&filename, basename, ref); + prefixlen = filename.len; for (f = cgit_snapshot_formats; f->suffix; f++) { if (!(repo->snapshots & f->bit)) continue; - strbuf_reset(&filename); - strbuf_addf(&filename, "%s%s", ref, f->suffix); + strbuf_setlen(&filename, prefixlen); + strbuf_addstr(&filename, f->suffix); cgit_snapshot_link(filename.buf, NULL, NULL, NULL, NULL, filename.buf); html(" "); } - if (free_ref) - free((char *)ref); strbuf_release(&filename); } @@ -161,9 +155,9 @@ static int print_tag(struct refinfo *ref) html("</td><td colspan='2'>"); if (info) { if (info->tagger_date > 0) - cgit_print_age(info->tagger_date, -1, NULL); + cgit_print_age(info->tagger_date, info->tagger_tz, -1); } else if (ref->object->type == OBJ_COMMIT) { - cgit_print_age(ref->commit->commit->date, -1, NULL); + cgit_print_age(ref->commit->commit->date, 0, -1); } html("</td></tr>\n"); diff --git a/ui-repolist.c b/ui-repolist.c index 6010a39..30915df 100644 --- a/ui-repolist.c +++ b/ui-repolist.c @@ -79,7 +79,7 @@ static void print_modtime(struct cgit_repo *repo) { time_t t; if (get_repo_modtime(repo, &t)) - cgit_print_age(t, -1, NULL); + cgit_print_age(t, 0, -1); } static int is_match(struct cgit_repo *repo) diff --git a/ui-shared.c b/ui-shared.c index d978524..05b613e 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -12,8 +12,7 @@ #include "html.h" static const char cgit_doctype[] = -"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" -" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"; +"<!DOCTYPE html>\n"; static char *http_date(time_t t) { @@ -254,7 +253,7 @@ static char *repolink(const char *title, const char *class, const char *page, } delim = "&"; } - if (head && strcmp(head, ctx.repo->defbranch)) { + if (head && ctx.repo->defbranch && strcmp(head, ctx.repo->defbranch)) { html(delim); html("h="); html_url_arg(head); @@ -655,35 +654,23 @@ void cgit_submodule_link(const char *class, char *path, const char *rev) path[len - 1] = tail; } -static const char *fmt_date(time_t secs, const char *format, int local_time) +const struct date_mode *cgit_date_mode(enum date_mode_type type) { - static char buf[64]; - struct tm *time; - - if (!secs) - return ""; - if (local_time) - time = localtime(&secs); - else - time = gmtime(&secs); - strftime(buf, sizeof(buf)-1, format, time); - return buf; -} - -void cgit_print_date(time_t secs, const char *format, int local_time) -{ - html_txt(fmt_date(secs, format, local_time)); + static struct date_mode mode; + mode.type = type; + mode.local = ctx.cfg.local_time; + return &mode; } -static void print_rel_date(time_t t, double value, +static void print_rel_date(time_t t, int tz, double value, const char *class, const char *suffix) { htmlf("<span class='%s' title='", class); - html_attr(fmt_date(t, FMT_LONGDATE, ctx.cfg.local_time)); + html_attr(show_date(t, tz, cgit_date_mode(DATE_ISO8601))); htmlf("'>%.0f %s</span>", value, suffix); } -void cgit_print_age(time_t t, time_t max_relative, const char *format) +void cgit_print_age(time_t t, int tz, time_t max_relative) { time_t now, secs; @@ -696,34 +683,34 @@ void cgit_print_age(time_t t, time_t max_relative, const char *format) if (secs > max_relative && max_relative >= 0) { html("<span title='"); - html_attr(fmt_date(t, FMT_LONGDATE, ctx.cfg.local_time)); + html_attr(show_date(t, tz, cgit_date_mode(DATE_ISO8601))); html("'>"); - cgit_print_date(t, format, ctx.cfg.local_time); + html_txt(show_date(t, tz, cgit_date_mode(DATE_SHORT))); html("</span>"); return; } if (secs < TM_HOUR * 2) { - print_rel_date(t, secs * 1.0 / TM_MIN, "age-mins", "min."); + print_rel_date(t, tz, secs * 1.0 / TM_MIN, "age-mins", "min."); return; } if (secs < TM_DAY * 2) { - print_rel_date(t, secs * 1.0 / TM_HOUR, "age-hours", "hours"); + print_rel_date(t, tz, secs * 1.0 / TM_HOUR, "age-hours", "hours"); return; } if (secs < TM_WEEK * 2) { - print_rel_date(t, secs * 1.0 / TM_DAY, "age-days", "days"); + print_rel_date(t, tz, secs * 1.0 / TM_DAY, "age-days", "days"); return; } if (secs < TM_MONTH * 2) { - print_rel_date(t, secs * 1.0 / TM_WEEK, "age-weeks", "weeks"); + print_rel_date(t, tz, secs * 1.0 / TM_WEEK, "age-weeks", "weeks"); return; } if (secs < TM_YEAR * 2) { - print_rel_date(t, secs * 1.0 / TM_MONTH, "age-months", "months"); + print_rel_date(t, tz, secs * 1.0 / TM_MONTH, "age-months", "months"); return; } - print_rel_date(t, secs * 1.0 / TM_YEAR, "age-years", "years"); + print_rel_date(t, tz, secs * 1.0 / TM_YEAR, "age-years", "years"); } void cgit_print_http_headers(void) @@ -762,7 +749,6 @@ void cgit_redirect(const char *url, bool permanent) html("Location: "); html_url_path(url); html("\n\n"); - exit(0); } static void print_rel_vcs_link(const char *url) @@ -784,7 +770,7 @@ void cgit_print_docstart(void) char *host = cgit_hosturl(); html(cgit_doctype); - html("<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>\n"); + html("<html lang='en'>\n"); html("<head>\n"); html("<title>"); html_txt(ctx.page.title); @@ -838,9 +824,9 @@ void cgit_print_docend(void) if (ctx.cfg.footer) html_include(ctx.cfg.footer); else { - htmlf("<div class='footer'>generated by <a href='http://git.zx2c4.com/cgit/about/'>cgit %s</a> at ", + htmlf("<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit %s</a> at ", cgit_version); - cgit_print_date(time(NULL), FMT_LONGDATE, ctx.cfg.local_time); + html_txt(show_date(time(NULL), 0, cgit_date_mode(DATE_ISO8601))); html("</div>\n"); } html("</div> <!-- id=cgit -->\n"); @@ -853,13 +839,11 @@ void cgit_print_error_page(int code, const char *msg, const char *fmt, ...) ctx.page.expires = ctx.cfg.cache_dynamic_ttl; ctx.page.status = code; ctx.page.statusmsg = msg; - cgit_print_http_headers(); - cgit_print_docstart(); - cgit_print_pageheader(); + cgit_print_layout_start(); va_start(ap, fmt); cgit_vprint_error(fmt, ap); va_end(ap); - cgit_print_docend(); + cgit_print_layout_end(); } void cgit_print_layout_start(void) @@ -1001,14 +985,14 @@ static void print_header(void) cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL); if (ctx.env.authenticated) { html("</td><td class='form'>"); - html("<form method='get' action=''>\n"); + html("<form method='get'>\n"); cgit_add_hidden_formfields(0, 1, ctx.qry.page); html("<select name='h' onchange='this.form.submit();'>\n"); for_each_branch_ref(print_branch_option, ctx.qry.head); if (ctx.repo->enable_remote_branches) for_each_remote_ref(print_branch_option, ctx.qry.head); html("</select> "); - html("<input type='submit' name='' value='switch'/>"); + html("<input type='submit' value='switch'/>"); html("</form>"); } } else @@ -1057,6 +1041,11 @@ void cgit_print_pageheader(void) if (ctx.repo->max_stats) cgit_stats_link("stats", NULL, hc("stats"), ctx.qry.head, ctx.qry.vpath); + if (ctx.repo->homepage) { + html("<a href='"); + html_attr(ctx.repo->homepage); + html("'>homepage</a>"); + } html("</td><td class='form'>"); html("<form class='right' method='get' action='"); if (ctx.cfg.virtual_root) { @@ -1128,18 +1117,34 @@ void cgit_print_filemode(unsigned short mode) html_fileperm(mode); } +void cgit_compose_snapshot_prefix(struct strbuf *filename, const char *base, + const char *ref) +{ + unsigned char sha1[20]; + + /* + * Prettify snapshot names by stripping leading "v" or "V" if the tag + * name starts with {v,V}[0-9] and the prettify mapping is injective, + * i.e. each stripped tag can be inverted without ambiguities. + */ + if (get_sha1(fmt("refs/tags/%s", ref), sha1) == 0 && + (ref[0] == 'v' || ref[0] == 'V') && isdigit(ref[1]) && + ((get_sha1(fmt("refs/tags/%s", ref + 1), sha1) == 0) + + (get_sha1(fmt("refs/tags/v%s", ref + 1), sha1) == 0) + + (get_sha1(fmt("refs/tags/V%s", ref + 1), sha1) == 0) == 1)) + ref++; + + strbuf_addf(filename, "%s-%s", base, ref); +} + void cgit_print_snapshot_links(const char *repo, const char *head, const char *hex, int snapshots) { const struct cgit_snapshot_format* f; struct strbuf filename = STRBUF_INIT; size_t prefixlen; - unsigned char sha1[20]; - if (get_sha1(fmt("refs/tags/%s", hex), sha1) == 0 && - (hex[0] == 'v' || hex[0] == 'V') && isdigit(hex[1])) - hex++; - strbuf_addf(&filename, "%s-%s", cgit_repobasename(repo), hex); + cgit_compose_snapshot_prefix(&filename, cgit_repobasename(repo), hex); prefixlen = filename.len; for (f = cgit_snapshot_formats; f->suffix; f++) { if (!(snapshots & f->bit)) diff --git a/ui-shared.h b/ui-shared.h index 6b4f9aa..aadc271 100644 --- a/ui-shared.h +++ b/ui-shared.h @@ -70,8 +70,8 @@ __attribute__((format (printf,1,2))) extern void cgit_print_error(const char *fmt, ...); __attribute__((format (printf,1,0))) extern void cgit_vprint_error(const char *fmt, va_list ap); -extern void cgit_print_date(time_t secs, const char *format, int local_time); -extern void cgit_print_age(time_t t, time_t max_relative, const char *format); +extern const struct date_mode *cgit_date_mode(enum date_mode_type type); +extern void cgit_print_age(time_t t, int tz, time_t max_relative); extern void cgit_print_http_headers(void); extern void cgit_redirect(const char *url, bool permanent); extern void cgit_print_docstart(void); @@ -80,6 +80,8 @@ __attribute__((format (printf,3,4))) extern void cgit_print_error_page(int code, const char *msg, const char *fmt, ...); extern void cgit_print_pageheader(void); extern void cgit_print_filemode(unsigned short mode); +extern void cgit_compose_snapshot_prefix(struct strbuf *filename, + const char *base, const char *ref); extern void cgit_print_snapshot_links(const char *repo, const char *head, const char *hex, int snapshots); extern void cgit_add_hidden_formfields(int incl_head, int incl_search, @@ -3,12 +3,6 @@ #include "html.h" #include "ui-shared.h" -#ifdef NO_C99_FORMAT -#define SZ_FMT "%u" -#else -#define SZ_FMT "%zu" -#endif - struct authorstat { long total; struct string_list list; @@ -174,6 +168,7 @@ static void add_commit(struct string_list *authors, struct commit *commit, char *tmp; struct tm *date; time_t t; + uintptr_t *counter; info = cgit_parse_commit(commit); tmp = xstrdup(info->author); @@ -189,9 +184,11 @@ static void add_commit(struct string_list *authors, struct commit *commit, period->trunc(date); tmp = xstrdup(period->pretty(date)); item = string_list_insert(items, tmp); - if (item->util) + counter = (uintptr_t *)&item->util; + if (*counter) free(tmp); - item->util++; + (*counter)++; + authorstat->total++; cgit_free_commitinfo(info); } @@ -286,7 +283,7 @@ static void print_combined_authorrow(struct string_list *authors, int from, items = &authorstat->list; date = string_list_lookup(items, tmp); if (date) - subtotal += (size_t)date->util; + subtotal += (uintptr_t)date->util; } htmlf("<td class='%s'>%ld</td>", centerclass, subtotal); total += subtotal; @@ -340,8 +337,8 @@ static void print_authors(struct string_list *authors, int top, if (!date) html("<td>0</td>"); else { - htmlf("<td>"SZ_FMT"</td>", (size_t)date->util); - total += (size_t)date->util; + htmlf("<td>%lu</td>", (uintptr_t)date->util); + total += (uintptr_t)date->util; } } htmlf("<td class='sum'>%ld</td></tr>", total); @@ -392,7 +389,7 @@ void cgit_show_stats(void) cgit_print_layout_start(); html("<div class='cgit-panel'>"); html("<b>stat options</b>"); - html("<form method='get' action=''>"); + html("<form method='get'>"); cgit_add_hidden_formfields(1, 0, "stats"); html("<table><tr><td colspan='2'/></tr>"); if (ctx.repo->max_stats > 1) { @@ -76,7 +76,8 @@ void cgit_print_tag(char *revname) htmlf(" (%s)</td></tr>\n", sha1_to_hex(sha1)); if (info->tagger_date > 0) { html("<tr><td>tag date</td><td>"); - cgit_print_date(info->tagger_date, FMT_LONGDATE, ctx.cfg.local_time); + html_txt(show_date(info->tagger_date, info->tagger_tz, + cgit_date_mode(DATE_ISO8601))); html("</td></tr>\n"); } if (info->tagger) { |