summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--Makefile4
-rw-r--r--cgit.c41
-rw-r--r--cgit.css24
-rwxr-xr-xtests/t0104-tree.sh2
-rw-r--r--ui-log.c35
-rw-r--r--ui-patch.c4
-rw-r--r--ui-refs.c2
-rw-r--r--ui-tree.c6
8 files changed, 90 insertions, 28 deletions
diff --git a/Makefile b/Makefile
index 3c7ec07..036fcd7 100644
--- a/Makefile
+++ b/Makefile
@@ -107,46 +107,46 @@ VERSION: force-version
CFLAGS += -g -Wall -Igit
CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)'
CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"'
CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"'
CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"'
CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"'
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)
cgit.o: VERSION
-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 -m 0644 cgit.css $(DESTDIR)$(CGIT_SCRIPT_PATH)/cgit.css
install -m 0644 cgit.png $(DESTDIR)$(CGIT_SCRIPT_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
clean:
rm -f cgit VERSION *.o *.d
get-git:
curl $(GIT_URL) | tar -xj && rm -rf git && mv git-$(GIT_VER) git
diff --git a/cgit.c b/cgit.c
index 166fbc6..d1cee58 100644
--- a/cgit.c
+++ b/cgit.c
@@ -418,59 +418,60 @@ static int calc_ttl()
}
int main(int argc, const char **argv)
{
const char *cgit_config_env = getenv("CGIT_CONFIG");
const char *path;
char *qry;
int err, ttl;
prepare_context(&ctx);
cgit_repolist.length = 0;
cgit_repolist.count = 0;
cgit_repolist.repos = NULL;
if (getenv("SCRIPT_NAME"))
ctx.cfg.script_name = xstrdup(getenv("SCRIPT_NAME"));
if (getenv("QUERY_STRING"))
ctx.qry.raw = xstrdup(getenv("QUERY_STRING"));
cgit_parse_args(argc, argv);
parse_configfile(cgit_config_env ? cgit_config_env : CGIT_CONFIG,
config_cb);
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();
ctx.page.expires += ttl*60;
if (ctx.cfg.nocache)
ctx.cfg.cache_size = 0;
err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root,
ctx.qry.raw, ttl, process_request, &ctx);
if (err)
cgit_print_error(fmt("Error processing page: %s (%d)",
strerror(err), err));
return err;
}
diff --git a/cgit.css b/cgit.css
index 7928c2f..f19446d 100644
--- a/cgit.css
+++ b/cgit.css
@@ -450,24 +450,48 @@ span.age-hours {
color: #080;
}
span.age-days {
color: #040;
}
span.age-weeks {
color: #444;
}
span.age-months {
color: #888;
}
span.age-years {
color: #bbb;
}
div.footer {
margin-top: 0.5em;
text-align: center;
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;
+}
diff --git a/tests/t0104-tree.sh b/tests/t0104-tree.sh
index 0d62cc8..33f4eb0 100755
--- a/tests/t0104-tree.sh
+++ b/tests/t0104-tree.sh
@@ -1,33 +1,33 @@
#!/bin/sh
. ./setup.sh
prepare_tests "Check content on tree page"
run_test 'generate bar/tree' 'cgit_url "bar/tree" >trash/tmp'
run_test 'find file-1' 'grep -e "file-1" trash/tmp'
run_test 'find file-50' 'grep -e "file-50" trash/tmp'
run_test 'generate bar/tree/file-50' 'cgit_url "bar/tree/file-50" >trash/tmp'
run_test 'find line 1' '
grep -e "<a id=.n1. name=.n1. href=.#n1.>1</a>" trash/tmp
'
run_test 'no line 2' '
- grep -e "<a id=.n2. name=.n2. href=.#n2.>2</a>" trash/tmp
+ ! grep -e "<a id=.n2. name=.n2. href=.#n2.>2</a>" trash/tmp
'
run_test 'generate foo+bar/tree' 'cgit_url "foo%2bbar/tree" >trash/tmp'
run_test 'verify a+b link' '
grep -e "/foo+bar/tree/a+b" trash/tmp
'
run_test 'generate foo+bar/tree?h=1+2' 'cgit_url "foo%2bbar/tree&h=1%2b2" >trash/tmp'
run_test 'verify a+b?h=1+2 link' '
grep -e "/foo+bar/tree/a+b?h=1%2b2" trash/tmp
'
tests_done
diff --git a/ui-log.c b/ui-log.c
index 2f90778..c3757dd 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -10,66 +10,99 @@
#include "html.h"
#include "ui-shared.h"
int files, add_lines, rem_lines;
void count_lines(char *line, int size)
{
if (size <= 0)
return;
if (line[0] == '+')
add_lines++;
else if (line[0] == '-')
rem_lines++;
}
void inspect_files(struct diff_filepair *pair)
{
files++;
if (ctx.repo->enable_log_linecount)
cgit_diff_files(pair->one->sha1, pair->two->sha1, count_lines);
}
+void show_commit_decorations(struct commit *commit)
+{
+ struct name_decoration *deco;
+ static char buf[1024];
+
+ buf[sizeof(buf) - 1] = 0;
+ deco = lookup_decoration(&name_decoration, &commit->object);
+ while (deco) {
+ if (!prefixcmp(deco->name, "refs/heads/")) {
+ strncpy(buf, deco->name + 11, sizeof(buf) - 1);
+ cgit_log_link(buf, NULL, "branch-deco", buf, NULL, NULL,
+ 0, NULL, NULL, ctx.qry.showmsg);
+ }
+ else if (!prefixcmp(deco->name, "tag: refs/tags/")) {
+ strncpy(buf, deco->name + 15, sizeof(buf) - 1);
+ cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf);
+ }
+ else if (!prefixcmp(deco->name, "refs/remotes/")) {
+ strncpy(buf, deco->name + 13, sizeof(buf) - 1);
+ cgit_log_link(buf, NULL, "remote-deco", NULL,
+ sha1_to_hex(commit->object.sha1), NULL,
+ 0, NULL, NULL, ctx.qry.showmsg);
+ }
+ else {
+ strncpy(buf, deco->name, sizeof(buf) - 1);
+ cgit_commit_link(buf, NULL, "deco", ctx.qry.head,
+ sha1_to_hex(commit->object.sha1));
+ }
+ deco = deco->next;
+ }
+}
+
void print_commit(struct commit *commit)
{
struct commitinfo *info;
char *tmp;
int cols = 2;
info = cgit_parse_commit(commit);
htmlf("<tr%s><td>",
ctx.qry.showmsg ? " class='logheader'" : "");
tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1));
tmp = cgit_pageurl(ctx.repo->url, "commit", tmp);
html_link_open(tmp, NULL, NULL);
cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE);
html_link_close();
htmlf("</td><td%s>",
ctx.qry.showmsg ? " class='logsubject'" : "");
cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head,
sha1_to_hex(commit->object.sha1));
+ show_commit_decorations(commit);
html("</td><td>");
html_txt(info->author);
if (ctx.repo->enable_log_filecount) {
files = 0;
add_lines = 0;
rem_lines = 0;
cgit_diff_commit(commit, inspect_files);
html("</td><td>");
htmlf("%d", files);
if (ctx.repo->enable_log_linecount) {
html("</td><td>");
htmlf("-%d/+%d", rem_lines, add_lines);
}
}
html("</td></tr>\n");
if (ctx.qry.showmsg) {
if (ctx.repo->enable_log_filecount) {
cols++;
if (ctx.repo->enable_log_linecount)
cols++;
}
htmlf("<tr class='nohover'><td/><td colspan='%d' class='logmsg'>",
cols);
html_txt(info->msg);
@@ -98,48 +131,50 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern
const char *argv[] = {NULL, NULL, NULL, NULL, NULL};
int argc = 2;
int i, columns = 3;
if (!tip)
tip = ctx.qry.head;
argv[1] = disambiguate_ref(tip);
if (grep && pattern && (!strcmp(grep, "grep") ||
!strcmp(grep, "author") ||
!strcmp(grep, "committer")))
argv[argc++] = fmt("--%s=%s", grep, pattern);
if (path) {
argv[argc++] = "--";
argv[argc++] = path;
}
init_revisions(&rev, NULL);
rev.abbrev = DEFAULT_ABBREV;
rev.commit_format = CMIT_FMT_DEFAULT;
rev.verbose_header = 1;
rev.show_root_diff = 0;
setup_revisions(argc, argv, &rev, NULL);
+ load_ref_decorations();
+ rev.show_decorations = 1;
rev.grep_filter.regflags |= REG_ICASE;
compile_grep_patterns(&rev.grep_filter);
prepare_revision_walk(&rev);
if (pager)
html("<table class='list nowrap'>");
html("<tr class='nohover'><th class='left'>Age</th>"
"<th class='left'>Commit message");
if (pager) {
html(" (");
cgit_log_link("toggle", NULL, NULL, ctx.qry.head, ctx.qry.sha1,
ctx.qry.path, ctx.qry.ofs, ctx.qry.grep,
ctx.qry.search, ctx.qry.showmsg ? 0 : 1);
html(")");
}
html("</th><th class='left'>Author</th>");
if (ctx.repo->enable_log_filecount) {
html("<th class='left'>Files</th>");
columns++;
if (ctx.repo->enable_log_linecount) {
html("<th class='left'>Lines</th>");
columns++;
}
diff --git a/ui-patch.c b/ui-patch.c
index e60877d..1d77336 100644
--- a/ui-patch.c
+++ b/ui-patch.c
@@ -80,39 +80,39 @@ void cgit_print_patch(char *hex)
if (!hex)
hex = ctx.qry.head;
if (get_sha1(hex, sha1)) {
cgit_print_error(fmt("Bad object id: %s", hex));
return;
}
commit = lookup_commit_reference(sha1);
if (!commit) {
cgit_print_error(fmt("Bad commit reference: %s", hex));
return;
}
info = cgit_parse_commit(commit);
if (commit->parents && commit->parents->item)
hashcpy(old_sha1, commit->parents->item->object.sha1);
else
hashclr(old_sha1);
patchname = fmt("%s.patch", sha1_to_hex(sha1));
ctx.page.mimetype = "text/plain";
ctx.page.filename = patchname;
cgit_print_http_headers(&ctx);
htmlf("From %s Mon Sep 17 00:00:00 2001\n", sha1_to_hex(sha1));
- htmlf("From: %s%s\n", info->author, info->author_email);
+ htmlf("From: %s %s\n", info->author, info->author_email);
html("Date: ");
- cgit_print_date(info->author_date, "%a, %d %b %Y %H:%M:%S %z%n", ctx.cfg.local_time);
+ cgit_print_date(info->author_date, "%a, %d %b %Y %H:%M:%S %z%n", ctx.cfg.local_time);
htmlf("Subject: %s\n\n", info->subject);
if (info->msg && *info->msg) {
htmlf("%s", info->msg);
if (info->msg[strlen(info->msg) - 1] != '\n')
html("\n");
}
html("---\n");
cgit_diff_tree(old_sha1, sha1, filepair_cb, NULL);
html("--\n");
htmlf("cgit %s\n", CGIT_VERSION);
cgit_free_commitinfo(info);
}
diff --git a/ui-refs.c b/ui-refs.c
index d61ee7c..c35e694 100644
--- a/ui-refs.c
+++ b/ui-refs.c
@@ -120,49 +120,49 @@ static int print_tag(struct refinfo *ref)
tag = (struct tag *)ref->object;
info = ref->tag;
if (!tag || !info)
return 1;
html("<tr><td>");
cgit_tag_link(name, NULL, NULL, ctx.qry.head, name);
html("</td><td>");
if (ctx.repo->snapshots && (tag->tagged->type == OBJ_COMMIT))
print_tag_downloads(ctx.repo, name);
else
cgit_object_link(tag->tagged);
html("</td><td>");
if (info->tagger)
html(info->tagger);
html("</td><td colspan='2'>");
if (info->tagger_date > 0)
cgit_print_age(info->tagger_date, -1, NULL);
html("</td></tr>\n");
} else {
if (!header)
print_tag_header();
html("<tr><td>");
html_txt(name);
html("</td><td>");
- if (ctx.repo->snapshots && (tag->tagged->type == OBJ_COMMIT))
+ if (ctx.repo->snapshots && (ref->object->type == OBJ_COMMIT))
print_tag_downloads(ctx.repo, name);
else
cgit_object_link(ref->object);
html("</td></tr>\n");
}
return 0;
}
static void print_refs_link(char *path)
{
html("<tr class='nohover'><td colspan='4'>");
cgit_refs_link("[...]", NULL, NULL, ctx.qry.head, NULL, path);
html("</td></tr>");
}
void cgit_print_branches(int maxcount)
{
struct reflist list;
int i;
html("<tr class='nohover'><th class='left'>Branch</th>"
"<th class='left'>Commit message</th>"
"<th class='left'>Author</th>"
"<th class='left' colspan='2'>Age</th></tr>\n");
diff --git a/ui-tree.c b/ui-tree.c
index 051db7c..9876c99 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -33,50 +33,52 @@ static void print_object(const unsigned char *sha1, char *path)
cgit_print_error(fmt("Error reading object %s",
sha1_to_hex(sha1)));
return;
}
html(" (");
cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
curr_rev, path);
htmlf(")<br/>blob: %s", sha1_to_hex(sha1));
html("<table summary='blob content' class='blob'>\n");
idx = 0;
start = 0;
lineno = 0;
while(idx < size) {
if (buf[idx] == '\n') {
buf[idx] = '\0';
htmlf(linefmt, ++lineno);
html_txt(buf + start);
html("</td></tr>\n");
start = idx + 1;
}
idx++;
}
- htmlf(linefmt, ++lineno);
- html_txt(buf + start);
+ if (start < idx) {
+ htmlf(linefmt, ++lineno);
+ html_txt(buf + start);
+ }
html("</td></tr>\n");
html("</table>\n");
}
static int ls_item(const unsigned char *sha1, const char *base, int baselen,
const char *pathname, unsigned int mode, int stage,
void *cbdata)
{
char *name;
char *fullpath;
enum object_type type;
unsigned long size = 0;
name = xstrdup(pathname);
fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "",
ctx.qry.path ? "/" : "", name);
if (!S_ISGITLINK(mode)) {
type = sha1_object_info(sha1, &size);
if (type == OBJ_BAD) {
htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
name,
sha1_to_hex(sha1));