aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
@@ -11,6 +11,9 @@ INSTALL = 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
@@ -68,7 +71,7 @@ endif
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
@@ -124,6 +127,12 @@ endif
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)
@@ -133,8 +142,8 @@ cgit.o: VERSION
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
diff --git a/cgit.c b/cgit.c
index ff678fb..4f68a4b 100644
--- a/cgit.c
+++ b/cgit.c
@@ -68,9 +68,9 @@ void repo_config(struct cgit_repo *repo, const char *name, const char *value)
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);
@@ -165,6 +165,8 @@ void config_cb(const char *name, const char *value)
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"))
@@ -211,6 +213,8 @@ static void querystring_cb(const char *name, const char *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")) {
@@ -272,6 +276,7 @@ static void prepare_context(struct cgit_context *ctx)
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;
diff --git a/cgit.css b/cgit.css
index 9e6d2a4..0cb894a 100644
--- a/cgit.css
+++ b/cgit.css
@@ -162,6 +162,11 @@ table.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}
diff --git a/cgit.h b/cgit.h
index b7b0adb..5941ec0 100644
--- a/cgit.h
+++ b/cgit.h
@@ -186,6 +186,7 @@ struct cgit_config {
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;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 252d546..70e4c78 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -1,3 +1,6 @@
1:man source: cgit
2:man manual: cgit
3
1CGITRC(5) 4CGITRC(5)
2======== 5========
3 6
@@ -174,6 +177,10 @@ max-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
@@ -425,8 +432,8 @@ mimetype.svg=image/svg+xml
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
@@ -448,7 +455,7 @@ repo.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
@@ -461,7 +468,7 @@ repo.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
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
@@ -3,6 +3,10 @@
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):
@@ -20,20 +24,11 @@
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
@@ -400,18 +400,25 @@ int cgit_close_filter(struct cgit_filter *filter)
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
@@ -94,7 +94,7 @@ int is_in_url(struct cgit_repo *repo)
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);
diff --git a/ui-shared.c b/ui-shared.c
index de55eff..08ea003 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -20,7 +20,7 @@ static char *http_date(time_t t)
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,
@@ -782,13 +782,18 @@ void 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 }
diff --git a/ui-shared.h b/ui-shared.h
index 166246d..9ebc1f9 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -3,6 +3,7 @@
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);
diff --git a/ui-tag.c b/ui-tag.c
index c2d72af..39e4cb8 100644
--- a/ui-tag.c
+++ b/ui-tag.c
@@ -30,6 +30,14 @@ static void print_tag_content(char *buf)
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];
@@ -56,16 +64,16 @@ void cgit_print_tag(char *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(" ");
@@ -73,19 +81,23 @@ void cgit_print_tag(char *revname)
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;
diff --git a/ui-tree.c b/ui-tree.c
index f53ab64..f281937 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -107,6 +107,12 @@ static void print_object(const unsigned char *sha1, char *path, const char *base
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