summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--Makefile15
-rw-r--r--cgit.c9
-rw-r--r--cgit.css5
-rw-r--r--cgit.h1
-rw-r--r--cgitrc.5.txt15
-rwxr-xr-xfilters/syntax-highlighting.sh29
-rw-r--r--shared.c17
-rw-r--r--ui-repolist.c2
-rw-r--r--ui-shared.c11
-rw-r--r--ui-shared.h1
-rw-r--r--ui-tag.c24
-rw-r--r--ui-tree.c6
12 files changed, 94 insertions, 41 deletions
diff --git a/Makefile b/Makefile
index cb7875e..f8a4d47 100644
--- a/Makefile
+++ b/Makefile
@@ -8,12 +8,15 @@ SHA1_HEADER = <openssl/sha.h>
8GIT_VER = 1.6.4.3 8GIT_VER = 1.6.4.3
9GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2 9GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2
10INSTALL = install 10INSTALL = install
11 11
12# Define NO_STRCASESTR if you don't have strcasestr. 12# Define NO_STRCASESTR if you don't have strcasestr.
13# 13#
14# Define NO_OPENSSL to disable linking with OpenSSL and use bundled SHA1
15# implementation (slower).
16#
14# Define NEEDS_LIBICONV if linking with libc is not enough (eg. Darwin). 17# Define NEEDS_LIBICONV if linking with libc is not enough (eg. Darwin).
15# 18#
16 19
17#-include config.mak 20#-include config.mak
18 21
19# 22#
@@ -65,13 +68,13 @@ endif
65# Define a pattern rule for silent object building 68# Define a pattern rule for silent object building
66# 69#
67%.o: %.c 70%.o: %.c
68 $(QUIET_CC)$(CC) -o $*.o -c $(CFLAGS) $< 71 $(QUIET_CC)$(CC) -o $*.o -c $(CFLAGS) $<
69 72
70 73
71EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lcrypto 74EXTLIBS = git/libgit.a git/xdiff/lib.a -lz
72OBJECTS = 75OBJECTS =
73OBJECTS += cache.o 76OBJECTS += cache.o
74OBJECTS += cgit.o 77OBJECTS += cgit.o
75OBJECTS += cmd.o 78OBJECTS += cmd.o
76OBJECTS += configfile.o 79OBJECTS += configfile.o
77OBJECTS += html.o 80OBJECTS += html.o
@@ -121,23 +124,29 @@ CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"'
121ifdef NO_ICONV 124ifdef NO_ICONV
122 CFLAGS += -DNO_ICONV 125 CFLAGS += -DNO_ICONV
123endif 126endif
124ifdef NO_STRCASESTR 127ifdef NO_STRCASESTR
125 CFLAGS += -DNO_STRCASESTR 128 CFLAGS += -DNO_STRCASESTR
126endif 129endif
130ifdef NO_OPENSSL
131 CFLAGS += -DNO_OPENSSL
132 GIT_OPTIONS += NO_OPENSSL=1
133else
134 EXTLIBS += -lcrypto
135endif
127 136
128cgit: $(OBJECTS) libgit 137cgit: $(OBJECTS) libgit
129 $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS) 138 $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS)
130 139
131cgit.o: VERSION 140cgit.o: VERSION
132 141
133-include $(OBJECTS:.o=.d) 142-include $(OBJECTS:.o=.d)
134 143
135libgit: 144libgit:
136 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 libgit.a 145 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) libgit.a
137 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 xdiff/lib.a 146 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) xdiff/lib.a
138 147
139test: all 148test: all
140 $(QUIET_SUBDIR0)tests $(QUIET_SUBDIR1) all 149 $(QUIET_SUBDIR0)tests $(QUIET_SUBDIR1) all
141 150
142install: all 151install: all
143 $(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_SCRIPT_PATH) 152 $(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_SCRIPT_PATH)
diff --git a/cgit.c b/cgit.c
index ff678fb..4f68a4b 100644
--- a/cgit.c
+++ b/cgit.c
@@ -65,15 +65,15 @@ void repo_config(struct cgit_repo *repo, const char *name, const char *value)
65 else if (!strcmp(name, "module-link")) 65 else if (!strcmp(name, "module-link"))
66 repo->module_link= xstrdup(value); 66 repo->module_link= xstrdup(value);
67 else if (!strcmp(name, "section")) 67 else if (!strcmp(name, "section"))
68 repo->section = xstrdup(value); 68 repo->section = xstrdup(value);
69 else if (!strcmp(name, "readme") && value != NULL) { 69 else if (!strcmp(name, "readme") && value != NULL) {
70 if (*value == '/') 70 if (*value == '/')
71 ctx.repo->readme = xstrdup(value); 71 repo->readme = xstrdup(value);
72 else 72 else
73 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value)); 73 repo->readme = xstrdup(fmt("%s/%s", repo->path, value));
74 } else if (ctx.cfg.enable_filter_overrides) { 74 } else if (ctx.cfg.enable_filter_overrides) {
75 if (!strcmp(name, "about-filter")) 75 if (!strcmp(name, "about-filter"))
76 repo->about_filter = new_filter(value, 0); 76 repo->about_filter = new_filter(value, 0);
77 else if (!strcmp(name, "commit-filter")) 77 else if (!strcmp(name, "commit-filter"))
78 repo->commit_filter = new_filter(value, 0); 78 repo->commit_filter = new_filter(value, 0);
79 else if (!strcmp(name, "source-filter")) 79 else if (!strcmp(name, "source-filter"))
@@ -162,12 +162,14 @@ void config_cb(const char *name, const char *value)
162 else if (!strcmp(name, "embedded")) 162 else if (!strcmp(name, "embedded"))
163 ctx.cfg.embedded = atoi(value); 163 ctx.cfg.embedded = atoi(value);
164 else if (!strcmp(name, "max-message-length")) 164 else if (!strcmp(name, "max-message-length"))
165 ctx.cfg.max_msg_len = atoi(value); 165 ctx.cfg.max_msg_len = atoi(value);
166 else if (!strcmp(name, "max-repodesc-length")) 166 else if (!strcmp(name, "max-repodesc-length"))
167 ctx.cfg.max_repodesc_len = atoi(value); 167 ctx.cfg.max_repodesc_len = atoi(value);
168 else if (!strcmp(name, "max-blob-size"))
169 ctx.cfg.max_blob_size = atoi(value);
168 else if (!strcmp(name, "max-repo-count")) 170 else if (!strcmp(name, "max-repo-count"))
169 ctx.cfg.max_repo_count = atoi(value); 171 ctx.cfg.max_repo_count = atoi(value);
170 else if (!strcmp(name, "max-commit-count")) 172 else if (!strcmp(name, "max-commit-count"))
171 ctx.cfg.max_commit_count = atoi(value); 173 ctx.cfg.max_commit_count = atoi(value);
172 else if (!strcmp(name, "scan-path")) 174 else if (!strcmp(name, "scan-path"))
173 if (!ctx.cfg.nocache && ctx.cfg.cache_size) 175 if (!ctx.cfg.nocache && ctx.cfg.cache_size)
@@ -208,12 +210,14 @@ static void querystring_cb(const char *name, const char *value)
208 if (!strcmp(name,"r")) { 210 if (!strcmp(name,"r")) {
209 ctx.qry.repo = xstrdup(value); 211 ctx.qry.repo = xstrdup(value);
210 ctx.repo = cgit_get_repoinfo(value); 212 ctx.repo = cgit_get_repoinfo(value);
211 } else if (!strcmp(name, "p")) { 213 } else if (!strcmp(name, "p")) {
212 ctx.qry.page = xstrdup(value); 214 ctx.qry.page = xstrdup(value);
213 } else if (!strcmp(name, "url")) { 215 } else if (!strcmp(name, "url")) {
216 if (*value == '/')
217 value++;
214 ctx.qry.url = xstrdup(value); 218 ctx.qry.url = xstrdup(value);
215 cgit_parse_url(value); 219 cgit_parse_url(value);
216 } else if (!strcmp(name, "qt")) { 220 } else if (!strcmp(name, "qt")) {
217 ctx.qry.grep = xstrdup(value); 221 ctx.qry.grep = xstrdup(value);
218 } else if (!strcmp(name, "q")) { 222 } else if (!strcmp(name, "q")) {
219 ctx.qry.search = xstrdup(value); 223 ctx.qry.search = xstrdup(value);
@@ -269,12 +273,13 @@ static void prepare_context(struct cgit_context *ctx)
269 ctx->cfg.enable_tree_linenumbers = 1; 273 ctx->cfg.enable_tree_linenumbers = 1;
270 ctx->cfg.max_repo_count = 50; 274 ctx->cfg.max_repo_count = 50;
271 ctx->cfg.max_commit_count = 50; 275 ctx->cfg.max_commit_count = 50;
272 ctx->cfg.max_lock_attempts = 5; 276 ctx->cfg.max_lock_attempts = 5;
273 ctx->cfg.max_msg_len = 80; 277 ctx->cfg.max_msg_len = 80;
274 ctx->cfg.max_repodesc_len = 80; 278 ctx->cfg.max_repodesc_len = 80;
279 ctx->cfg.max_blob_size = 0;
275 ctx->cfg.max_stats = 0; 280 ctx->cfg.max_stats = 0;
276 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s"; 281 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s";
277 ctx->cfg.renamelimit = -1; 282 ctx->cfg.renamelimit = -1;
278 ctx->cfg.robots = "index, nofollow"; 283 ctx->cfg.robots = "index, nofollow";
279 ctx->cfg.root_title = "Git repository browser"; 284 ctx->cfg.root_title = "Git repository browser";
280 ctx->cfg.root_desc = "a fast webinterface for the git dscm"; 285 ctx->cfg.root_desc = "a fast webinterface for the git dscm";
diff --git a/cgit.css b/cgit.css
index 9e6d2a4..0cb894a 100644
--- a/cgit.css
+++ b/cgit.css
@@ -159,12 +159,17 @@ table.list td.logmsg {
159} 159}
160 160
161table.list td a { 161table.list td a {
162 color: black; 162 color: black;
163} 163}
164 164
165table.list td a.ls-dir {
166 font-weight: bold;
167 color: #00f;
168}
169
165table.list td a:hover { 170table.list td a:hover {
166 color: #00f; 171 color: #00f;
167} 172}
168 173
169img { 174img {
170 border: none; 175 border: none;
diff --git a/cgit.h b/cgit.h
index b7b0adb..5941ec0 100644
--- a/cgit.h
+++ b/cgit.h
@@ -183,12 +183,13 @@ struct cgit_config {
183 int local_time; 183 int local_time;
184 int max_repo_count; 184 int max_repo_count;
185 int max_commit_count; 185 int max_commit_count;
186 int max_lock_attempts; 186 int max_lock_attempts;
187 int max_msg_len; 187 int max_msg_len;
188 int max_repodesc_len; 188 int max_repodesc_len;
189 int max_blob_size;
189 int max_stats; 190 int max_stats;
190 int nocache; 191 int nocache;
191 int noplainemail; 192 int noplainemail;
192 int noheader; 193 int noheader;
193 int renamelimit; 194 int renamelimit;
194 int snapshots; 195 int snapshots;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 252d546..70e4c78 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -1,6 +1,9 @@
1:man source: cgit
2:man manual: cgit
3
1CGITRC(5) 4CGITRC(5)
2======== 5========
3 6
4 7
5NAME 8NAME
6---- 9----
@@ -171,12 +174,16 @@ max-repo-count::
171 index page. Default value: "50". 174 index page. Default value: "50".
172 175
173max-repodesc-length:: 176max-repodesc-length::
174 Specifies the maximum number of repo description characters to display 177 Specifies the maximum number of repo description characters to display
175 on the repository index page. Default value: "80". 178 on the repository index page. Default value: "80".
176 179
180max-blob-size::
181 Specifies the maximum size of a blob to display HTML for in KBytes.
182 Default value: "0" (limit disabled).
183
177max-stats:: 184max-stats::
178 Set the default maximum statistics period. Valid values are "week", 185 Set the default maximum statistics period. Valid values are "week",
179 "month", "quarter" and "year". If unspecified, statistics are 186 "month", "quarter" and "year". If unspecified, statistics are
180 disabled. Default value: none. See also: "repo.max-stats". 187 disabled. Default value: none. See also: "repo.max-stats".
181 188
182mimetype.<ext>:: 189mimetype.<ext>::
@@ -422,14 +429,14 @@ mimetype.pdf=application/pdf
422mimetype.png=image/png 429mimetype.png=image/png
423mimetype.svg=image/svg+xml 430mimetype.svg=image/svg+xml
424 431
425 432
426## 433##
427## List of repositories. 434## List of repositories.
428## PS: Any repositories listed when repo.group is unset will not be 435## PS: Any repositories listed when section is unset will not be
429## displayed under a group heading 436## displayed under a section heading
430## PPS: This list could be kept in a different file (e.g. '/etc/cgitrepos') 437## PPS: This list could be kept in a different file (e.g. '/etc/cgitrepos')
431## and included like this: 438## and included like this:
432## include=/etc/cgitrepos 439## include=/etc/cgitrepos
433## 440##
434 441
435 442
@@ -445,26 +452,26 @@ repo.path=/pub/git/bar.git
445repo.desc=the bars for your foo 452repo.desc=the bars for your foo
446repo.owner=barman@foobar.com 453repo.owner=barman@foobar.com
447repo.readme=info/web/about.html 454repo.readme=info/web/about.html
448 455
449 456
450# The next repositories will be displayed under the 'extras' heading 457# The next repositories will be displayed under the 'extras' heading
451repo.group=extras 458section=extras
452 459
453 460
454repo.url=baz 461repo.url=baz
455repo.path=/pub/git/baz.git 462repo.path=/pub/git/baz.git
456repo.desc=a set of extensions for bar users 463repo.desc=a set of extensions for bar users
457 464
458repo.url=wiz 465repo.url=wiz
459repo.path=/pub/git/wiz.git 466repo.path=/pub/git/wiz.git
460repo.desc=the wizard of foo 467repo.desc=the wizard of foo
461 468
462 469
463# Add some mirrored repositories 470# Add some mirrored repositories
464repo.group=mirrors 471section=mirrors
465 472
466 473
467repo.url=git 474repo.url=git
468repo.path=/pub/git/git.git 475repo.path=/pub/git/git.git
469repo.desc=the dscm 476repo.desc=the dscm
470 477
diff --git a/filters/syntax-highlighting.sh b/filters/syntax-highlighting.sh
index 999ad0c..6b1c576 100755
--- a/filters/syntax-highlighting.sh
+++ b/filters/syntax-highlighting.sh
@@ -1,11 +1,15 @@
1#!/bin/sh 1#!/bin/sh
2# This script can be used to implement syntax highlighting in the cgit 2# This script can be used to implement syntax highlighting in the cgit
3# tree-view by refering to this file with the source-filter or repo.source- 3# tree-view by refering to this file with the source-filter or repo.source-
4# filter options in cgitrc. 4# filter options in cgitrc.
5# 5#
6# This script requires a shell supporting the ${var##pattern} syntax.
7# It is supported by at least dash and bash, however busybox environments
8# might have to use an external call to sed instead.
9#
6# Note: the highlight command (http://www.andre-simon.de/) uses css for syntax 10# Note: the highlight command (http://www.andre-simon.de/) uses css for syntax
7# highlighting, so you'll probably want something like the following included 11# highlighting, so you'll probably want something like the following included
8# in your css file (generated by highlight 2.4.8 and adapted for cgit): 12# in your css file (generated by highlight 2.4.8 and adapted for cgit):
9# 13#
10# table.blob .num { color:#2928ff; } 14# table.blob .num { color:#2928ff; }
11# table.blob .esc { color:#ff00ff; } 15# table.blob .esc { color:#ff00ff; }
@@ -17,23 +21,14 @@
17# table.blob .sym { color:#000000; } 21# table.blob .sym { color:#000000; }
18# table.blob .kwa { color:#000000; font-weight:bold; } 22# table.blob .kwa { color:#000000; font-weight:bold; }
19# table.blob .kwb { color:#830000; } 23# table.blob .kwb { color:#830000; }
20# table.blob .kwc { color:#000000; font-weight:bold; } 24# table.blob .kwc { color:#000000; font-weight:bold; }
21# table.blob .kwd { color:#010181; } 25# table.blob .kwd { color:#010181; }
22 26
23case "$1" in 27# store filename and extension in local vars
24 *.c) 28BASENAME="$1"
25 highlight -f -I -X -S c 29EXTENSION="${BASENAME##*.}"
26 ;; 30
27 *.h) 31# map Makefile and Makefile.* to .mk
28 highlight -f -I -X -S c 32[ "${BASENAME%%.*}" == "Makefile" ] && EXTENSION=mk
29 ;; 33
30 *.sh) 34exec highlight --force -f -I -X -S $EXTENSION 2>/dev/null
31 highlight -f -I -X -S sh
32 ;;
33 *.css)
34 highlight -f -I -X -S css
35 ;;
36 *)
37 highlight -f -I -X -S txt
38 ;;
39esac
diff --git a/shared.c b/shared.c
index d7b2d5a..9362d21 100644
--- a/shared.c
+++ b/shared.c
@@ -397,21 +397,28 @@ int cgit_close_filter(struct cgit_filter *filter)
397 397
398/* Read the content of the specified file into a newly allocated buffer, 398/* Read the content of the specified file into a newly allocated buffer,
399 * zeroterminate the buffer and return 0 on success, errno otherwise. 399 * zeroterminate the buffer and return 0 on success, errno otherwise.
400 */ 400 */
401int readfile(const char *path, char **buf, size_t *size) 401int readfile(const char *path, char **buf, size_t *size)
402{ 402{
403 int fd; 403 int fd, e;
404 struct stat st; 404 struct stat st;
405 405
406 fd = open(path, O_RDONLY); 406 fd = open(path, O_RDONLY);
407 if (fd == -1) 407 if (fd == -1)
408 return errno; 408 return errno;
409 if (fstat(fd, &st)) 409 if (fstat(fd, &st)) {
410 return errno; 410 e = errno;
411 if (!S_ISREG(st.st_mode)) 411 close(fd);
412 return e;
413 }
414 if (!S_ISREG(st.st_mode)) {
415 close(fd);
412 return EISDIR; 416 return EISDIR;
417 }
413 *buf = xmalloc(st.st_size + 1); 418 *buf = xmalloc(st.st_size + 1);
414 *size = read_in_full(fd, *buf, st.st_size); 419 *size = read_in_full(fd, *buf, st.st_size);
420 e = errno;
415 (*buf)[*size] = '\0'; 421 (*buf)[*size] = '\0';
416 return (*size == st.st_size ? 0 : errno); 422 close(fd);
423 return (*size == st.st_size ? 0 : e);
417} 424}
diff --git a/ui-repolist.c b/ui-repolist.c
index 3ef2e99..0a0b6ca 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -91,13 +91,13 @@ int is_in_url(struct cgit_repo *repo)
91 return 1; 91 return 1;
92 return 0; 92 return 0;
93} 93}
94 94
95void print_sort_header(const char *title, const char *sort) 95void print_sort_header(const char *title, const char *sort)
96{ 96{
97 htmlf("<th class='left'><a href='./?s=%s", sort); 97 htmlf("<th class='left'><a href='%s?s=%s", cgit_rooturl(), sort);
98 if (ctx.qry.search) { 98 if (ctx.qry.search) {
99 html("&q="); 99 html("&q=");
100 html_url_arg(ctx.qry.search); 100 html_url_arg(ctx.qry.search);
101 } 101 }
102 htmlf("'>%s</a></th>", title); 102 htmlf("'>%s</a></th>", title);
103} 103}
diff --git a/ui-shared.c b/ui-shared.c
index de55eff..08ea003 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -17,13 +17,13 @@ const char cgit_doctype[] =
17static char *http_date(time_t t) 17static char *http_date(time_t t)
18{ 18{
19 static char day[][4] = 19 static char day[][4] =
20 {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; 20 {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
21 static char month[][4] = 21 static char month[][4] =
22 {"Jan", "Feb", "Mar", "Apr", "May", "Jun", 22 {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
23 "Jul", "Aug", "Sep", "Oct", "Now", "Dec"}; 23 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
24 struct tm *tm = gmtime(&t); 24 struct tm *tm = gmtime(&t);
25 return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday], 25 return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday],
26 tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year, 26 tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year,
27 tm->tm_hour, tm->tm_min, tm->tm_sec); 27 tm->tm_hour, tm->tm_min, tm->tm_sec);
28} 28}
29 29
@@ -779,17 +779,22 @@ void cgit_print_filemode(unsigned short mode)
779} 779}
780 780
781void cgit_print_snapshot_links(const char *repo, const char *head, 781void cgit_print_snapshot_links(const char *repo, const char *head,
782 const char *hex, int snapshots) 782 const char *hex, int snapshots)
783{ 783{
784 const struct cgit_snapshot_format* f; 784 const struct cgit_snapshot_format* f;
785 char *prefix;
785 char *filename; 786 char *filename;
787 unsigned char sha1[20];
786 788
789 if (get_sha1(fmt("refs/tags/%s", hex), sha1) == 0 &&
790 (hex[0] == 'v' || hex[0] == 'V') && isdigit(hex[1]))
791 hex++;
792 prefix = xstrdup(fmt("%s-%s", cgit_repobasename(repo), hex));
787 for (f = cgit_snapshot_formats; f->suffix; f++) { 793 for (f = cgit_snapshot_formats; f->suffix; f++) {
788 if (!(snapshots & f->bit)) 794 if (!(snapshots & f->bit))
789 continue; 795 continue;
790 filename = fmt("%s-%s%s", cgit_repobasename(repo), hex, 796 filename = fmt("%s%s", prefix, f->suffix);
791 f->suffix);
792 cgit_snapshot_link(filename, NULL, NULL, NULL, NULL, filename); 797 cgit_snapshot_link(filename, NULL, NULL, NULL, NULL, filename);
793 html("<br/>"); 798 html("<br/>");
794 } 799 }
795} 800}
diff --git a/ui-shared.h b/ui-shared.h
index 166246d..9ebc1f9 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -1,11 +1,12 @@
1#ifndef UI_SHARED_H 1#ifndef UI_SHARED_H
2#define UI_SHARED_H 2#define UI_SHARED_H
3 3
4extern char *cgit_httpscheme(); 4extern char *cgit_httpscheme();
5extern char *cgit_hosturl(); 5extern char *cgit_hosturl();
6extern char *cgit_rooturl();
6extern char *cgit_repourl(const char *reponame); 7extern char *cgit_repourl(const char *reponame);
7extern char *cgit_fileurl(const char *reponame, const char *pagename, 8extern char *cgit_fileurl(const char *reponame, const char *pagename,
8 const char *filename, const char *query); 9 const char *filename, const char *query);
9extern char *cgit_pageurl(const char *reponame, const char *pagename, 10extern char *cgit_pageurl(const char *reponame, const char *pagename,
10 const char *query); 11 const char *query);
11 12
diff --git a/ui-tag.c b/ui-tag.c
index c2d72af..39e4cb8 100644
--- a/ui-tag.c
+++ b/ui-tag.c
@@ -27,12 +27,20 @@ static void print_tag_content(char *buf)
27 html("<div class='commit-msg'>"); 27 html("<div class='commit-msg'>");
28 html_txt(++p); 28 html_txt(++p);
29 html("</div>"); 29 html("</div>");
30 } 30 }
31} 31}
32 32
33void print_download_links(char *revname)
34{
35 html("<tr><th>download</th><td class='sha1'>");
36 cgit_print_snapshot_links(ctx.qry.repo, ctx.qry.head,
37 revname, ctx.repo->snapshots);
38 html("</td></tr>");
39}
40
33void cgit_print_tag(char *revname) 41void cgit_print_tag(char *revname)
34{ 42{
35 unsigned char sha1[20]; 43 unsigned char sha1[20];
36 struct object *obj; 44 struct object *obj;
37 struct tag *tag; 45 struct tag *tag;
38 struct taginfo *info; 46 struct taginfo *info;
@@ -53,40 +61,44 @@ void cgit_print_tag(char *revname)
53 tag = lookup_tag(sha1); 61 tag = lookup_tag(sha1);
54 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) { 62 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) {
55 cgit_print_error(fmt("Bad tag object: %s", revname)); 63 cgit_print_error(fmt("Bad tag object: %s", revname));
56 return; 64 return;
57 } 65 }
58 html("<table class='commit-info'>\n"); 66 html("<table class='commit-info'>\n");
59 htmlf("<tr><td>Tag name</td><td>"); 67 htmlf("<tr><td>tag name</td><td>");
60 html_txt(revname); 68 html_txt(revname);
61 htmlf(" (%s)</td></tr>\n", sha1_to_hex(sha1)); 69 htmlf(" (%s)</td></tr>\n", sha1_to_hex(sha1));
62 if (info->tagger_date > 0) { 70 if (info->tagger_date > 0) {
63 html("<tr><td>Tag date</td><td>"); 71 html("<tr><td>tag date</td><td>");
64 cgit_print_date(info->tagger_date, FMT_LONGDATE, ctx.cfg.local_time); 72 cgit_print_date(info->tagger_date, FMT_LONGDATE, ctx.cfg.local_time);
65 html("</td></tr>\n"); 73 html("</td></tr>\n");
66 } 74 }
67 if (info->tagger) { 75 if (info->tagger) {
68 html("<tr><td>Tagged by</td><td>"); 76 html("<tr><td>tagged by</td><td>");
69 html_txt(info->tagger); 77 html_txt(info->tagger);
70 if (info->tagger_email && !ctx.cfg.noplainemail) { 78 if (info->tagger_email && !ctx.cfg.noplainemail) {
71 html(" "); 79 html(" ");
72 html_txt(info->tagger_email); 80 html_txt(info->tagger_email);
73 } 81 }
74 html("</td></tr>\n"); 82 html("</td></tr>\n");
75 } 83 }
76 html("<tr><td>Tagged object</td><td>"); 84 html("<tr><td>tagged object</td><td class='sha1'>");
77 cgit_object_link(tag->tagged); 85 cgit_object_link(tag->tagged);
78 html("</td></tr>\n"); 86 html("</td></tr>\n");
87 if (ctx.repo->snapshots)
88 print_download_links(revname);
79 html("</table>\n"); 89 html("</table>\n");
80 print_tag_content(info->msg); 90 print_tag_content(info->msg);
81 } else { 91 } else {
82 html("<table class='commit-info'>\n"); 92 html("<table class='commit-info'>\n");
83 htmlf("<tr><td>Tag name</td><td>"); 93 htmlf("<tr><td>tag name</td><td>");
84 html_txt(revname); 94 html_txt(revname);
85 html("</td></tr>\n"); 95 html("</td></tr>\n");
86 html("<tr><td>Tagged object</td><td>"); 96 html("<tr><td>Tagged object</td><td class='sha1'>");
87 cgit_object_link(obj); 97 cgit_object_link(obj);
88 html("</td></tr>\n"); 98 html("</td></tr>\n");
99 if (ctx.repo->snapshots)
100 print_download_links(revname);
89 html("</table>\n"); 101 html("</table>\n");
90 } 102 }
91 return; 103 return;
92} 104}
diff --git a/ui-tree.c b/ui-tree.c
index f53ab64..f281937 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -104,12 +104,18 @@ static void print_object(const unsigned char *sha1, char *path, const char *base
104 104
105 html(" ("); 105 html(" (");
106 cgit_plain_link("plain", NULL, NULL, ctx.qry.head, 106 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
107 curr_rev, path); 107 curr_rev, path);
108 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1)); 108 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
109 109
110 if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) {
111 htmlf("<div class='error'>blob size (%dKB) exceeds display size limit (%dKB).</div>",
112 size / 1024, ctx.cfg.max_blob_size);
113 return;
114 }
115
110 if (buffer_is_binary(buf, size)) 116 if (buffer_is_binary(buf, size))
111 print_binary_buffer(buf, size); 117 print_binary_buffer(buf, size);
112 else 118 else
113 print_text_buffer(basename, buf, size); 119 print_text_buffer(basename, buf, size);
114} 120}
115 121