Merge branch 'master' into lookshe/master

Conflicts:
	filters/html-converters/md2html
This commit is contained in:
lookshe 2016-07-12 09:22:30 +02:00
commit 1787404b6a
24 changed files with 197 additions and 151 deletions

View file

@ -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

4
README
View file

@ -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>

6
cgit.c
View file

@ -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

View file

@ -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 {

11
cgit.h
View file

@ -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;
};

12
cgit.mk
View file

@ -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

View file

@ -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.

14
cmd.c
View file

@ -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();
}

View file

@ -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/>
--

2
git

@ -1 +1 @@
Subproject commit 754884255bb580df159e58defa81cdd30b5c430c
Subproject commit 05219a1276341e72d8082d76b7f5ed394b7437a4

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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>");

View file

@ -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);
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/tags/")) {
strncpy(buf, deco->name + 10, sizeof(buf) - 1);
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");

View file

@ -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)) {

View file

@ -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("&nbsp;&nbsp;");
}
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");

View file

@ -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)

View file

@ -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 = "&amp;";
}
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;
static struct date_mode mode;
mode.type = type;
mode.local = ctx.cfg.local_time;
return &mode;
}
void cgit_print_date(time_t secs, const char *format, int local_time)
{
html_txt(fmt_date(secs, format, local_time));
}
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))

View file

@ -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,

View file

@ -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) {

View file

@ -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) {