aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--Makefile21
-rw-r--r--cgit-doc.css3
-rw-r--r--cgit.c8
-rw-r--r--cgit.h4
-rw-r--r--cgitrc.5.txt122
-rw-r--r--ui-atom.c6
-rw-r--r--ui-blob.c8
-rw-r--r--ui-plain.c6
-rw-r--r--ui-shared.c26
-rw-r--r--ui-shared.h1
-rw-r--r--ui-snapshot.c23
-rw-r--r--ui-tree.c26
13 files changed, 177 insertions, 82 deletions
diff --git a/.gitignore b/.gitignore
index 1e016e5..487728b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,5 +2,10 @@
2cgit 2cgit
3cgit.conf 3cgit.conf
4VERSION 4VERSION
5cgitrc.5
6cgitrc.5.fo
7cgitrc.5.html
8cgitrc.5.pdf
9cgitrc.5.xml
5*.o 10*.o
6*.d 11*.d
diff --git a/Makefile b/Makefile
index 0f0089a..707d446 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
1CGIT_VERSION = v0.8.2 1CGIT_VERSION = v0.8.2.1
2CGIT_SCRIPT_NAME = cgit.cgi 2CGIT_SCRIPT_NAME = cgit.cgi
3CGIT_SCRIPT_PATH = /var/www/htdocs/cgit 3CGIT_SCRIPT_PATH = /var/www/htdocs/cgit
4CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH) 4CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH)
@@ -100,7 +100,8 @@ ifdef NEEDS_LIBICONV
100endif 100endif
101 101
102 102
103.PHONY: all libgit test install uninstall clean force-version get-git 103.PHONY: all libgit test install uninstall clean force-version get-git \
104 doc man-doc html-doc clean-doc
104 105
105all: cgit 106all: cgit
106 107
@@ -149,8 +150,22 @@ uninstall:
149 rm -f $(CGIT_DATA_PATH)/cgit.css 150 rm -f $(CGIT_DATA_PATH)/cgit.css
150 rm -f $(CGIT_DATA_PATH)/cgit.png 151 rm -f $(CGIT_DATA_PATH)/cgit.png
151 152
152clean: 153doc: man-doc html-doc pdf-doc
154
155man-doc: cgitrc.5.txt
156 a2x -f manpage cgitrc.5.txt
157
158html-doc: cgitrc.5.txt
159 a2x -f xhtml --stylesheet=cgit-doc.css cgitrc.5.txt
160
161pdf-doc: cgitrc.5.txt
162 a2x -f pdf cgitrc.5.txt
163
164clean: clean-doc
153 rm -f cgit VERSION *.o *.d 165 rm -f cgit VERSION *.o *.d
154 166
167clean-doc:
168 rm -f cgitrc.5 cgitrc.5.html cgitrc.5.pdf cgitrc.5.xml cgitrc.5.fo
169
155get-git: 170get-git:
156 curl $(GIT_URL) | tar -xj && rm -rf git && mv git-$(GIT_VER) git 171 curl $(GIT_URL) | tar -xj && rm -rf git && mv git-$(GIT_VER) git
diff --git a/cgit-doc.css b/cgit-doc.css
new file mode 100644
index 0000000..5a399b6
--- /dev/null
+++ b/cgit-doc.css
@@ -0,0 +1,3 @@
1div.variablelist dt {
2 margin-top: 1em;
3}
diff --git a/cgit.c b/cgit.c
index 38f0fdd..2039ab1 100644
--- a/cgit.c
+++ b/cgit.c
@@ -31,6 +31,8 @@ void config_cb(const char *name, const char *value)
31 ctx.cfg.favicon = xstrdup(value); 31 ctx.cfg.favicon = xstrdup(value);
32 else if (!strcmp(name, "footer")) 32 else if (!strcmp(name, "footer"))
33 ctx.cfg.footer = xstrdup(value); 33 ctx.cfg.footer = xstrdup(value);
34 else if (!strcmp(name, "head-include"))
35 ctx.cfg.head_include = xstrdup(value);
34 else if (!strcmp(name, "header")) 36 else if (!strcmp(name, "header"))
35 ctx.cfg.header = xstrdup(value); 37 ctx.cfg.header = xstrdup(value);
36 else if (!strcmp(name, "logo")) 38 else if (!strcmp(name, "logo"))
@@ -210,6 +212,7 @@ static void prepare_context(struct cgit_context *ctx)
210 ctx->page.size = 0; 212 ctx->page.size = 0;
211 ctx->page.modified = time(NULL); 213 ctx->page.modified = time(NULL);
212 ctx->page.expires = ctx->page.modified; 214 ctx->page.expires = ctx->page.modified;
215 ctx->page.etag = NULL;
213} 216}
214 217
215struct refmatch { 218struct refmatch {
@@ -289,6 +292,8 @@ static int prepare_repo_cmd(struct cgit_context *ctx)
289 if (get_sha1(ctx->qry.head, sha1)) { 292 if (get_sha1(ctx->qry.head, sha1)) {
290 tmp = xstrdup(ctx->qry.head); 293 tmp = xstrdup(ctx->qry.head);
291 ctx->qry.head = ctx->repo->defbranch; 294 ctx->qry.head = ctx->repo->defbranch;
295 ctx->page.status = 404;
296 ctx->page.statusmsg = "not found";
292 cgit_print_http_headers(ctx); 297 cgit_print_http_headers(ctx);
293 cgit_print_docstart(ctx); 298 cgit_print_docstart(ctx);
294 cgit_print_pageheader(ctx); 299 cgit_print_pageheader(ctx);
@@ -433,6 +438,7 @@ static int calc_ttl()
433int main(int argc, const char **argv) 438int main(int argc, const char **argv)
434{ 439{
435 const char *cgit_config_env = getenv("CGIT_CONFIG"); 440 const char *cgit_config_env = getenv("CGIT_CONFIG");
441 const char *method = getenv("REQUEST_METHOD");
436 const char *path; 442 const char *path;
437 char *qry; 443 char *qry;
438 int err, ttl; 444 int err, ttl;
@@ -479,6 +485,8 @@ int main(int argc, const char **argv)
479 485
480 ttl = calc_ttl(); 486 ttl = calc_ttl();
481 ctx.page.expires += ttl*60; 487 ctx.page.expires += ttl*60;
488 if (method && !strcmp(method, "HEAD"))
489 ctx.cfg.nocache = 1;
482 if (ctx.cfg.nocache) 490 if (ctx.cfg.nocache)
483 ctx.cfg.cache_size = 0; 491 ctx.cfg.cache_size = 0;
484 err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root, 492 err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root,
diff --git a/cgit.h b/cgit.h
index ca01705..8c64efe 100644
--- a/cgit.h
+++ b/cgit.h
@@ -136,6 +136,7 @@ struct cgit_config {
136 char *css; 136 char *css;
137 char *favicon; 137 char *favicon;
138 char *footer; 138 char *footer;
139 char *head_include;
139 char *header; 140 char *header;
140 char *index_header; 141 char *index_header;
141 char *index_info; 142 char *index_info;
@@ -182,7 +183,10 @@ struct cgit_page {
182 char *mimetype; 183 char *mimetype;
183 char *charset; 184 char *charset;
184 char *filename; 185 char *filename;
186 char *etag;
185 char *title; 187 char *title;
188 int status;
189 char *statusmsg;
186}; 190};
187 191
188struct cgit_context { 192struct cgit_context {
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 771bb7d..a207fe0 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -1,14 +1,14 @@
1CGITRC 1CGITRC(5)
2====== 2========
3 3
4 4
5NAME 5NAME
6---- 6----
7 cgitrc - runtime configuration for cgit 7cgitrc - runtime configuration for cgit
8 8
9 9
10DESCRIPTION 10SYNOPSIS
11----------- 11--------
12Cgitrc contains all runtime settings for cgit, including the list of git 12Cgitrc contains all runtime settings for cgit, including the list of git
13repositories, formatted as a line-separated list of NAME=VALUE pairs. Blank 13repositories, formatted as a line-separated list of NAME=VALUE pairs. Blank
14lines, and lines starting with '#', are ignored. 14lines, and lines starting with '#', are ignored.
@@ -16,175 +16,179 @@ lines, and lines starting with '#', are ignored.
16 16
17GLOBAL SETTINGS 17GLOBAL SETTINGS
18--------------- 18---------------
19agefile 19agefile::
20 Specifies a path, relative to each repository path, which can be used 20 Specifies a path, relative to each repository path, which can be used
21 to specify the date and time of the youngest commit in the repository. 21 to specify the date and time of the youngest commit in the repository.
22 The first line in the file is used as input to the "parse_date" 22 The first line in the file is used as input to the "parse_date"
23 function in libgit. Recommended timestamp-format is "yyyy-mm-dd 23 function in libgit. Recommended timestamp-format is "yyyy-mm-dd
24 hh:mm:ss". Default value: "info/web/last-modified". 24 hh:mm:ss". Default value: "info/web/last-modified".
25 25
26cache-root 26cache-root::
27 Path used to store the cgit cache entries. Default value: 27 Path used to store the cgit cache entries. Default value:
28 "/var/cache/cgit". 28 "/var/cache/cgit".
29 29
30cache-dynamic-ttl 30cache-dynamic-ttl::
31 Number which specifies the time-to-live, in minutes, for the cached 31 Number which specifies the time-to-live, in minutes, for the cached
32 version of repository pages accessed without a fixed SHA1. Default 32 version of repository pages accessed without a fixed SHA1. Default
33 value: "5". 33 value: "5".
34 34
35cache-repo-ttl 35cache-repo-ttl::
36 Number which specifies the time-to-live, in minutes, for the cached 36 Number which specifies the time-to-live, in minutes, for the cached
37 version of the repository summary page. Default value: "5". 37 version of the repository summary page. Default value: "5".
38 38
39cache-root-ttl 39cache-root-ttl::
40 Number which specifies the time-to-live, in minutes, for the cached 40 Number which specifies the time-to-live, in minutes, for the cached
41 version of the repository index page. Default value: "5". 41 version of the repository index page. Default value: "5".
42 42
43cache-size 43cache-size::
44 The maximum number of entries in the cgit cache. Default value: "0" 44 The maximum number of entries in the cgit cache. Default value: "0"
45 (i.e. caching is disabled). 45 (i.e. caching is disabled).
46 46
47cache-static-ttl 47cache-static-ttl::
48 Number which specifies the time-to-live, in minutes, for the cached 48 Number which specifies the time-to-live, in minutes, for the cached
49 version of repository pages accessed with a fixed SHA1. Default value: 49 version of repository pages accessed with a fixed SHA1. Default value:
50 "5". 50 "5".
51 51
52clone-prefix 52clone-prefix::
53 Space-separated list of common prefixes which, when combined with a 53 Space-separated list of common prefixes which, when combined with a
54 repository url, generates valid clone urls for the repository. This 54 repository url, generates valid clone urls for the repository. This
55 setting is only used if `repo.clone-url` is unspecified. Default value: 55 setting is only used if `repo.clone-url` is unspecified. Default value:
56 none. 56 none.
57 57
58css 58css::
59 Url which specifies the css document to include in all cgit pages. 59 Url which specifies the css document to include in all cgit pages.
60 Default value: "/cgit.css". 60 Default value: "/cgit.css".
61 61
62embedded 62embedded::
63 Flag which, when set to "1", will make cgit generate a html fragment 63 Flag which, when set to "1", will make cgit generate a html fragment
64 suitable for embedding in other html pages. Default value: none. See 64 suitable for embedding in other html pages. Default value: none. See
65 also: "noheader". 65 also: "noheader".
66 66
67enable-index-links 67enable-index-links::
68 Flag which, when set to "1", will make cgit generate extra links for 68 Flag which, when set to "1", will make cgit generate extra links for
69 each repo in the repository index (specifically, to the "summary", 69 each repo in the repository index (specifically, to the "summary",
70 "commit" and "tree" pages). Default value: "0". 70 "commit" and "tree" pages). Default value: "0".
71 71
72enable-log-filecount 72enable-log-filecount::
73 Flag which, when set to "1", will make cgit print the number of 73 Flag which, when set to "1", will make cgit print the number of
74 modified files for each commit on the repository log page. Default 74 modified files for each commit on the repository log page. Default
75 value: "0". 75 value: "0".
76 76
77enable-log-linecount 77enable-log-linecount::
78 Flag which, when set to "1", will make cgit print the number of added 78 Flag which, when set to "1", will make cgit print the number of added
79 and removed lines for each commit on the repository log page. Default 79 and removed lines for each commit on the repository log page. Default
80 value: "0". 80 value: "0".
81 81
82favicon 82favicon::
83 Url used as link to a shortcut icon for cgit. If specified, it is 83 Url used as link to a shortcut icon for cgit. If specified, it is
84 suggested to use the value "/favicon.ico" since certain browsers will 84 suggested to use the value "/favicon.ico" since certain browsers will
85 ignore other values. Default value: none. 85 ignore other values. Default value: none.
86 86
87footer 87footer::
88 The content of the file specified with this option will be included 88 The content of the file specified with this option will be included
89 verbatim at the bottom of all pages (i.e. it replaces the standard 89 verbatim at the bottom of all pages (i.e. it replaces the standard
90 "generated by..." message. Default value: none. 90 "generated by..." message. Default value: none.
91 91
92header 92head-include::
93 The content of the file specified with this option will be included
94 verbatim in the html HEAD section on all pages. Default value: none.
95
96header::
93 The content of the file specified with this option will be included 97 The content of the file specified with this option will be included
94 verbatim at the top of all pages. Default value: none. 98 verbatim at the top of all pages. Default value: none.
95 99
96include 100include::
97 Name of a configfile to include before the rest of the current config- 101 Name of a configfile to include before the rest of the current config-
98 file is parsed. Default value: none. 102 file is parsed. Default value: none.
99 103
100index-header 104index-header::
101 The content of the file specified with this option will be included 105 The content of the file specified with this option will be included
102 verbatim above the repository index. This setting is deprecated, and 106 verbatim above the repository index. This setting is deprecated, and
103 will not be supported by cgit-1.0 (use root-readme instead). Default 107 will not be supported by cgit-1.0 (use root-readme instead). Default
104 value: none. 108 value: none.
105 109
106index-info 110index-info::
107 The content of the file specified with this option will be included 111 The content of the file specified with this option will be included
108 verbatim below the heading on the repository index page. This setting 112 verbatim below the heading on the repository index page. This setting
109 is deprecated, and will not be supported by cgit-1.0 (use root-desc 113 is deprecated, and will not be supported by cgit-1.0 (use root-desc
110 instead). Default value: none. 114 instead). Default value: none.
111 115
112local-time 116local-time::
113 Flag which, if set to "1", makes cgit print commit and tag times in the 117 Flag which, if set to "1", makes cgit print commit and tag times in the
114 servers timezone. Default value: "0". 118 servers timezone. Default value: "0".
115 119
116logo 120logo::
117 Url which specifies the source of an image which will be used as a logo 121 Url which specifies the source of an image which will be used as a logo
118 on all cgit pages. 122 on all cgit pages.
119 123
120logo-link 124logo-link::
121 Url loaded when clicking on the cgit logo image. If unspecified the 125 Url loaded when clicking on the cgit logo image. If unspecified the
122 calculated url of the repository index page will be used. Default 126 calculated url of the repository index page will be used. Default
123 value: none. 127 value: none.
124 128
125max-commit-count 129max-commit-count::
126 Specifies the number of entries to list per page in "log" view. Default 130 Specifies the number of entries to list per page in "log" view. Default
127 value: "50". 131 value: "50".
128 132
129max-message-length 133max-message-length::
130 Specifies the maximum number of commit message characters to display in 134 Specifies the maximum number of commit message characters to display in
131 "log" view. Default value: "80". 135 "log" view. Default value: "80".
132 136
133max-repo-count 137max-repo-count::
134 Specifies the number of entries to list per page on the repository 138 Specifies the number of entries to list per page on the repository
135 index page. Default value: "50". 139 index page. Default value: "50".
136 140
137max-repodesc-length 141max-repodesc-length::
138 Specifies the maximum number of repo description characters to display 142 Specifies the maximum number of repo description characters to display
139 on the repository index page. Default value: "80". 143 on the repository index page. Default value: "80".
140 144
141max-stats 145max-stats::
142 Set the default maximum statistics period. Valid values are "week", 146 Set the default maximum statistics period. Valid values are "week",
143 "month", "quarter" and "year". If unspecified, statistics are 147 "month", "quarter" and "year". If unspecified, statistics are
144 disabled. Default value: none. See also: "repo.max-stats". 148 disabled. Default value: none. See also: "repo.max-stats".
145 149
146module-link 150module-link::
147 Text which will be used as the formatstring for a hyperlink when a 151 Text which will be used as the formatstring for a hyperlink when a
148 submodule is printed in a directory listing. The arguments for the 152 submodule is printed in a directory listing. The arguments for the
149 formatstring are the path and SHA1 of the submodule commit. Default 153 formatstring are the path and SHA1 of the submodule commit. Default
150 value: "./?repo=%s&page=commit&id=%s" 154 value: "./?repo=%s&page=commit&id=%s"
151 155
152nocache 156nocache::
153 If set to the value "1" caching will be disabled. This settings is 157 If set to the value "1" caching will be disabled. This settings is
154 deprecated, and will not be honored starting with cgit-1.0. Default 158 deprecated, and will not be honored starting with cgit-1.0. Default
155 value: "0". 159 value: "0".
156 160
157noheader 161noheader::
158 Flag which, when set to "1", will make cgit omit the standard header 162 Flag which, when set to "1", will make cgit omit the standard header
159 on all pages. Default value: none. See also: "embedded". 163 on all pages. Default value: none. See also: "embedded".
160 164
161renamelimit 165renamelimit::
162 Maximum number of files to consider when detecting renames. The value 166 Maximum number of files to consider when detecting renames. The value
163 "-1" uses the compiletime value in git (for further info, look at 167 "-1" uses the compiletime value in git (for further info, look at
164 `man git-diff`). Default value: "-1". 168 `man git-diff`). Default value: "-1".
165 169
166repo.group 170repo.group::
167 A value for the current repository group, which all repositories 171 A value for the current repository group, which all repositories
168 specified after this setting will inherit. Default value: none. 172 specified after this setting will inherit. Default value: none.
169 173
170robots 174robots::
171 Text used as content for the "robots" meta-tag. Default value: 175 Text used as content for the "robots" meta-tag. Default value:
172 "index, nofollow". 176 "index, nofollow".
173 177
174root-desc 178root-desc::
175 Text printed below the heading on the repository index page. Default 179 Text printed below the heading on the repository index page. Default
176 value: "a fast webinterface for the git dscm". 180 value: "a fast webinterface for the git dscm".
177 181
178root-readme: 182root-readme::
179 The content of the file specified with this option will be included 183 The content of the file specified with this option will be included
180 verbatim below the "about" link on the repository index page. Default 184 verbatim below the "about" link on the repository index page. Default
181 value: none. 185 value: none.
182 186
183root-title 187root-title::
184 Text printed as heading on the repository index page. Default value: 188 Text printed as heading on the repository index page. Default value:
185 "Git Repository Browser". 189 "Git Repository Browser".
186 190
187snapshots 191snapshots::
188 Text which specifies the default (and allowed) set of snapshot formats 192 Text which specifies the default (and allowed) set of snapshot formats
189 supported by cgit. The value is a space-separated list of zero or more 193 supported by cgit. The value is a space-separated list of zero or more
190 of the following values: 194 of the following values:
@@ -194,19 +198,19 @@ snapshots
194 "zip" zip-file 198 "zip" zip-file
195 Default value: none. 199 Default value: none.
196 200
197summary-branches 201summary-branches::
198 Specifies the number of branches to display in the repository "summary" 202 Specifies the number of branches to display in the repository "summary"
199 view. Default value: "10". 203 view. Default value: "10".
200 204
201summary-log 205summary-log::
202 Specifies the number of log entries to display in the repository 206 Specifies the number of log entries to display in the repository
203 "summary" view. Default value: "10". 207 "summary" view. Default value: "10".
204 208
205summary-tags 209summary-tags::
206 Specifies the number of tags to display in the repository "summary" 210 Specifies the number of tags to display in the repository "summary"
207 view. Default value: "10". 211 view. Default value: "10".
208 212
209virtual-root 213virtual-root::
210 Url which, if specified, will be used as root for all cgit links. It 214 Url which, if specified, will be used as root for all cgit links. It
211 will also cause cgit to generate 'virtual urls', i.e. urls like 215 will also cause cgit to generate 'virtual urls', i.e. urls like
212 '/cgit/tree/README' as opposed to '?r=cgit&p=tree&path=README'. Default 216 '/cgit/tree/README' as opposed to '?r=cgit&p=tree&path=README'. Default
@@ -216,51 +220,51 @@ virtual-root
216 220
217REPOSITORY SETTINGS 221REPOSITORY SETTINGS
218------------------- 222-------------------
219repo.clone-url 223repo.clone-url::
220 A list of space-separated urls which can be used to clone this repo. 224 A list of space-separated urls which can be used to clone this repo.
221 Default value: none. 225 Default value: none.
222 226
223repo.defbranch 227repo.defbranch::
224 The name of the default branch for this repository. If no such branch 228 The name of the default branch for this repository. If no such branch
225 exists in the repository, the first branch name (when sorted) is used 229 exists in the repository, the first branch name (when sorted) is used
226 as default instead. Default value: "master". 230 as default instead. Default value: "master".
227 231
228repo.desc 232repo.desc::
229 The value to show as repository description. Default value: none. 233 The value to show as repository description. Default value: none.
230 234
231repo.enable-log-filecount 235repo.enable-log-filecount::
232 A flag which can be used to disable the global setting 236 A flag which can be used to disable the global setting
233 `enable-log-filecount'. Default value: none. 237 `enable-log-filecount'. Default value: none.
234 238
235repo.enable-log-linecount 239repo.enable-log-linecount::
236 A flag which can be used to disable the global setting 240 A flag which can be used to disable the global setting
237 `enable-log-linecount'. Default value: none. 241 `enable-log-linecount'. Default value: none.
238 242
239repo.max-stats 243repo.max-stats::
240 Override the default maximum statistics period. Valid values are equal 244 Override the default maximum statistics period. Valid values are equal
241 to the values specified for the global "max-stats" setting. Default 245 to the values specified for the global "max-stats" setting. Default
242 value: none. 246 value: none.
243 247
244repo.name 248repo.name::
245 The value to show as repository name. Default value: <repo.url>. 249 The value to show as repository name. Default value: <repo.url>.
246 250
247repo.owner 251repo.owner::
248 A value used to identify the owner of the repository. Default value: 252 A value used to identify the owner of the repository. Default value:
249 none. 253 none.
250 254
251repo.path 255repo.path::
252 An absolute path to the repository directory. For non-bare repositories 256 An absolute path to the repository directory. For non-bare repositories
253 this is the .git-directory. Default value: none. 257 this is the .git-directory. Default value: none.
254 258
255repo.readme 259repo.readme::
256 A path (relative to <repo.path>) which specifies a file to include 260 A path (relative to <repo.path>) which specifies a file to include
257 verbatim as the "About" page for this repo. Default value: none. 261 verbatim as the "About" page for this repo. Default value: none.
258 262
259repo.snapshots 263repo.snapshots::
260 A mask of allowed snapshot-formats for this repo, restricted by the 264 A mask of allowed snapshot-formats for this repo, restricted by the
261 "snapshots" global setting. Default value: <snapshots>. 265 "snapshots" global setting. Default value: <snapshots>.
262 266
263repo.url 267repo.url::
264 The relative url used to access the repository. This must be the first 268 The relative url used to access the repository. This must be the first
265 setting specified for each repo. Default value: none. 269 setting specified for each repo. Default value: none.
266 270
@@ -268,6 +272,7 @@ repo.url
268EXAMPLE CGITRC FILE 272EXAMPLE CGITRC FILE
269------------------- 273-------------------
270 274
275....
271# Enable caching of up to 1000 output entriess 276# Enable caching of up to 1000 output entriess
272cache-size=1000 277cache-size=1000
273 278
@@ -377,6 +382,7 @@ repo.enable-log-linecount=0
377 382
378# Restrict the max statistics period for this repo 383# Restrict the max statistics period for this repo
379repo.max-stats=month 384repo.max-stats=month
385....
380 386
381 387
382BUGS 388BUGS
diff --git a/ui-atom.c b/ui-atom.c
index a6ea3ee..e5c31d9 100644
--- a/ui-atom.c
+++ b/ui-atom.c
@@ -52,7 +52,8 @@ void add_entry(struct commit *commit, char *host)
52 cgit_print_date(info->author_date, FMT_ATOMDATE, ctx.cfg.local_time); 52 cgit_print_date(info->author_date, FMT_ATOMDATE, ctx.cfg.local_time);
53 html("</published>\n"); 53 html("</published>\n");
54 if (host) { 54 if (host) {
55 html("<link rel='alternate' type='text/html' href='http://"); 55 html("<link rel='alternate' type='text/html' href='");
56 html(cgit_httpscheme());
56 html_attr(host); 57 html_attr(host);
57 html_attr(cgit_pageurl(ctx.repo->url, "commit", NULL)); 58 html_attr(cgit_pageurl(ctx.repo->url, "commit", NULL));
58 if (ctx.cfg.virtual_root) 59 if (ctx.cfg.virtual_root)
@@ -113,7 +114,8 @@ void cgit_print_atom(char *tip, char *path, int max_count)
113 html_txt(ctx.repo->desc); 114 html_txt(ctx.repo->desc);
114 html("</subtitle>\n"); 115 html("</subtitle>\n");
115 if (host) { 116 if (host) {
116 html("<link rel='alternate' type='text/html' href='http://"); 117 html("<link rel='alternate' type='text/html' href='");
118 html(cgit_httpscheme());
117 html_attr(host); 119 html_attr(host);
118 html_attr(cgit_repourl(ctx.repo->url)); 120 html_attr(cgit_repourl(ctx.repo->url));
119 html("'/>\n"); 121 html("'/>\n");
diff --git a/ui-blob.c b/ui-blob.c
index 3cda03d..2ccd31d 100644
--- a/ui-blob.c
+++ b/ui-blob.c
@@ -27,7 +27,7 @@ void cgit_print_blob(const char *hex, char *path, const char *head)
27 27
28 unsigned char sha1[20]; 28 unsigned char sha1[20];
29 enum object_type type; 29 enum object_type type;
30 unsigned char *buf; 30 char *buf;
31 unsigned long size; 31 unsigned long size;
32 struct commit *commit; 32 struct commit *commit;
33 const char *paths[] = {path, NULL}; 33 const char *paths[] = {path, NULL};
@@ -67,6 +67,12 @@ void cgit_print_blob(const char *hex, char *path, const char *head)
67 67
68 buf[size] = '\0'; 68 buf[size] = '\0';
69 ctx.page.mimetype = ctx.qry.mimetype; 69 ctx.page.mimetype = ctx.qry.mimetype;
70 if (!ctx.page.mimetype) {
71 if (buffer_is_binary(buf, size))
72 ctx.page.mimetype = "application/octet-stream";
73 else
74 ctx.page.mimetype = "text/plain";
75 }
70 ctx.page.filename = path; 76 ctx.page.filename = path;
71 cgit_print_http_headers(&ctx); 77 cgit_print_http_headers(&ctx);
72 write(htmlfd, buf, size); 78 write(htmlfd, buf, size);
diff --git a/ui-plain.c b/ui-plain.c
index 5addd9e..93a3a05 100644
--- a/ui-plain.c
+++ b/ui-plain.c
@@ -31,9 +31,13 @@ static void print_object(const unsigned char *sha1, const char *path)
31 html_status(404, "Not found", 0); 31 html_status(404, "Not found", 0);
32 return; 32 return;
33 } 33 }
34 ctx.page.mimetype = "text/plain"; 34 if (buffer_is_binary(buf, size))
35 ctx.page.mimetype = "application/octet-stream";
36 else
37 ctx.page.mimetype = "text/plain";
35 ctx.page.filename = fmt("%s", path); 38 ctx.page.filename = fmt("%s", path);
36 ctx.page.size = size; 39 ctx.page.size = size;
40 ctx.page.etag = sha1_to_hex(sha1);
37 cgit_print_http_headers(&ctx); 41 cgit_print_http_headers(&ctx);
38 html_raw(buf, size); 42 html_raw(buf, size);
39 match = 1; 43 match = 1;
diff --git a/ui-shared.c b/ui-shared.c
index 5e03a7a..015c52b 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -34,6 +34,17 @@ void cgit_print_error(char *msg)
34 html("</div>\n"); 34 html("</div>\n");
35} 35}
36 36
37char *cgit_httpscheme()
38{
39 char *https;
40
41 https = getenv("HTTPS");
42 if (https != NULL && strcmp(https, "on") == 0)
43 return "https://";
44 else
45 return "http://";
46}
47
37char *cgit_hosturl() 48char *cgit_hosturl()
38{ 49{
39 char *host, *port; 50 char *host, *port;
@@ -456,9 +467,13 @@ void cgit_print_age(time_t t, time_t max_relative, char *format)
456 467
457void cgit_print_http_headers(struct cgit_context *ctx) 468void cgit_print_http_headers(struct cgit_context *ctx)
458{ 469{
470 const char *method = getenv("REQUEST_METHOD");
471
459 if (ctx->cfg.embedded) 472 if (ctx->cfg.embedded)
460 return; 473 return;
461 474
475 if (ctx->page.status)
476 htmlf("Status: %d %s\n", ctx->page.status, ctx->page.statusmsg);
462 if (ctx->page.mimetype && ctx->page.charset) 477 if (ctx->page.mimetype && ctx->page.charset)
463 htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype, 478 htmlf("Content-Type: %s; charset=%s\n", ctx->page.mimetype,
464 ctx->page.charset); 479 ctx->page.charset);
@@ -471,7 +486,11 @@ void cgit_print_http_headers(struct cgit_context *ctx)
471 ctx->page.filename); 486 ctx->page.filename);
472 htmlf("Last-Modified: %s\n", http_date(ctx->page.modified)); 487 htmlf("Last-Modified: %s\n", http_date(ctx->page.modified));
473 htmlf("Expires: %s\n", http_date(ctx->page.expires)); 488 htmlf("Expires: %s\n", http_date(ctx->page.expires));
489 if (ctx->page.etag)
490 htmlf("ETag: \"%s\"\n", ctx->page.etag);
474 html("\n"); 491 html("\n");
492 if (method && !strcmp(method, "HEAD"))
493 exit(0);
475} 494}
476 495
477void cgit_print_docstart(struct cgit_context *ctx) 496void cgit_print_docstart(struct cgit_context *ctx)
@@ -498,12 +517,15 @@ void cgit_print_docstart(struct cgit_context *ctx)
498 html("'/>\n"); 517 html("'/>\n");
499 } 518 }
500 if (host && ctx->repo) { 519 if (host && ctx->repo) {
501 html("<link rel='alternate' title='Atom feed' href='http://"); 520 html("<link rel='alternate' title='Atom feed' href='");
521 html(cgit_httpscheme());
502 html_attr(cgit_hosturl()); 522 html_attr(cgit_hosturl());
503 html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path, 523 html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path,
504 fmt("h=%s", ctx->qry.head))); 524 fmt("h=%s", ctx->qry.head)));
505 html("' type='application/atom+xml'/>"); 525 html("' type='application/atom+xml'/>\n");
506 } 526 }
527 if (ctx->cfg.head_include)
528 html_include(ctx->cfg.head_include);
507 html("</head>\n"); 529 html("</head>\n");
508 html("<body>\n"); 530 html("<body>\n");
509 if (ctx->cfg.header) 531 if (ctx->cfg.header)
diff --git a/ui-shared.h b/ui-shared.h
index 5a3821f..bff4826 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -1,6 +1,7 @@
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_hosturl(); 5extern char *cgit_hosturl();
5extern char *cgit_repourl(const char *reponame); 6extern char *cgit_repourl(const char *reponame);
6extern char *cgit_fileurl(const char *reponame, const char *pagename, 7extern char *cgit_fileurl(const char *reponame, const char *pagename,
diff --git a/ui-snapshot.c b/ui-snapshot.c
index f25613e..5372f5d 100644
--- a/ui-snapshot.c
+++ b/ui-snapshot.c
@@ -156,20 +156,31 @@ static const char *get_ref_from_filename(const char *url, const char *filename,
156 return NULL; 156 return NULL;
157} 157}
158 158
159void show_error(char *msg)
160{
161 ctx.page.mimetype = "text/html";
162 cgit_print_http_headers(&ctx);
163 cgit_print_docstart(&ctx);
164 cgit_print_pageheader(&ctx);
165 cgit_print_error(msg);
166 cgit_print_docend();
167}
168
159void cgit_print_snapshot(const char *head, const char *hex, 169void cgit_print_snapshot(const char *head, const char *hex,
160 const char *filename, int snapshots, int dwim) 170 const char *filename, int snapshots, int dwim)
161{ 171{
162 const struct cgit_snapshot_format* f; 172 const struct cgit_snapshot_format* f;
163 char *prefix = NULL; 173 char *prefix = NULL;
164 174
175 if (!filename) {
176 show_error("No snapshot name specified");
177 return;
178 }
179
165 f = get_format(filename); 180 f = get_format(filename);
166 if (!f) { 181 if (!f) {
167 ctx.page.mimetype = "text/html"; 182 show_error(xstrdup(fmt("Unsupported snapshot format: %s",
168 cgit_print_http_headers(&ctx); 183 filename)));
169 cgit_print_docstart(&ctx);
170 cgit_print_pageheader(&ctx);
171 cgit_print_error(fmt("Unsupported snapshot format: %s", filename));
172 cgit_print_docend();
173 return; 184 return;
174 } 185 }
175 186
diff --git a/ui-tree.c b/ui-tree.c
index a37a4e5..553dbaa 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -25,11 +25,14 @@ static void print_text_buffer(char *buf, unsigned long size)
25 html("<tr><td class='linenumbers'><pre>"); 25 html("<tr><td class='linenumbers'><pre>");
26 idx = 0; 26 idx = 0;
27 lineno = 0; 27 lineno = 0;
28 htmlf(numberfmt, ++lineno); 28
29 while(idx < size - 1) { // skip absolute last newline 29 if (size) {
30 if (buf[idx] == '\n') 30 htmlf(numberfmt, ++lineno);
31 htmlf(numberfmt, ++lineno); 31 while(idx < size - 1) { // skip absolute last newline
32 idx++; 32 if (buf[idx] == '\n')
33 htmlf(numberfmt, ++lineno);
34 idx++;
35 }
33 } 36 }
34 html("</pre></td>\n"); 37 html("</pre></td>\n");
35 html("<td class='lines'><pre><code>"); 38 html("<td class='lines'><pre><code>");
@@ -37,21 +40,26 @@ static void print_text_buffer(char *buf, unsigned long size)
37 html("</code></pre></td></tr></table>\n"); 40 html("</code></pre></td></tr></table>\n");
38} 41}
39 42
43#define ROWLEN 32
44
40static void print_binary_buffer(char *buf, unsigned long size) 45static void print_binary_buffer(char *buf, unsigned long size)
41{ 46{
42 unsigned long ofs, idx; 47 unsigned long ofs, idx;
48 static char ascii[ROWLEN + 1];
43 49
44 html("<table summary='blob content' class='bin-blob'>\n"); 50 html("<table summary='blob content' class='bin-blob'>\n");
45 html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>"); 51 html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>");
46 for (ofs = 0; ofs < size; ofs += 32, buf += 32) { 52 for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) {
47 htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs); 53 htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs);
48 for (idx = 0; idx < 32 && ofs + idx < size; idx++) 54 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++)
49 htmlf("%*s%02x", 55 htmlf("%*s%02x",
50 idx == 16 ? 4 : 1, "", 56 idx == 16 ? 4 : 1, "",
51 buf[idx] & 0xff); 57 buf[idx] & 0xff);
52 html(" </td><td class='hex'>"); 58 html(" </td><td class='hex'>");
53 for (idx = 0; idx < 32 && ofs + idx < size; idx++) 59 for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++)
54 htmlf("%c", isgraph(buf[idx]) ? buf[idx] : '.'); 60 ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.';
61 ascii[idx] = '\0';
62 html_txt(ascii);
55 html("</td></tr>\n"); 63 html("</td></tr>\n");
56 } 64 }
57 html("</table>\n"); 65 html("</table>\n");