summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--Makefile4
-rw-r--r--cgit.c19
-rw-r--r--cgit.css24
-rwxr-xr-xtests/t0104-tree.sh2
-rw-r--r--ui-log.c35
-rw-r--r--ui-patch.c0
-rw-r--r--ui-refs.c2
-rw-r--r--ui-tree.c2
8 files changed, 75 insertions, 13 deletions
diff --git a/Makefile b/Makefile
index 3c7ec07..036fcd7 100644
--- a/Makefile
+++ b/Makefile
@@ -119,26 +119,26 @@ endif
119ifdef NO_STRCASESTR 119ifdef NO_STRCASESTR
120 CFLAGS += -DNO_STRCASESTR 120 CFLAGS += -DNO_STRCASESTR
121endif 121endif
122 122
123cgit: $(OBJECTS) libgit 123cgit: $(OBJECTS) libgit
124 $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS) 124 $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS)
125 125
126cgit.o: VERSION 126cgit.o: VERSION
127 127
128-include $(OBJECTS:.o=.d) 128-include $(OBJECTS:.o=.d)
129 129
130libgit: 130libgit:
131 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) libgit.a 131 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 libgit.a
132 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) xdiff/lib.a 132 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 xdiff/lib.a
133 133
134test: all 134test: all
135 $(QUIET_SUBDIR0)tests $(QUIET_SUBDIR1) all 135 $(QUIET_SUBDIR0)tests $(QUIET_SUBDIR1) all
136 136
137install: all 137install: all
138 mkdir -p $(DESTDIR)$(CGIT_SCRIPT_PATH) 138 mkdir -p $(DESTDIR)$(CGIT_SCRIPT_PATH)
139 install cgit $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) 139 install cgit $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)
140 install -m 0644 cgit.css $(DESTDIR)$(CGIT_SCRIPT_PATH)/cgit.css 140 install -m 0644 cgit.css $(DESTDIR)$(CGIT_SCRIPT_PATH)/cgit.css
141 install -m 0644 cgit.png $(DESTDIR)$(CGIT_SCRIPT_PATH)/cgit.png 141 install -m 0644 cgit.png $(DESTDIR)$(CGIT_SCRIPT_PATH)/cgit.png
142 142
143uninstall: 143uninstall:
144 rm -f $(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) 144 rm -f $(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)
diff --git a/cgit.c b/cgit.c
index 166fbc6..d1cee58 100644
--- a/cgit.c
+++ b/cgit.c
@@ -430,47 +430,48 @@ int main(int argc, const char **argv)
430 cgit_repolist.repos = NULL; 430 cgit_repolist.repos = NULL;
431 431
432 if (getenv("SCRIPT_NAME")) 432 if (getenv("SCRIPT_NAME"))
433 ctx.cfg.script_name = xstrdup(getenv("SCRIPT_NAME")); 433 ctx.cfg.script_name = xstrdup(getenv("SCRIPT_NAME"));
434 if (getenv("QUERY_STRING")) 434 if (getenv("QUERY_STRING"))
435 ctx.qry.raw = xstrdup(getenv("QUERY_STRING")); 435 ctx.qry.raw = xstrdup(getenv("QUERY_STRING"));
436 cgit_parse_args(argc, argv); 436 cgit_parse_args(argc, argv);
437 parse_configfile(cgit_config_env ? cgit_config_env : CGIT_CONFIG, 437 parse_configfile(cgit_config_env ? cgit_config_env : CGIT_CONFIG,
438 config_cb); 438 config_cb);
439 ctx.repo = NULL; 439 ctx.repo = NULL;
440 http_parse_querystring(ctx.qry.raw, querystring_cb); 440 http_parse_querystring(ctx.qry.raw, querystring_cb);
441 441
442 /* If virtual-root isn't specified in cgitrc and no url 442 /* If virtual-root isn't specified in cgitrc, lets pretend
443 * parameter is specified on the querystring, lets pretend 443 * that virtual-root equals SCRIPT_NAME.
444 * that virtualroot equals SCRIPT_NAME and use PATH_INFO as
445 * url. This allows cgit to work with virtual urls without
446 * the need for rewriterules in the webserver (as long as
447 * PATH_INFO is included in the cache lookup key).
448 */ 444 */
449 if (!ctx.cfg.virtual_root && !ctx.qry.url) { 445 if (!ctx.cfg.virtual_root)
450 ctx.cfg.virtual_root = ctx.cfg.script_name; 446 ctx.cfg.virtual_root = ctx.cfg.script_name;
447
448 /* If no url parameter is specified on the querystring, lets
449 * use PATH_INFO as url. This allows cgit to work with virtual
450 * urls without the need for rewriterules in the webserver (as
451 * long as PATH_INFO is included in the cache lookup key).
452 */
451 path = getenv("PATH_INFO"); 453 path = getenv("PATH_INFO");
452 if (path) { 454 if (!ctx.qry.url && path) {
453 if (path[0] == '/') 455 if (path[0] == '/')
454 path++; 456 path++;
455 ctx.qry.url = xstrdup(path); 457 ctx.qry.url = xstrdup(path);
456 if (ctx.qry.raw) { 458 if (ctx.qry.raw) {
457 qry = ctx.qry.raw; 459 qry = ctx.qry.raw;
458 ctx.qry.raw = xstrdup(fmt("%s?%s", path, qry)); 460 ctx.qry.raw = xstrdup(fmt("%s?%s", path, qry));
459 free(qry); 461 free(qry);
460 } else 462 } else
461 ctx.qry.raw = ctx.qry.url; 463 ctx.qry.raw = ctx.qry.url;
462 cgit_parse_url(ctx.qry.url); 464 cgit_parse_url(ctx.qry.url);
463 } 465 }
464 }
465 466
466 ttl = calc_ttl(); 467 ttl = calc_ttl();
467 ctx.page.expires += ttl*60; 468 ctx.page.expires += ttl*60;
468 if (ctx.cfg.nocache) 469 if (ctx.cfg.nocache)
469 ctx.cfg.cache_size = 0; 470 ctx.cfg.cache_size = 0;
470 err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root, 471 err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root,
471 ctx.qry.raw, ttl, process_request, &ctx); 472 ctx.qry.raw, ttl, process_request, &ctx);
472 if (err) 473 if (err)
473 cgit_print_error(fmt("Error processing page: %s (%d)", 474 cgit_print_error(fmt("Error processing page: %s (%d)",
474 strerror(err), err)); 475 strerror(err), err));
475 return err; 476 return err;
476} 477}
diff --git a/cgit.css b/cgit.css
index 7928c2f..f19446d 100644
--- a/cgit.css
+++ b/cgit.css
@@ -462,12 +462,36 @@ span.age-months {
462 color: #888; 462 color: #888;
463} 463}
464 464
465span.age-years { 465span.age-years {
466 color: #bbb; 466 color: #bbb;
467} 467}
468div.footer { 468div.footer {
469 margin-top: 0.5em; 469 margin-top: 0.5em;
470 text-align: center; 470 text-align: center;
471 font-size: 80%; 471 font-size: 80%;
472 color: #ccc; 472 color: #ccc;
473} 473}
474a.branch-deco {
475 margin: 0px 0.5em;
476 padding: 0px 0.25em;
477 background-color: #88ff88;
478 border: solid 1px #007700;
479}
480a.tag-deco {
481 margin: 0px 0.5em;
482 padding: 0px 0.25em;
483 background-color: #ffff88;
484 border: solid 1px #777700;
485}
486a.remote-deco {
487 margin: 0px 0.5em;
488 padding: 0px 0.25em;
489 background-color: #ccccff;
490 border: solid 1px #000077;
491}
492a.deco {
493 margin: 0px 0.5em;
494 padding: 0px 0.25em;
495 background-color: #ff8888;
496 border: solid 1px #770000;
497}
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
@@ -6,25 +6,25 @@ prepare_tests "Check content on tree page"
6 6
7run_test 'generate bar/tree' 'cgit_url "bar/tree" >trash/tmp' 7run_test 'generate bar/tree' 'cgit_url "bar/tree" >trash/tmp'
8run_test 'find file-1' 'grep -e "file-1" trash/tmp' 8run_test 'find file-1' 'grep -e "file-1" trash/tmp'
9run_test 'find file-50' 'grep -e "file-50" trash/tmp' 9run_test 'find file-50' 'grep -e "file-50" trash/tmp'
10 10
11run_test 'generate bar/tree/file-50' 'cgit_url "bar/tree/file-50" >trash/tmp' 11run_test 'generate bar/tree/file-50' 'cgit_url "bar/tree/file-50" >trash/tmp'
12 12
13run_test 'find line 1' ' 13run_test 'find line 1' '
14 grep -e "<a id=.n1. name=.n1. href=.#n1.>1</a>" trash/tmp 14 grep -e "<a id=.n1. name=.n1. href=.#n1.>1</a>" trash/tmp
15' 15'
16 16
17run_test 'no line 2' ' 17run_test 'no line 2' '
18 grep -e "<a id=.n2. name=.n2. href=.#n2.>2</a>" trash/tmp 18 ! grep -e "<a id=.n2. name=.n2. href=.#n2.>2</a>" trash/tmp
19' 19'
20 20
21run_test 'generate foo+bar/tree' 'cgit_url "foo%2bbar/tree" >trash/tmp' 21run_test 'generate foo+bar/tree' 'cgit_url "foo%2bbar/tree" >trash/tmp'
22 22
23run_test 'verify a+b link' ' 23run_test 'verify a+b link' '
24 grep -e "/foo+bar/tree/a+b" trash/tmp 24 grep -e "/foo+bar/tree/a+b" trash/tmp
25' 25'
26 26
27run_test 'generate foo+bar/tree?h=1+2' 'cgit_url "foo%2bbar/tree&h=1%2b2" >trash/tmp' 27run_test 'generate foo+bar/tree?h=1+2' 'cgit_url "foo%2bbar/tree&h=1%2b2" >trash/tmp'
28 28
29run_test 'verify a+b?h=1+2 link' ' 29run_test 'verify a+b?h=1+2 link' '
30 grep -e "/foo+bar/tree/a+b?h=1%2b2" trash/tmp 30 grep -e "/foo+bar/tree/a+b?h=1%2b2" trash/tmp
diff --git a/ui-log.c b/ui-log.c
index 2f90778..c3757dd 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -22,42 +22,75 @@ void count_lines(char *line, int size)
22 22
23 else if (line[0] == '-') 23 else if (line[0] == '-')
24 rem_lines++; 24 rem_lines++;
25} 25}
26 26
27void inspect_files(struct diff_filepair *pair) 27void inspect_files(struct diff_filepair *pair)
28{ 28{
29 files++; 29 files++;
30 if (ctx.repo->enable_log_linecount) 30 if (ctx.repo->enable_log_linecount)
31 cgit_diff_files(pair->one->sha1, pair->two->sha1, count_lines); 31 cgit_diff_files(pair->one->sha1, pair->two->sha1, count_lines);
32} 32}
33 33
34void show_commit_decorations(struct commit *commit)
35{
36 struct name_decoration *deco;
37 static char buf[1024];
38
39 buf[sizeof(buf) - 1] = 0;
40 deco = lookup_decoration(&name_decoration, &commit->object);
41 while (deco) {
42 if (!prefixcmp(deco->name, "refs/heads/")) {
43 strncpy(buf, deco->name + 11, sizeof(buf) - 1);
44 cgit_log_link(buf, NULL, "branch-deco", buf, NULL, NULL,
45 0, NULL, NULL, ctx.qry.showmsg);
46 }
47 else if (!prefixcmp(deco->name, "tag: refs/tags/")) {
48 strncpy(buf, deco->name + 15, sizeof(buf) - 1);
49 cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf);
50 }
51 else if (!prefixcmp(deco->name, "refs/remotes/")) {
52 strncpy(buf, deco->name + 13, sizeof(buf) - 1);
53 cgit_log_link(buf, NULL, "remote-deco", NULL,
54 sha1_to_hex(commit->object.sha1), NULL,
55 0, NULL, NULL, ctx.qry.showmsg);
56 }
57 else {
58 strncpy(buf, deco->name, sizeof(buf) - 1);
59 cgit_commit_link(buf, NULL, "deco", ctx.qry.head,
60 sha1_to_hex(commit->object.sha1));
61 }
62 deco = deco->next;
63 }
64}
65
34void print_commit(struct commit *commit) 66void print_commit(struct commit *commit)
35{ 67{
36 struct commitinfo *info; 68 struct commitinfo *info;
37 char *tmp; 69 char *tmp;
38 int cols = 2; 70 int cols = 2;
39 71
40 info = cgit_parse_commit(commit); 72 info = cgit_parse_commit(commit);
41 htmlf("<tr%s><td>", 73 htmlf("<tr%s><td>",
42 ctx.qry.showmsg ? " class='logheader'" : ""); 74 ctx.qry.showmsg ? " class='logheader'" : "");
43 tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1)); 75 tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1));
44 tmp = cgit_pageurl(ctx.repo->url, "commit", tmp); 76 tmp = cgit_pageurl(ctx.repo->url, "commit", tmp);
45 html_link_open(tmp, NULL, NULL); 77 html_link_open(tmp, NULL, NULL);
46 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); 78 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE);
47 html_link_close(); 79 html_link_close();
48 htmlf("</td><td%s>", 80 htmlf("</td><td%s>",
49 ctx.qry.showmsg ? " class='logsubject'" : ""); 81 ctx.qry.showmsg ? " class='logsubject'" : "");
50 cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head, 82 cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head,
51 sha1_to_hex(commit->object.sha1)); 83 sha1_to_hex(commit->object.sha1));
84 show_commit_decorations(commit);
52 html("</td><td>"); 85 html("</td><td>");
53 html_txt(info->author); 86 html_txt(info->author);
54 if (ctx.repo->enable_log_filecount) { 87 if (ctx.repo->enable_log_filecount) {
55 files = 0; 88 files = 0;
56 add_lines = 0; 89 add_lines = 0;
57 rem_lines = 0; 90 rem_lines = 0;
58 cgit_diff_commit(commit, inspect_files); 91 cgit_diff_commit(commit, inspect_files);
59 html("</td><td>"); 92 html("</td><td>");
60 htmlf("%d", files); 93 htmlf("%d", files);
61 if (ctx.repo->enable_log_linecount) { 94 if (ctx.repo->enable_log_linecount) {
62 html("</td><td>"); 95 html("</td><td>");
63 htmlf("-%d/+%d", rem_lines, add_lines); 96 htmlf("-%d/+%d", rem_lines, add_lines);
@@ -110,24 +143,26 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern
110 argv[argc++] = fmt("--%s=%s", grep, pattern); 143 argv[argc++] = fmt("--%s=%s", grep, pattern);
111 144
112 if (path) { 145 if (path) {
113 argv[argc++] = "--"; 146 argv[argc++] = "--";
114 argv[argc++] = path; 147 argv[argc++] = path;
115 } 148 }
116 init_revisions(&rev, NULL); 149 init_revisions(&rev, NULL);
117 rev.abbrev = DEFAULT_ABBREV; 150 rev.abbrev = DEFAULT_ABBREV;
118 rev.commit_format = CMIT_FMT_DEFAULT; 151 rev.commit_format = CMIT_FMT_DEFAULT;
119 rev.verbose_header = 1; 152 rev.verbose_header = 1;
120 rev.show_root_diff = 0; 153 rev.show_root_diff = 0;
121 setup_revisions(argc, argv, &rev, NULL); 154 setup_revisions(argc, argv, &rev, NULL);
155 load_ref_decorations();
156 rev.show_decorations = 1;
122 rev.grep_filter.regflags |= REG_ICASE; 157 rev.grep_filter.regflags |= REG_ICASE;
123 compile_grep_patterns(&rev.grep_filter); 158 compile_grep_patterns(&rev.grep_filter);
124 prepare_revision_walk(&rev); 159 prepare_revision_walk(&rev);
125 160
126 if (pager) 161 if (pager)
127 html("<table class='list nowrap'>"); 162 html("<table class='list nowrap'>");
128 163
129 html("<tr class='nohover'><th class='left'>Age</th>" 164 html("<tr class='nohover'><th class='left'>Age</th>"
130 "<th class='left'>Commit message"); 165 "<th class='left'>Commit message");
131 if (pager) { 166 if (pager) {
132 html(" ("); 167 html(" (");
133 cgit_log_link("toggle", NULL, NULL, ctx.qry.head, ctx.qry.sha1, 168 cgit_log_link("toggle", NULL, NULL, ctx.qry.head, ctx.qry.sha1,
diff --git a/ui-patch.c b/ui-patch.c
index e60877d..1d77336 100644
--- a/ui-patch.c
+++ b/ui-patch.c
diff --git a/ui-refs.c b/ui-refs.c
index d61ee7c..c35e694 100644
--- a/ui-refs.c
+++ b/ui-refs.c
@@ -132,25 +132,25 @@ static int print_tag(struct refinfo *ref)
132 if (info->tagger) 132 if (info->tagger)
133 html(info->tagger); 133 html(info->tagger);
134 html("</td><td colspan='2'>"); 134 html("</td><td colspan='2'>");
135 if (info->tagger_date > 0) 135 if (info->tagger_date > 0)
136 cgit_print_age(info->tagger_date, -1, NULL); 136 cgit_print_age(info->tagger_date, -1, NULL);
137 html("</td></tr>\n"); 137 html("</td></tr>\n");
138 } else { 138 } else {
139 if (!header) 139 if (!header)
140 print_tag_header(); 140 print_tag_header();
141 html("<tr><td>"); 141 html("<tr><td>");
142 html_txt(name); 142 html_txt(name);
143 html("</td><td>"); 143 html("</td><td>");
144 if (ctx.repo->snapshots && (tag->tagged->type == OBJ_COMMIT)) 144 if (ctx.repo->snapshots && (ref->object->type == OBJ_COMMIT))
145 print_tag_downloads(ctx.repo, name); 145 print_tag_downloads(ctx.repo, name);
146 else 146 else
147 cgit_object_link(ref->object); 147 cgit_object_link(ref->object);
148 html("</td></tr>\n"); 148 html("</td></tr>\n");
149 } 149 }
150 return 0; 150 return 0;
151} 151}
152 152
153static void print_refs_link(char *path) 153static void print_refs_link(char *path)
154{ 154{
155 html("<tr class='nohover'><td colspan='4'>"); 155 html("<tr class='nohover'><td colspan='4'>");
156 cgit_refs_link("[...]", NULL, NULL, ctx.qry.head, NULL, path); 156 cgit_refs_link("[...]", NULL, NULL, ctx.qry.head, NULL, path);
diff --git a/ui-tree.c b/ui-tree.c
index 051db7c..9876c99 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -45,26 +45,28 @@ static void print_object(const unsigned char *sha1, char *path)
45 start = 0; 45 start = 0;
46 lineno = 0; 46 lineno = 0;
47 while(idx < size) { 47 while(idx < size) {
48 if (buf[idx] == '\n') { 48 if (buf[idx] == '\n') {
49 buf[idx] = '\0'; 49 buf[idx] = '\0';
50 htmlf(linefmt, ++lineno); 50 htmlf(linefmt, ++lineno);
51 html_txt(buf + start); 51 html_txt(buf + start);
52 html("</td></tr>\n"); 52 html("</td></tr>\n");
53 start = idx + 1; 53 start = idx + 1;
54 } 54 }
55 idx++; 55 idx++;
56 } 56 }
57 if (start < idx) {
57 htmlf(linefmt, ++lineno); 58 htmlf(linefmt, ++lineno);
58 html_txt(buf + start); 59 html_txt(buf + start);
60 }
59 html("</td></tr>\n"); 61 html("</td></tr>\n");
60 html("</table>\n"); 62 html("</table>\n");
61} 63}
62 64
63 65
64static int ls_item(const unsigned char *sha1, const char *base, int baselen, 66static int ls_item(const unsigned char *sha1, const char *base, int baselen,
65 const char *pathname, unsigned int mode, int stage, 67 const char *pathname, unsigned int mode, int stage,
66 void *cbdata) 68 void *cbdata)
67{ 69{
68 char *name; 70 char *name;
69 char *fullpath; 71 char *fullpath;
70 enum object_type type; 72 enum object_type type;