diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | cgit.c | 4 | ||||
-rw-r--r-- | cgit.css | 14 | ||||
-rw-r--r-- | cgit.h | 11 | ||||
-rw-r--r-- | cgitrc.5.txt | 15 | ||||
-rw-r--r-- | cmd.c | 14 | ||||
-rwxr-xr-x | filters/html-converters/md2html | 6 | ||||
m--------- | git | 0 | ||||
-rw-r--r-- | parsing.c | 10 | ||||
-rw-r--r-- | scan-tree.c | 2 | ||||
-rw-r--r-- | shared.c | 1 | ||||
-rw-r--r-- | ui-atom.c | 6 | ||||
-rw-r--r-- | ui-commit.c | 6 | ||||
-rw-r--r-- | ui-log.c | 4 | ||||
-rw-r--r-- | ui-plain.c | 2 | ||||
-rw-r--r-- | ui-refs.c | 6 | ||||
-rw-r--r-- | ui-repolist.c | 2 | ||||
-rw-r--r-- | ui-shared.c | 52 | ||||
-rw-r--r-- | ui-shared.h | 4 | ||||
-rw-r--r-- | ui-stats.c | 19 | ||||
-rw-r--r-- | ui-tag.c | 3 |
21 files changed, 103 insertions, 80 deletions
@@ -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.7.2 GIT_URL = https://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.gz INSTALL = install COPYTREE = cp -r @@ -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")) @@ -793,6 +795,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", @@ -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; } @@ -797,9 +803,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; }; diff --git a/cgitrc.5.txt b/cgitrc.5.txt index 47850a8..2e1912d 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. @@ -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/html-converters/md2html b/filters/html-converters/md2html index 67141ba..c8ee7d9 100755 --- a/filters/html-converters/md2html +++ b/filters/html-converters/md2html @@ -1,5 +1,6 @@ #!/usr/bin/env python import markdown +from pygments.formatters import HtmlFormatter print(''' <style> .markdown-body { @@ -277,9 +278,12 @@ print(''' background-color: transparent; border: none; } +''') +print(HtmlFormatter(style='pastie').get_style_defs('.highlight')) +print(''' </style> ''') print("<div class='markdown-body'>") # Note: you may want to run this through bleach for sanitization -markdown.markdownFromFile(output_format="html5") +markdown.markdownFromFile(output_format="html5", extensions=["markdown.extensions.fenced_code", "markdown.extensions.codehilite", "markdown.extensions.tables"], extension_configs={"markdown.extensions.codehilite":{"css_class":"highlight"}}) print("</div>") diff --git a/git b/git -Subproject 754884255bb580df159e58defa81cdd30b5c430 +Subproject 326e5bc91eecf73234ead29636207bc516573e7 @@ -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..2e87999 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); @@ -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 0c3d740..099d294 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); @@ -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 || @@ -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) html_txt(info->author); 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); @@ -161,9 +161,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 54bbde7..9a38aa9 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -607,35 +607,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; @@ -648,34 +636,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) @@ -714,7 +702,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) @@ -792,7 +779,7 @@ void cgit_print_docend(void) else { htmlf("<div class='footer'>generated by <a href='http://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"); @@ -1009,6 +996,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) { diff --git a/ui-shared.h b/ui-shared.h index de08e1b..b457c97 100644 --- a/ui-shared.h +++ b/ui-shared.h @@ -61,8 +61,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); @@ -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); @@ -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) { |