summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2008-03-24 00:00:36 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2008-03-24 00:01:28 (UTC)
commitb608e88adb6f77328288afb6dd0eddf674fc9b5b (patch) (unidiff)
treee194a466ba00d67bc037c76329ca050e84e1223b
parentf3c1a187fe2bc33f8423cd535d5045899699995b (diff)
downloadcgit-b608e88adb6f77328288afb6dd0eddf674fc9b5b.zip
cgit-b608e88adb6f77328288afb6dd0eddf674fc9b5b.tar.gz
cgit-b608e88adb6f77328288afb6dd0eddf674fc9b5b.tar.bz2
Remove obsolete cacheitem parameter to ui-functions
This parameter hasn't been used for a very long time... Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c12
-rw-r--r--cgit.h12
-rw-r--r--ui-blob.c2
-rw-r--r--ui-patch.c2
-rw-r--r--ui-repolist.c2
-rw-r--r--ui-snapshot.c3
6 files changed, 16 insertions, 17 deletions
diff --git a/cgit.c b/cgit.c
index d0f6905..a83f0be 100644
--- a/cgit.c
+++ b/cgit.c
@@ -1,332 +1,332 @@
1/* cgit.c: cgi for the git scm 1/* cgit.c: cgi for the git scm
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include "cmd.h" 10#include "cmd.h"
11 11
12static int cgit_prepare_cache(struct cacheitem *item) 12static int cgit_prepare_cache(struct cacheitem *item)
13{ 13{
14 if (!ctx.repo && ctx.qry.repo) { 14 if (!ctx.repo && ctx.qry.repo) {
15 ctx.page.title = fmt("%s - %s", ctx.cfg.root_title, 15 ctx.page.title = fmt("%s - %s", ctx.cfg.root_title,
16 "Bad request"); 16 "Bad request");
17 cgit_print_http_headers(&ctx); 17 cgit_print_http_headers(&ctx);
18 cgit_print_docstart(&ctx); 18 cgit_print_docstart(&ctx);
19 cgit_print_pageheader(&ctx); 19 cgit_print_pageheader(&ctx);
20 cgit_print_error(fmt("Unknown repo: %s", ctx.qry.repo)); 20 cgit_print_error(fmt("Unknown repo: %s", ctx.qry.repo));
21 cgit_print_docend(); 21 cgit_print_docend();
22 return 0; 22 return 0;
23 } 23 }
24 24
25 if (!ctx.repo) { 25 if (!ctx.repo) {
26 item->name = xstrdup(fmt("%s/index.html", ctx.cfg.cache_root)); 26 item->name = xstrdup(fmt("%s/index.html", ctx.cfg.cache_root));
27 item->ttl = ctx.cfg.cache_root_ttl; 27 item->ttl = ctx.cfg.cache_root_ttl;
28 return 1; 28 return 1;
29 } 29 }
30 30
31 if (!cgit_cmd) { 31 if (!cgit_cmd) {
32 item->name = xstrdup(fmt("%s/%s/index.%s.html", ctx.cfg.cache_root, 32 item->name = xstrdup(fmt("%s/%s/index.%s.html", ctx.cfg.cache_root,
33 cache_safe_filename(ctx.repo->url), 33 cache_safe_filename(ctx.repo->url),
34 cache_safe_filename(ctx.qry.raw))); 34 cache_safe_filename(ctx.qry.raw)));
35 item->ttl = ctx.cfg.cache_repo_ttl; 35 item->ttl = ctx.cfg.cache_repo_ttl;
36 } else { 36 } else {
37 item->name = xstrdup(fmt("%s/%s/%s/%s.html", ctx.cfg.cache_root, 37 item->name = xstrdup(fmt("%s/%s/%s/%s.html", ctx.cfg.cache_root,
38 cache_safe_filename(ctx.repo->url), 38 cache_safe_filename(ctx.repo->url),
39 ctx.qry.page, 39 ctx.qry.page,
40 cache_safe_filename(ctx.qry.raw))); 40 cache_safe_filename(ctx.qry.raw)));
41 if (ctx.qry.has_symref) 41 if (ctx.qry.has_symref)
42 item->ttl = ctx.cfg.cache_dynamic_ttl; 42 item->ttl = ctx.cfg.cache_dynamic_ttl;
43 else if (ctx.qry.has_sha1) 43 else if (ctx.qry.has_sha1)
44 item->ttl = ctx.cfg.cache_static_ttl; 44 item->ttl = ctx.cfg.cache_static_ttl;
45 else 45 else
46 item->ttl = ctx.cfg.cache_repo_ttl; 46 item->ttl = ctx.cfg.cache_repo_ttl;
47 } 47 }
48 return 1; 48 return 1;
49} 49}
50 50
51struct refmatch { 51struct refmatch {
52 char *req_ref; 52 char *req_ref;
53 char *first_ref; 53 char *first_ref;
54 int match; 54 int match;
55}; 55};
56 56
57int find_current_ref(const char *refname, const unsigned char *sha1, 57int find_current_ref(const char *refname, const unsigned char *sha1,
58 int flags, void *cb_data) 58 int flags, void *cb_data)
59{ 59{
60 struct refmatch *info; 60 struct refmatch *info;
61 61
62 info = (struct refmatch *)cb_data; 62 info = (struct refmatch *)cb_data;
63 if (!strcmp(refname, info->req_ref)) 63 if (!strcmp(refname, info->req_ref))
64 info->match = 1; 64 info->match = 1;
65 if (!info->first_ref) 65 if (!info->first_ref)
66 info->first_ref = xstrdup(refname); 66 info->first_ref = xstrdup(refname);
67 return info->match; 67 return info->match;
68} 68}
69 69
70char *find_default_branch(struct cgit_repo *repo) 70char *find_default_branch(struct cgit_repo *repo)
71{ 71{
72 struct refmatch info; 72 struct refmatch info;
73 73
74 info.req_ref = repo->defbranch; 74 info.req_ref = repo->defbranch;
75 info.first_ref = NULL; 75 info.first_ref = NULL;
76 info.match = 0; 76 info.match = 0;
77 for_each_branch_ref(find_current_ref, &info); 77 for_each_branch_ref(find_current_ref, &info);
78 if (info.match) 78 if (info.match)
79 return info.req_ref; 79 return info.req_ref;
80 else 80 else
81 return info.first_ref; 81 return info.first_ref;
82} 82}
83 83
84static void cgit_print_repo_page(struct cacheitem *item) 84static void cgit_print_repo_page()
85{ 85{
86 char *tmp; 86 char *tmp;
87 int show_search; 87 int show_search;
88 unsigned char sha1[20]; 88 unsigned char sha1[20];
89 int nongit = 0; 89 int nongit = 0;
90 90
91 setenv("GIT_DIR", ctx.repo->path, 1); 91 setenv("GIT_DIR", ctx.repo->path, 1);
92 setup_git_directory_gently(&nongit); 92 setup_git_directory_gently(&nongit);
93 if (nongit) { 93 if (nongit) {
94 ctx.page.title = fmt("%s - %s", ctx.cfg.root_title, 94 ctx.page.title = fmt("%s - %s", ctx.cfg.root_title,
95 "config error"); 95 "config error");
96 tmp = fmt("Not a git repository: '%s'", ctx.repo->path); 96 tmp = fmt("Not a git repository: '%s'", ctx.repo->path);
97 ctx.repo = NULL; 97 ctx.repo = NULL;
98 cgit_print_http_headers(&ctx); 98 cgit_print_http_headers(&ctx);
99 cgit_print_docstart(&ctx); 99 cgit_print_docstart(&ctx);
100 cgit_print_pageheader(&ctx); 100 cgit_print_pageheader(&ctx);
101 cgit_print_error(tmp); 101 cgit_print_error(tmp);
102 cgit_print_docend(); 102 cgit_print_docend();
103 return; 103 return;
104 } 104 }
105 105
106 ctx.page.title = fmt("%s - %s", ctx.repo->name, ctx.repo->desc); 106 ctx.page.title = fmt("%s - %s", ctx.repo->name, ctx.repo->desc);
107 show_search = 0; 107 show_search = 0;
108 108
109 if (!ctx.qry.head) { 109 if (!ctx.qry.head) {
110 ctx.qry.head = xstrdup(find_default_branch(ctx.repo)); 110 ctx.qry.head = xstrdup(find_default_branch(ctx.repo));
111 ctx.repo->defbranch = ctx.qry.head; 111 ctx.repo->defbranch = ctx.qry.head;
112 } 112 }
113 113
114 if (!ctx.qry.head) { 114 if (!ctx.qry.head) {
115 cgit_print_http_headers(&ctx); 115 cgit_print_http_headers(&ctx);
116 cgit_print_docstart(&ctx); 116 cgit_print_docstart(&ctx);
117 cgit_print_pageheader(&ctx); 117 cgit_print_pageheader(&ctx);
118 cgit_print_error("Repository seems to be empty"); 118 cgit_print_error("Repository seems to be empty");
119 cgit_print_docend(); 119 cgit_print_docend();
120 return; 120 return;
121 } 121 }
122 122
123 if (get_sha1(ctx.qry.head, sha1)) { 123 if (get_sha1(ctx.qry.head, sha1)) {
124 tmp = xstrdup(ctx.qry.head); 124 tmp = xstrdup(ctx.qry.head);
125 ctx.qry.head = ctx.repo->defbranch; 125 ctx.qry.head = ctx.repo->defbranch;
126 cgit_print_http_headers(&ctx); 126 cgit_print_http_headers(&ctx);
127 cgit_print_docstart(&ctx); 127 cgit_print_docstart(&ctx);
128 cgit_print_pageheader(&ctx); 128 cgit_print_pageheader(&ctx);
129 cgit_print_error(fmt("Invalid branch: %s", tmp)); 129 cgit_print_error(fmt("Invalid branch: %s", tmp));
130 cgit_print_docend(); 130 cgit_print_docend();
131 return; 131 return;
132 } 132 }
133 133
134 if ((cgit_cmd == CMD_SNAPSHOT) && ctx.repo->snapshots) { 134 if ((cgit_cmd == CMD_SNAPSHOT) && ctx.repo->snapshots) {
135 cgit_print_snapshot(item, ctx.qry.head, ctx.qry.sha1, 135 cgit_print_snapshot(ctx.qry.head, ctx.qry.sha1,
136 cgit_repobasename(ctx.repo->url), 136 cgit_repobasename(ctx.repo->url),
137 ctx.qry.path, 137 ctx.qry.path,
138 ctx.repo->snapshots ); 138 ctx.repo->snapshots );
139 return; 139 return;
140 } 140 }
141 141
142 if (cgit_cmd == CMD_PATCH) { 142 if (cgit_cmd == CMD_PATCH) {
143 cgit_print_patch(ctx.qry.sha1, item); 143 cgit_print_patch(ctx.qry.sha1);
144 return; 144 return;
145 } 145 }
146 146
147 if (cgit_cmd == CMD_BLOB) { 147 if (cgit_cmd == CMD_BLOB) {
148 cgit_print_blob(item, ctx.qry.sha1, ctx.qry.path); 148 cgit_print_blob(ctx.qry.sha1, ctx.qry.path);
149 return; 149 return;
150 } 150 }
151 151
152 show_search = (cgit_cmd == CMD_LOG); 152 show_search = (cgit_cmd == CMD_LOG);
153 cgit_print_http_headers(&ctx); 153 cgit_print_http_headers(&ctx);
154 cgit_print_docstart(&ctx); 154 cgit_print_docstart(&ctx);
155 if (!cgit_cmd) { 155 if (!cgit_cmd) {
156 cgit_print_pageheader(&ctx); 156 cgit_print_pageheader(&ctx);
157 cgit_print_summary(); 157 cgit_print_summary();
158 cgit_print_docend(); 158 cgit_print_docend();
159 return; 159 return;
160 } 160 }
161 161
162 cgit_print_pageheader(&ctx); 162 cgit_print_pageheader(&ctx);
163 163
164 switch(cgit_cmd) { 164 switch(cgit_cmd) {
165 case CMD_LOG: 165 case CMD_LOG:
166 cgit_print_log(ctx.qry.sha1, ctx.qry.ofs, 166 cgit_print_log(ctx.qry.sha1, ctx.qry.ofs,
167 ctx.cfg.max_commit_count, ctx.qry.grep, ctx.qry.search, 167 ctx.cfg.max_commit_count, ctx.qry.grep, ctx.qry.search,
168 ctx.qry.path, 1); 168 ctx.qry.path, 1);
169 break; 169 break;
170 case CMD_TREE: 170 case CMD_TREE:
171 cgit_print_tree(ctx.qry.sha1, ctx.qry.path); 171 cgit_print_tree(ctx.qry.sha1, ctx.qry.path);
172 break; 172 break;
173 case CMD_COMMIT: 173 case CMD_COMMIT:
174 cgit_print_commit(ctx.qry.sha1); 174 cgit_print_commit(ctx.qry.sha1);
175 break; 175 break;
176 case CMD_REFS: 176 case CMD_REFS:
177 cgit_print_refs(); 177 cgit_print_refs();
178 break; 178 break;
179 case CMD_TAG: 179 case CMD_TAG:
180 cgit_print_tag(ctx.qry.sha1); 180 cgit_print_tag(ctx.qry.sha1);
181 break; 181 break;
182 case CMD_DIFF: 182 case CMD_DIFF:
183 cgit_print_diff(ctx.qry.sha1, ctx.qry.sha2, ctx.qry.path); 183 cgit_print_diff(ctx.qry.sha1, ctx.qry.sha2, ctx.qry.path);
184 break; 184 break;
185 default: 185 default:
186 cgit_print_error("Invalid request"); 186 cgit_print_error("Invalid request");
187 } 187 }
188 cgit_print_docend(); 188 cgit_print_docend();
189} 189}
190 190
191static long ttl_seconds(long ttl) 191static long ttl_seconds(long ttl)
192{ 192{
193 if (ttl<0) 193 if (ttl<0)
194 return 60 * 60 * 24 * 365; 194 return 60 * 60 * 24 * 365;
195 else 195 else
196 return ttl * 60; 196 return ttl * 60;
197} 197}
198 198
199static void cgit_fill_cache(struct cacheitem *item, int use_cache) 199static void cgit_fill_cache(struct cacheitem *item, int use_cache)
200{ 200{
201 int stdout2; 201 int stdout2;
202 202
203 if (use_cache) { 203 if (use_cache) {
204 stdout2 = chk_positive(dup(STDOUT_FILENO), 204 stdout2 = chk_positive(dup(STDOUT_FILENO),
205 "Preserving STDOUT"); 205 "Preserving STDOUT");
206 chk_zero(close(STDOUT_FILENO), "Closing STDOUT"); 206 chk_zero(close(STDOUT_FILENO), "Closing STDOUT");
207 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)"); 207 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)");
208 } 208 }
209 209
210 ctx.page.modified = time(NULL); 210 ctx.page.modified = time(NULL);
211 ctx.page.expires = ctx.page.modified + ttl_seconds(item->ttl); 211 ctx.page.expires = ctx.page.modified + ttl_seconds(item->ttl);
212 if (ctx.repo) 212 if (ctx.repo)
213 cgit_print_repo_page(item); 213 cgit_print_repo_page();
214 else 214 else
215 cgit_print_repolist(item); 215 cgit_print_repolist();
216 216
217 if (use_cache) { 217 if (use_cache) {
218 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT"); 218 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT");
219 chk_positive(dup2(stdout2, STDOUT_FILENO), 219 chk_positive(dup2(stdout2, STDOUT_FILENO),
220 "Restoring original STDOUT"); 220 "Restoring original STDOUT");
221 chk_zero(close(stdout2), "Closing temporary STDOUT"); 221 chk_zero(close(stdout2), "Closing temporary STDOUT");
222 } 222 }
223} 223}
224 224
225static void cgit_check_cache(struct cacheitem *item) 225static void cgit_check_cache(struct cacheitem *item)
226{ 226{
227 int i = 0; 227 int i = 0;
228 228
229 top: 229 top:
230 if (++i > ctx.cfg.max_lock_attempts) { 230 if (++i > ctx.cfg.max_lock_attempts) {
231 die("cgit_refresh_cache: unable to lock %s: %s", 231 die("cgit_refresh_cache: unable to lock %s: %s",
232 item->name, strerror(errno)); 232 item->name, strerror(errno));
233 } 233 }
234 if (!cache_exist(item)) { 234 if (!cache_exist(item)) {
235 if (!cache_lock(item)) { 235 if (!cache_lock(item)) {
236 sleep(1); 236 sleep(1);
237 goto top; 237 goto top;
238 } 238 }
239 if (!cache_exist(item)) { 239 if (!cache_exist(item)) {
240 cgit_fill_cache(item, 1); 240 cgit_fill_cache(item, 1);
241 cache_unlock(item); 241 cache_unlock(item);
242 } else { 242 } else {
243 cache_cancel_lock(item); 243 cache_cancel_lock(item);
244 } 244 }
245 } else if (cache_expired(item) && cache_lock(item)) { 245 } else if (cache_expired(item) && cache_lock(item)) {
246 if (cache_expired(item)) { 246 if (cache_expired(item)) {
247 cgit_fill_cache(item, 1); 247 cgit_fill_cache(item, 1);
248 cache_unlock(item); 248 cache_unlock(item);
249 } else { 249 } else {
250 cache_cancel_lock(item); 250 cache_cancel_lock(item);
251 } 251 }
252 } 252 }
253} 253}
254 254
255static void cgit_print_cache(struct cacheitem *item) 255static void cgit_print_cache(struct cacheitem *item)
256{ 256{
257 static char buf[4096]; 257 static char buf[4096];
258 ssize_t i; 258 ssize_t i;
259 259
260 int fd = open(item->name, O_RDONLY); 260 int fd = open(item->name, O_RDONLY);
261 if (fd<0) 261 if (fd<0)
262 die("Unable to open cached file %s", item->name); 262 die("Unable to open cached file %s", item->name);
263 263
264 while((i=read(fd, buf, sizeof(buf))) > 0) 264 while((i=read(fd, buf, sizeof(buf))) > 0)
265 write(STDOUT_FILENO, buf, i); 265 write(STDOUT_FILENO, buf, i);
266 266
267 close(fd); 267 close(fd);
268} 268}
269 269
270static void cgit_parse_args(int argc, const char **argv) 270static void cgit_parse_args(int argc, const char **argv)
271{ 271{
272 int i; 272 int i;
273 273
274 for (i = 1; i < argc; i++) { 274 for (i = 1; i < argc; i++) {
275 if (!strncmp(argv[i], "--cache=", 8)) { 275 if (!strncmp(argv[i], "--cache=", 8)) {
276 ctx.cfg.cache_root = xstrdup(argv[i]+8); 276 ctx.cfg.cache_root = xstrdup(argv[i]+8);
277 } 277 }
278 if (!strcmp(argv[i], "--nocache")) { 278 if (!strcmp(argv[i], "--nocache")) {
279 ctx.cfg.nocache = 1; 279 ctx.cfg.nocache = 1;
280 } 280 }
281 if (!strncmp(argv[i], "--query=", 8)) { 281 if (!strncmp(argv[i], "--query=", 8)) {
282 ctx.qry.raw = xstrdup(argv[i]+8); 282 ctx.qry.raw = xstrdup(argv[i]+8);
283 } 283 }
284 if (!strncmp(argv[i], "--repo=", 7)) { 284 if (!strncmp(argv[i], "--repo=", 7)) {
285 ctx.qry.repo = xstrdup(argv[i]+7); 285 ctx.qry.repo = xstrdup(argv[i]+7);
286 } 286 }
287 if (!strncmp(argv[i], "--page=", 7)) { 287 if (!strncmp(argv[i], "--page=", 7)) {
288 ctx.qry.page = xstrdup(argv[i]+7); 288 ctx.qry.page = xstrdup(argv[i]+7);
289 } 289 }
290 if (!strncmp(argv[i], "--head=", 7)) { 290 if (!strncmp(argv[i], "--head=", 7)) {
291 ctx.qry.head = xstrdup(argv[i]+7); 291 ctx.qry.head = xstrdup(argv[i]+7);
292 ctx.qry.has_symref = 1; 292 ctx.qry.has_symref = 1;
293 } 293 }
294 if (!strncmp(argv[i], "--sha1=", 7)) { 294 if (!strncmp(argv[i], "--sha1=", 7)) {
295 ctx.qry.sha1 = xstrdup(argv[i]+7); 295 ctx.qry.sha1 = xstrdup(argv[i]+7);
296 ctx.qry.has_sha1 = 1; 296 ctx.qry.has_sha1 = 1;
297 } 297 }
298 if (!strncmp(argv[i], "--ofs=", 6)) { 298 if (!strncmp(argv[i], "--ofs=", 6)) {
299 ctx.qry.ofs = atoi(argv[i]+6); 299 ctx.qry.ofs = atoi(argv[i]+6);
300 } 300 }
301 } 301 }
302} 302}
303 303
304int main(int argc, const char **argv) 304int main(int argc, const char **argv)
305{ 305{
306 struct cacheitem item; 306 struct cacheitem item;
307 const char *cgit_config_env = getenv("CGIT_CONFIG"); 307 const char *cgit_config_env = getenv("CGIT_CONFIG");
308 308
309 cgit_prepare_context(&ctx); 309 cgit_prepare_context(&ctx);
310 item.st.st_mtime = time(NULL); 310 item.st.st_mtime = time(NULL);
311 cgit_repolist.length = 0; 311 cgit_repolist.length = 0;
312 cgit_repolist.count = 0; 312 cgit_repolist.count = 0;
313 cgit_repolist.repos = NULL; 313 cgit_repolist.repos = NULL;
314 314
315 cgit_read_config(cgit_config_env ? cgit_config_env : CGIT_CONFIG, 315 cgit_read_config(cgit_config_env ? cgit_config_env : CGIT_CONFIG,
316 cgit_global_config_cb); 316 cgit_global_config_cb);
317 if (getenv("SCRIPT_NAME")) 317 if (getenv("SCRIPT_NAME"))
318 ctx.cfg.script_name = xstrdup(getenv("SCRIPT_NAME")); 318 ctx.cfg.script_name = xstrdup(getenv("SCRIPT_NAME"));
319 if (getenv("QUERY_STRING")) 319 if (getenv("QUERY_STRING"))
320 ctx.qry.raw = xstrdup(getenv("QUERY_STRING")); 320 ctx.qry.raw = xstrdup(getenv("QUERY_STRING"));
321 cgit_parse_args(argc, argv); 321 cgit_parse_args(argc, argv);
322 cgit_parse_query(ctx.qry.raw, cgit_querystring_cb); 322 cgit_parse_query(ctx.qry.raw, cgit_querystring_cb);
323 if (!cgit_prepare_cache(&item)) 323 if (!cgit_prepare_cache(&item))
324 return 0; 324 return 0;
325 if (ctx.cfg.nocache) { 325 if (ctx.cfg.nocache) {
326 cgit_fill_cache(&item, 0); 326 cgit_fill_cache(&item, 0);
327 } else { 327 } else {
328 cgit_check_cache(&item); 328 cgit_check_cache(&item);
329 cgit_print_cache(&item); 329 cgit_print_cache(&item);
330 } 330 }
331 return 0; 331 return 0;
332} 332}
diff --git a/cgit.h b/cgit.h
index 8ab8e07..40e2d40 100644
--- a/cgit.h
+++ b/cgit.h
@@ -1,299 +1,299 @@
1#ifndef CGIT_H 1#ifndef CGIT_H
2#define CGIT_H 2#define CGIT_H
3 3
4 4
5#include <git-compat-util.h> 5#include <git-compat-util.h>
6#include <cache.h> 6#include <cache.h>
7#include <grep.h> 7#include <grep.h>
8#include <object.h> 8#include <object.h>
9#include <tree.h> 9#include <tree.h>
10#include <commit.h> 10#include <commit.h>
11#include <tag.h> 11#include <tag.h>
12#include <diff.h> 12#include <diff.h>
13#include <diffcore.h> 13#include <diffcore.h>
14#include <refs.h> 14#include <refs.h>
15#include <revision.h> 15#include <revision.h>
16#include <log-tree.h> 16#include <log-tree.h>
17#include <archive.h> 17#include <archive.h>
18#include <xdiff/xdiff.h> 18#include <xdiff/xdiff.h>
19#include <utf8.h> 19#include <utf8.h>
20 20
21 21
22/* 22/*
23 * The valid cgit repo-commands 23 * The valid cgit repo-commands
24 */ 24 */
25#define CMD_LOG 1 25#define CMD_LOG 1
26#define CMD_COMMIT 2 26#define CMD_COMMIT 2
27#define CMD_DIFF 3 27#define CMD_DIFF 3
28#define CMD_TREE 4 28#define CMD_TREE 4
29#define CMD_BLOB 5 29#define CMD_BLOB 5
30#define CMD_SNAPSHOT 6 30#define CMD_SNAPSHOT 6
31#define CMD_TAG 7 31#define CMD_TAG 7
32#define CMD_REFS 8 32#define CMD_REFS 8
33#define CMD_PATCH 9 33#define CMD_PATCH 9
34 34
35/* 35/*
36 * Dateformats used on misc. pages 36 * Dateformats used on misc. pages
37 */ 37 */
38#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S" 38#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S"
39#define FMT_SHORTDATE "%Y-%m-%d" 39#define FMT_SHORTDATE "%Y-%m-%d"
40 40
41 41
42/* 42/*
43 * Limits used for relative dates 43 * Limits used for relative dates
44 */ 44 */
45#define TM_MIN 60 45#define TM_MIN 60
46#define TM_HOUR (TM_MIN * 60) 46#define TM_HOUR (TM_MIN * 60)
47#define TM_DAY (TM_HOUR * 24) 47#define TM_DAY (TM_HOUR * 24)
48#define TM_WEEK (TM_DAY * 7) 48#define TM_WEEK (TM_DAY * 7)
49#define TM_YEAR (TM_DAY * 365) 49#define TM_YEAR (TM_DAY * 365)
50#define TM_MONTH (TM_YEAR / 12.0) 50#define TM_MONTH (TM_YEAR / 12.0)
51 51
52 52
53/* 53/*
54 * Default encoding 54 * Default encoding
55 */ 55 */
56#define PAGE_ENCODING "UTF-8" 56#define PAGE_ENCODING "UTF-8"
57 57
58typedef void (*configfn)(const char *name, const char *value); 58typedef void (*configfn)(const char *name, const char *value);
59typedef void (*filepair_fn)(struct diff_filepair *pair); 59typedef void (*filepair_fn)(struct diff_filepair *pair);
60typedef void (*linediff_fn)(char *line, int len); 60typedef void (*linediff_fn)(char *line, int len);
61 61
62struct cacheitem { 62struct cacheitem {
63 char *name; 63 char *name;
64 struct stat st; 64 struct stat st;
65 int ttl; 65 int ttl;
66 int fd; 66 int fd;
67}; 67};
68 68
69struct cgit_repo { 69struct cgit_repo {
70 char *url; 70 char *url;
71 char *name; 71 char *name;
72 char *path; 72 char *path;
73 char *desc; 73 char *desc;
74 char *owner; 74 char *owner;
75 char *defbranch; 75 char *defbranch;
76 char *group; 76 char *group;
77 char *module_link; 77 char *module_link;
78 char *readme; 78 char *readme;
79 char *clone_url; 79 char *clone_url;
80 int snapshots; 80 int snapshots;
81 int enable_log_filecount; 81 int enable_log_filecount;
82 int enable_log_linecount; 82 int enable_log_linecount;
83}; 83};
84 84
85struct cgit_repolist { 85struct cgit_repolist {
86 int length; 86 int length;
87 int count; 87 int count;
88 struct cgit_repo *repos; 88 struct cgit_repo *repos;
89}; 89};
90 90
91struct commitinfo { 91struct commitinfo {
92 struct commit *commit; 92 struct commit *commit;
93 char *author; 93 char *author;
94 char *author_email; 94 char *author_email;
95 unsigned long author_date; 95 unsigned long author_date;
96 char *committer; 96 char *committer;
97 char *committer_email; 97 char *committer_email;
98 unsigned long committer_date; 98 unsigned long committer_date;
99 char *subject; 99 char *subject;
100 char *msg; 100 char *msg;
101 char *msg_encoding; 101 char *msg_encoding;
102}; 102};
103 103
104struct taginfo { 104struct taginfo {
105 char *tagger; 105 char *tagger;
106 char *tagger_email; 106 char *tagger_email;
107 int tagger_date; 107 int tagger_date;
108 char *msg; 108 char *msg;
109}; 109};
110 110
111struct refinfo { 111struct refinfo {
112 const char *refname; 112 const char *refname;
113 struct object *object; 113 struct object *object;
114 union { 114 union {
115 struct taginfo *tag; 115 struct taginfo *tag;
116 struct commitinfo *commit; 116 struct commitinfo *commit;
117 }; 117 };
118}; 118};
119 119
120struct reflist { 120struct reflist {
121 struct refinfo **refs; 121 struct refinfo **refs;
122 int alloc; 122 int alloc;
123 int count; 123 int count;
124}; 124};
125 125
126struct cgit_query { 126struct cgit_query {
127 int has_symref; 127 int has_symref;
128 int has_sha1; 128 int has_sha1;
129 char *raw; 129 char *raw;
130 char *repo; 130 char *repo;
131 char *page; 131 char *page;
132 char *search; 132 char *search;
133 char *grep; 133 char *grep;
134 char *head; 134 char *head;
135 char *sha1; 135 char *sha1;
136 char *sha2; 136 char *sha2;
137 char *path; 137 char *path;
138 char *name; 138 char *name;
139 int ofs; 139 int ofs;
140}; 140};
141 141
142struct cgit_config { 142struct cgit_config {
143 char *agefile; 143 char *agefile;
144 char *cache_root; 144 char *cache_root;
145 char *clone_prefix; 145 char *clone_prefix;
146 char *css; 146 char *css;
147 char *index_header; 147 char *index_header;
148 char *index_info; 148 char *index_info;
149 char *logo; 149 char *logo;
150 char *logo_link; 150 char *logo_link;
151 char *module_link; 151 char *module_link;
152 char *repo_group; 152 char *repo_group;
153 char *robots; 153 char *robots;
154 char *root_title; 154 char *root_title;
155 char *script_name; 155 char *script_name;
156 char *virtual_root; 156 char *virtual_root;
157 int cache_dynamic_ttl; 157 int cache_dynamic_ttl;
158 int cache_max_create_time; 158 int cache_max_create_time;
159 int cache_repo_ttl; 159 int cache_repo_ttl;
160 int cache_root_ttl; 160 int cache_root_ttl;
161 int cache_static_ttl; 161 int cache_static_ttl;
162 int enable_index_links; 162 int enable_index_links;
163 int enable_log_filecount; 163 int enable_log_filecount;
164 int enable_log_linecount; 164 int enable_log_linecount;
165 int max_commit_count; 165 int max_commit_count;
166 int max_lock_attempts; 166 int max_lock_attempts;
167 int max_msg_len; 167 int max_msg_len;
168 int max_repodesc_len; 168 int max_repodesc_len;
169 int nocache; 169 int nocache;
170 int renamelimit; 170 int renamelimit;
171 int snapshots; 171 int snapshots;
172 int summary_branches; 172 int summary_branches;
173 int summary_log; 173 int summary_log;
174 int summary_tags; 174 int summary_tags;
175}; 175};
176 176
177struct cgit_page { 177struct cgit_page {
178 time_t modified; 178 time_t modified;
179 time_t expires; 179 time_t expires;
180 char *mimetype; 180 char *mimetype;
181 char *charset; 181 char *charset;
182 char *filename; 182 char *filename;
183 char *title; 183 char *title;
184}; 184};
185 185
186struct cgit_context { 186struct cgit_context {
187 struct cgit_query qry; 187 struct cgit_query qry;
188 struct cgit_config cfg; 188 struct cgit_config cfg;
189 struct cgit_repo *repo; 189 struct cgit_repo *repo;
190 struct cgit_page page; 190 struct cgit_page page;
191}; 191};
192 192
193extern const char *cgit_version; 193extern const char *cgit_version;
194 194
195extern struct cgit_repolist cgit_repolist; 195extern struct cgit_repolist cgit_repolist;
196extern struct cgit_context ctx; 196extern struct cgit_context ctx;
197extern int cgit_cmd; 197extern int cgit_cmd;
198 198
199extern void cgit_prepare_context(struct cgit_context *ctx); 199extern void cgit_prepare_context(struct cgit_context *ctx);
200extern int cgit_get_cmd_index(const char *cmd); 200extern int cgit_get_cmd_index(const char *cmd);
201extern struct cgit_repo *cgit_get_repoinfo(const char *url); 201extern struct cgit_repo *cgit_get_repoinfo(const char *url);
202extern void cgit_global_config_cb(const char *name, const char *value); 202extern void cgit_global_config_cb(const char *name, const char *value);
203extern void cgit_repo_config_cb(const char *name, const char *value); 203extern void cgit_repo_config_cb(const char *name, const char *value);
204extern void cgit_querystring_cb(const char *name, const char *value); 204extern void cgit_querystring_cb(const char *name, const char *value);
205 205
206extern int chk_zero(int result, char *msg); 206extern int chk_zero(int result, char *msg);
207extern int chk_positive(int result, char *msg); 207extern int chk_positive(int result, char *msg);
208extern int chk_non_negative(int result, char *msg); 208extern int chk_non_negative(int result, char *msg);
209 209
210extern int hextoint(char c); 210extern int hextoint(char c);
211extern char *trim_end(const char *str, char c); 211extern char *trim_end(const char *str, char c);
212extern char *strlpart(char *txt, int maxlen); 212extern char *strlpart(char *txt, int maxlen);
213extern char *strrpart(char *txt, int maxlen); 213extern char *strrpart(char *txt, int maxlen);
214 214
215extern void cgit_add_ref(struct reflist *list, struct refinfo *ref); 215extern void cgit_add_ref(struct reflist *list, struct refinfo *ref);
216extern int cgit_refs_cb(const char *refname, const unsigned char *sha1, 216extern int cgit_refs_cb(const char *refname, const unsigned char *sha1,
217 int flags, void *cb_data); 217 int flags, void *cb_data);
218 218
219extern void *cgit_free_commitinfo(struct commitinfo *info); 219extern void *cgit_free_commitinfo(struct commitinfo *info);
220 220
221extern int cgit_diff_files(const unsigned char *old_sha1, 221extern int cgit_diff_files(const unsigned char *old_sha1,
222 const unsigned char *new_sha1, 222 const unsigned char *new_sha1,
223 linediff_fn fn); 223 linediff_fn fn);
224 224
225extern void cgit_diff_tree(const unsigned char *old_sha1, 225extern void cgit_diff_tree(const unsigned char *old_sha1,
226 const unsigned char *new_sha1, 226 const unsigned char *new_sha1,
227 filepair_fn fn, const char *prefix); 227 filepair_fn fn, const char *prefix);
228 228
229extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); 229extern void cgit_diff_commit(struct commit *commit, filepair_fn fn);
230 230
231extern char *fmt(const char *format,...); 231extern char *fmt(const char *format,...);
232 232
233extern int cgit_read_config(const char *filename, configfn fn); 233extern int cgit_read_config(const char *filename, configfn fn);
234extern int cgit_parse_query(char *txt, configfn fn); 234extern int cgit_parse_query(char *txt, configfn fn);
235extern struct commitinfo *cgit_parse_commit(struct commit *commit); 235extern struct commitinfo *cgit_parse_commit(struct commit *commit);
236extern struct taginfo *cgit_parse_tag(struct tag *tag); 236extern struct taginfo *cgit_parse_tag(struct tag *tag);
237extern void cgit_parse_url(const char *url); 237extern void cgit_parse_url(const char *url);
238 238
239extern char *cache_safe_filename(const char *unsafe); 239extern char *cache_safe_filename(const char *unsafe);
240extern int cache_lock(struct cacheitem *item); 240extern int cache_lock(struct cacheitem *item);
241extern int cache_unlock(struct cacheitem *item); 241extern int cache_unlock(struct cacheitem *item);
242extern int cache_cancel_lock(struct cacheitem *item); 242extern int cache_cancel_lock(struct cacheitem *item);
243extern int cache_exist(struct cacheitem *item); 243extern int cache_exist(struct cacheitem *item);
244extern int cache_expired(struct cacheitem *item); 244extern int cache_expired(struct cacheitem *item);
245 245
246extern char *cgit_repourl(const char *reponame); 246extern char *cgit_repourl(const char *reponame);
247extern char *cgit_fileurl(const char *reponame, const char *pagename, 247extern char *cgit_fileurl(const char *reponame, const char *pagename,
248 const char *filename, const char *query); 248 const char *filename, const char *query);
249extern char *cgit_pageurl(const char *reponame, const char *pagename, 249extern char *cgit_pageurl(const char *reponame, const char *pagename,
250 const char *query); 250 const char *query);
251 251
252extern const char *cgit_repobasename(const char *reponame); 252extern const char *cgit_repobasename(const char *reponame);
253 253
254extern void cgit_tree_link(char *name, char *title, char *class, char *head, 254extern void cgit_tree_link(char *name, char *title, char *class, char *head,
255 char *rev, char *path); 255 char *rev, char *path);
256extern void cgit_log_link(char *name, char *title, char *class, char *head, 256extern void cgit_log_link(char *name, char *title, char *class, char *head,
257 char *rev, char *path, int ofs, char *grep, 257 char *rev, char *path, int ofs, char *grep,
258 char *pattern); 258 char *pattern);
259extern void cgit_commit_link(char *name, char *title, char *class, char *head, 259extern void cgit_commit_link(char *name, char *title, char *class, char *head,
260 char *rev); 260 char *rev);
261extern void cgit_refs_link(char *name, char *title, char *class, char *head, 261extern void cgit_refs_link(char *name, char *title, char *class, char *head,
262 char *rev, char *path); 262 char *rev, char *path);
263extern void cgit_snapshot_link(char *name, char *title, char *class, 263extern void cgit_snapshot_link(char *name, char *title, char *class,
264 char *head, char *rev, char *archivename); 264 char *head, char *rev, char *archivename);
265extern void cgit_diff_link(char *name, char *title, char *class, char *head, 265extern void cgit_diff_link(char *name, char *title, char *class, char *head,
266 char *new_rev, char *old_rev, char *path); 266 char *new_rev, char *old_rev, char *path);
267 267
268extern void cgit_object_link(struct object *obj); 268extern void cgit_object_link(struct object *obj);
269 269
270extern void cgit_print_error(char *msg); 270extern void cgit_print_error(char *msg);
271extern void cgit_print_date(time_t secs, char *format); 271extern void cgit_print_date(time_t secs, char *format);
272extern void cgit_print_age(time_t t, time_t max_relative, char *format); 272extern void cgit_print_age(time_t t, time_t max_relative, char *format);
273extern void cgit_print_http_headers(struct cgit_context *ctx); 273extern void cgit_print_http_headers(struct cgit_context *ctx);
274extern void cgit_print_docstart(struct cgit_context *ctx); 274extern void cgit_print_docstart(struct cgit_context *ctx);
275extern void cgit_print_docend(); 275extern void cgit_print_docend();
276extern void cgit_print_pageheader(struct cgit_context *ctx); 276extern void cgit_print_pageheader(struct cgit_context *ctx);
277extern void cgit_print_filemode(unsigned short mode); 277extern void cgit_print_filemode(unsigned short mode);
278extern void cgit_print_branches(int maxcount); 278extern void cgit_print_branches(int maxcount);
279extern void cgit_print_tags(int maxcount); 279extern void cgit_print_tags(int maxcount);
280 280
281extern void cgit_print_repolist(struct cacheitem *item); 281extern void cgit_print_repolist();
282extern void cgit_print_summary(); 282extern void cgit_print_summary();
283extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, 283extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep,
284 char *pattern, char *path, int pager); 284 char *pattern, char *path, int pager);
285extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path); 285extern void cgit_print_blob(const char *hex, char *path);
286extern void cgit_print_tree(const char *rev, char *path); 286extern void cgit_print_tree(const char *rev, char *path);
287extern void cgit_print_commit(char *hex); 287extern void cgit_print_commit(char *hex);
288extern void cgit_print_refs(); 288extern void cgit_print_refs();
289extern void cgit_print_tag(char *revname); 289extern void cgit_print_tag(char *revname);
290extern void cgit_print_diff(const char *new_hex, const char *old_hex, const char *prefix); 290extern void cgit_print_diff(const char *new_hex, const char *old_hex, const char *prefix);
291extern void cgit_print_patch(char *hex, struct cacheitem *item); 291extern void cgit_print_patch(char *hex);
292extern void cgit_print_snapshot(struct cacheitem *item, const char *head, 292extern void cgit_print_snapshot(const char *head, const char *hex,
293 const char *hex, const char *prefix, 293 const char *prefix, const char *filename,
294 const char *filename, int snapshot); 294 int snapshot);
295extern void cgit_print_snapshot_links(const char *repo, const char *head, 295extern void cgit_print_snapshot_links(const char *repo, const char *head,
296 const char *hex, int snapshots); 296 const char *hex, int snapshots);
297extern int cgit_parse_snapshots_mask(const char *str); 297extern int cgit_parse_snapshots_mask(const char *str);
298 298
299#endif /* CGIT_H */ 299#endif /* CGIT_H */
diff --git a/ui-blob.c b/ui-blob.c
index bd44574..3b29132 100644
--- a/ui-blob.c
+++ b/ui-blob.c
@@ -1,42 +1,42 @@
1/* ui-blob.c: show blob content 1/* ui-blob.c: show blob content
2 * 2 *
3 * Copyright (C) 2008 Lars Hjemli 3 * Copyright (C) 2008 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include "html.h" 10#include "html.h"
11 11
12void cgit_print_blob(struct cacheitem *item, const char *hex, char *path) 12void cgit_print_blob(const char *hex, char *path)
13{ 13{
14 14
15 unsigned char sha1[20]; 15 unsigned char sha1[20];
16 enum object_type type; 16 enum object_type type;
17 unsigned char *buf; 17 unsigned char *buf;
18 unsigned long size; 18 unsigned long size;
19 19
20 if (get_sha1_hex(hex, sha1)){ 20 if (get_sha1_hex(hex, sha1)){
21 cgit_print_error(fmt("Bad hex value: %s", hex)); 21 cgit_print_error(fmt("Bad hex value: %s", hex));
22 return; 22 return;
23 } 23 }
24 24
25 type = sha1_object_info(sha1, &size); 25 type = sha1_object_info(sha1, &size);
26 if (type == OBJ_BAD) { 26 if (type == OBJ_BAD) {
27 cgit_print_error(fmt("Bad object name: %s", hex)); 27 cgit_print_error(fmt("Bad object name: %s", hex));
28 return; 28 return;
29 } 29 }
30 30
31 buf = read_sha1_file(sha1, &type, &size); 31 buf = read_sha1_file(sha1, &type, &size);
32 if (!buf) { 32 if (!buf) {
33 cgit_print_error(fmt("Error reading object %s", hex)); 33 cgit_print_error(fmt("Error reading object %s", hex));
34 return; 34 return;
35 } 35 }
36 36
37 buf[size] = '\0'; 37 buf[size] = '\0';
38 ctx.page.mimetype = "text/plain"; 38 ctx.page.mimetype = "text/plain";
39 ctx.page.filename = path; 39 ctx.page.filename = path;
40 cgit_print_http_headers(&ctx); 40 cgit_print_http_headers(&ctx);
41 write(htmlfd, buf, size); 41 write(htmlfd, buf, size);
42} 42}
diff --git a/ui-patch.c b/ui-patch.c
index a77f3f6..68ebb15 100644
--- a/ui-patch.c
+++ b/ui-patch.c
@@ -1,113 +1,113 @@
1/* ui-patch.c: generate patch view 1/* ui-patch.c: generate patch view
2 * 2 *
3 * Copyright (C) 2007 Lars Hjemli 3 * Copyright (C) 2007 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include "html.h" 10#include "html.h"
11 11
12static void print_line(char *line, int len) 12static void print_line(char *line, int len)
13{ 13{
14 char c = line[len-1]; 14 char c = line[len-1];
15 15
16 line[len-1] = '\0'; 16 line[len-1] = '\0';
17 htmlf("%s\n", line); 17 htmlf("%s\n", line);
18 line[len-1] = c; 18 line[len-1] = c;
19} 19}
20 20
21static void header(unsigned char *sha1, char *path1, int mode1, 21static void header(unsigned char *sha1, char *path1, int mode1,
22 unsigned char *sha2, char *path2, int mode2) 22 unsigned char *sha2, char *path2, int mode2)
23{ 23{
24 char *abbrev1, *abbrev2; 24 char *abbrev1, *abbrev2;
25 int subproject; 25 int subproject;
26 26
27 subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); 27 subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2));
28 htmlf("diff --git a/%s b/%s\n", path1, path2); 28 htmlf("diff --git a/%s b/%s\n", path1, path2);
29 29
30 if (is_null_sha1(sha1)) 30 if (is_null_sha1(sha1))
31 path1 = "dev/null"; 31 path1 = "dev/null";
32 if (is_null_sha1(sha2)) 32 if (is_null_sha1(sha2))
33 path2 = "dev/null"; 33 path2 = "dev/null";
34 34
35 if (mode1 == 0) 35 if (mode1 == 0)
36 htmlf("new file mode %.6o\n", mode2); 36 htmlf("new file mode %.6o\n", mode2);
37 37
38 if (mode2 == 0) 38 if (mode2 == 0)
39 htmlf("deleted file mode %.6o\n", mode1); 39 htmlf("deleted file mode %.6o\n", mode1);
40 40
41 if (!subproject) { 41 if (!subproject) {
42 abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); 42 abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV));
43 abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); 43 abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV));
44 htmlf("index %s..%s", abbrev1, abbrev2); 44 htmlf("index %s..%s", abbrev1, abbrev2);
45 free(abbrev1); 45 free(abbrev1);
46 free(abbrev2); 46 free(abbrev2);
47 if (mode1 != 0 && mode2 != 0) { 47 if (mode1 != 0 && mode2 != 0) {
48 htmlf(" %.6o", mode1); 48 htmlf(" %.6o", mode1);
49 if (mode2 != mode1) 49 if (mode2 != mode1)
50 htmlf("..%.6o", mode2); 50 htmlf("..%.6o", mode2);
51 } 51 }
52 htmlf("\n--- a/%s\n", path1); 52 htmlf("\n--- a/%s\n", path1);
53 htmlf("+++ b/%s\n", path2); 53 htmlf("+++ b/%s\n", path2);
54 } 54 }
55} 55}
56 56
57static void filepair_cb(struct diff_filepair *pair) 57static void filepair_cb(struct diff_filepair *pair)
58{ 58{
59 header(pair->one->sha1, pair->one->path, pair->one->mode, 59 header(pair->one->sha1, pair->one->path, pair->one->mode,
60 pair->two->sha1, pair->two->path, pair->two->mode); 60 pair->two->sha1, pair->two->path, pair->two->mode);
61 if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { 61 if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) {
62 if (S_ISGITLINK(pair->one->mode)) 62 if (S_ISGITLINK(pair->one->mode))
63 print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); 63 print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52);
64 if (S_ISGITLINK(pair->two->mode)) 64 if (S_ISGITLINK(pair->two->mode))
65 print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); 65 print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52);
66 return; 66 return;
67 } 67 }
68 if (cgit_diff_files(pair->one->sha1, pair->two->sha1, print_line)) 68 if (cgit_diff_files(pair->one->sha1, pair->two->sha1, print_line))
69 html("Error running diff"); 69 html("Error running diff");
70} 70}
71 71
72void cgit_print_patch(char *hex, struct cacheitem *item) 72void cgit_print_patch(char *hex)
73{ 73{
74 struct commit *commit; 74 struct commit *commit;
75 struct commitinfo *info; 75 struct commitinfo *info;
76 unsigned char sha1[20], old_sha1[20]; 76 unsigned char sha1[20], old_sha1[20];
77 char *patchname; 77 char *patchname;
78 78
79 if (!hex) 79 if (!hex)
80 hex = ctx.qry.head; 80 hex = ctx.qry.head;
81 81
82 if (get_sha1(hex, sha1)) { 82 if (get_sha1(hex, sha1)) {
83 cgit_print_error(fmt("Bad object id: %s", hex)); 83 cgit_print_error(fmt("Bad object id: %s", hex));
84 return; 84 return;
85 } 85 }
86 commit = lookup_commit_reference(sha1); 86 commit = lookup_commit_reference(sha1);
87 if (!commit) { 87 if (!commit) {
88 cgit_print_error(fmt("Bad commit reference: %s", hex)); 88 cgit_print_error(fmt("Bad commit reference: %s", hex));
89 return; 89 return;
90 } 90 }
91 info = cgit_parse_commit(commit); 91 info = cgit_parse_commit(commit);
92 hashcpy(old_sha1, commit->parents->item->object.sha1); 92 hashcpy(old_sha1, commit->parents->item->object.sha1);
93 93
94 patchname = fmt("%s.patch", sha1_to_hex(sha1)); 94 patchname = fmt("%s.patch", sha1_to_hex(sha1));
95 ctx.page.mimetype = "text/plain"; 95 ctx.page.mimetype = "text/plain";
96 ctx.page.filename = patchname; 96 ctx.page.filename = patchname;
97 cgit_print_http_headers(&ctx); 97 cgit_print_http_headers(&ctx);
98 htmlf("From %s Mon Sep 17 00:00:00 2001\n", sha1_to_hex(sha1)); 98 htmlf("From %s Mon Sep 17 00:00:00 2001\n", sha1_to_hex(sha1));
99 htmlf("From: %s%s\n", info->author, info->author_email); 99 htmlf("From: %s%s\n", info->author, info->author_email);
100 html("Date: "); 100 html("Date: ");
101 cgit_print_date(info->author_date, "%a, %d %b %Y %H:%M:%S %z%n"); 101 cgit_print_date(info->author_date, "%a, %d %b %Y %H:%M:%S %z%n");
102 htmlf("Subject: %s\n\n", info->subject); 102 htmlf("Subject: %s\n\n", info->subject);
103 if (info->msg && *info->msg) { 103 if (info->msg && *info->msg) {
104 htmlf("%s", info->msg); 104 htmlf("%s", info->msg);
105 if (info->msg[strlen(info->msg) - 1] != '\n') 105 if (info->msg[strlen(info->msg) - 1] != '\n')
106 html("\n"); 106 html("\n");
107 } 107 }
108 html("---\n"); 108 html("---\n");
109 cgit_diff_tree(old_sha1, sha1, filepair_cb, NULL); 109 cgit_diff_tree(old_sha1, sha1, filepair_cb, NULL);
110 html("--\n"); 110 html("--\n");
111 htmlf("cgit %s\n", CGIT_VERSION); 111 htmlf("cgit %s\n", CGIT_VERSION);
112 cgit_free_commitinfo(info); 112 cgit_free_commitinfo(info);
113} 113}
diff --git a/ui-repolist.c b/ui-repolist.c
index e663585..ad9b1bc 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -1,113 +1,113 @@
1/* ui-repolist.c: functions for generating the repolist page 1/* ui-repolist.c: functions for generating the repolist page
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include <time.h> 9#include <time.h>
10 10
11#include "cgit.h" 11#include "cgit.h"
12#include "html.h" 12#include "html.h"
13 13
14time_t read_agefile(char *path) 14time_t read_agefile(char *path)
15{ 15{
16 FILE *f; 16 FILE *f;
17 static char buf[64], buf2[64]; 17 static char buf[64], buf2[64];
18 18
19 if (!(f = fopen(path, "r"))) 19 if (!(f = fopen(path, "r")))
20 return -1; 20 return -1;
21 fgets(buf, sizeof(buf), f); 21 fgets(buf, sizeof(buf), f);
22 fclose(f); 22 fclose(f);
23 if (parse_date(buf, buf2, sizeof(buf2))) 23 if (parse_date(buf, buf2, sizeof(buf2)))
24 return strtoul(buf2, NULL, 10); 24 return strtoul(buf2, NULL, 10);
25 else 25 else
26 return 0; 26 return 0;
27} 27}
28 28
29static void print_modtime(struct cgit_repo *repo) 29static void print_modtime(struct cgit_repo *repo)
30{ 30{
31 char *path; 31 char *path;
32 struct stat s; 32 struct stat s;
33 33
34 path = fmt("%s/%s", repo->path, ctx.cfg.agefile); 34 path = fmt("%s/%s", repo->path, ctx.cfg.agefile);
35 if (stat(path, &s) == 0) { 35 if (stat(path, &s) == 0) {
36 cgit_print_age(read_agefile(path), -1, NULL); 36 cgit_print_age(read_agefile(path), -1, NULL);
37 return; 37 return;
38 } 38 }
39 39
40 path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); 40 path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch);
41 if (stat(path, &s) != 0) 41 if (stat(path, &s) != 0)
42 return; 42 return;
43 cgit_print_age(s.st_mtime, -1, NULL); 43 cgit_print_age(s.st_mtime, -1, NULL);
44} 44}
45 45
46void cgit_print_repolist(struct cacheitem *item) 46void cgit_print_repolist()
47{ 47{
48 int i, columns = 4; 48 int i, columns = 4;
49 char *last_group = NULL; 49 char *last_group = NULL;
50 50
51 if (ctx.cfg.enable_index_links) 51 if (ctx.cfg.enable_index_links)
52 columns++; 52 columns++;
53 53
54 ctx.page.title = ctx.cfg.root_title; 54 ctx.page.title = ctx.cfg.root_title;
55 cgit_print_http_headers(&ctx); 55 cgit_print_http_headers(&ctx);
56 cgit_print_docstart(&ctx); 56 cgit_print_docstart(&ctx);
57 cgit_print_pageheader(&ctx); 57 cgit_print_pageheader(&ctx);
58 58
59 html("<table summary='repository list' class='list nowrap'>"); 59 html("<table summary='repository list' class='list nowrap'>");
60 if (ctx.cfg.index_header) { 60 if (ctx.cfg.index_header) {
61 htmlf("<tr class='nohover'><td colspan='%d' class='include-block'>", 61 htmlf("<tr class='nohover'><td colspan='%d' class='include-block'>",
62 columns); 62 columns);
63 html_include(ctx.cfg.index_header); 63 html_include(ctx.cfg.index_header);
64 html("</td></tr>"); 64 html("</td></tr>");
65 } 65 }
66 html("<tr class='nohover'>" 66 html("<tr class='nohover'>"
67 "<th class='left'>Name</th>" 67 "<th class='left'>Name</th>"
68 "<th class='left'>Description</th>" 68 "<th class='left'>Description</th>"
69 "<th class='left'>Owner</th>" 69 "<th class='left'>Owner</th>"
70 "<th class='left'>Idle</th>"); 70 "<th class='left'>Idle</th>");
71 if (ctx.cfg.enable_index_links) 71 if (ctx.cfg.enable_index_links)
72 html("<th>Links</th>"); 72 html("<th>Links</th>");
73 html("</tr>\n"); 73 html("</tr>\n");
74 74
75 for (i=0; i<cgit_repolist.count; i++) { 75 for (i=0; i<cgit_repolist.count; i++) {
76 ctx.repo = &cgit_repolist.repos[i]; 76 ctx.repo = &cgit_repolist.repos[i];
77 if ((last_group == NULL && ctx.repo->group != NULL) || 77 if ((last_group == NULL && ctx.repo->group != NULL) ||
78 (last_group != NULL && ctx.repo->group == NULL) || 78 (last_group != NULL && ctx.repo->group == NULL) ||
79 (last_group != NULL && ctx.repo->group != NULL && 79 (last_group != NULL && ctx.repo->group != NULL &&
80 strcmp(ctx.repo->group, last_group))) { 80 strcmp(ctx.repo->group, last_group))) {
81 htmlf("<tr class='nohover'><td colspan='%d' class='repogroup'>", 81 htmlf("<tr class='nohover'><td colspan='%d' class='repogroup'>",
82 columns); 82 columns);
83 html_txt(ctx.repo->group); 83 html_txt(ctx.repo->group);
84 html("</td></tr>"); 84 html("</td></tr>");
85 last_group = ctx.repo->group; 85 last_group = ctx.repo->group;
86 } 86 }
87 htmlf("<tr><td class='%s'>", 87 htmlf("<tr><td class='%s'>",
88 ctx.repo->group ? "sublevel-repo" : "toplevel-repo"); 88 ctx.repo->group ? "sublevel-repo" : "toplevel-repo");
89 html_link_open(cgit_repourl(ctx.repo->url), NULL, NULL); 89 html_link_open(cgit_repourl(ctx.repo->url), NULL, NULL);
90 html_txt(ctx.repo->name); 90 html_txt(ctx.repo->name);
91 html_link_close(); 91 html_link_close();
92 html("</td><td>"); 92 html("</td><td>");
93 html_ntxt(ctx.cfg.max_repodesc_len, ctx.repo->desc); 93 html_ntxt(ctx.cfg.max_repodesc_len, ctx.repo->desc);
94 html("</td><td>"); 94 html("</td><td>");
95 html_txt(ctx.repo->owner); 95 html_txt(ctx.repo->owner);
96 html("</td><td>"); 96 html("</td><td>");
97 print_modtime(ctx.repo); 97 print_modtime(ctx.repo);
98 html("</td>"); 98 html("</td>");
99 if (ctx.cfg.enable_index_links) { 99 if (ctx.cfg.enable_index_links) {
100 html("<td>"); 100 html("<td>");
101 html_link_open(cgit_repourl(ctx.repo->url), 101 html_link_open(cgit_repourl(ctx.repo->url),
102 NULL, "button"); 102 NULL, "button");
103 html("summary</a>"); 103 html("summary</a>");
104 cgit_log_link("log", NULL, "button", NULL, NULL, NULL, 104 cgit_log_link("log", NULL, "button", NULL, NULL, NULL,
105 0, NULL, NULL); 105 0, NULL, NULL);
106 cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL); 106 cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL);
107 html("</td>"); 107 html("</td>");
108 } 108 }
109 html("</tr>\n"); 109 html("</tr>\n");
110 } 110 }
111 html("</table>"); 111 html("</table>");
112 cgit_print_docend(); 112 cgit_print_docend();
113} 113}
diff --git a/ui-snapshot.c b/ui-snapshot.c
index 4449803..c741469 100644
--- a/ui-snapshot.c
+++ b/ui-snapshot.c
@@ -1,160 +1,159 @@
1/* ui-snapshot.c: generate snapshot of a commit 1/* ui-snapshot.c: generate snapshot of a commit
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * 4 *
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include "html.h" 10#include "html.h"
11 11
12static int write_compressed_tar_archive(struct archiver_args *args,const char *filter) 12static int write_compressed_tar_archive(struct archiver_args *args,const char *filter)
13{ 13{
14 int rw[2]; 14 int rw[2];
15 pid_t gzpid; 15 pid_t gzpid;
16 int stdout2; 16 int stdout2;
17 int status; 17 int status;
18 int rv; 18 int rv;
19 19
20 stdout2 = chk_non_negative(dup(STDIN_FILENO), "Preserving STDOUT before compressing"); 20 stdout2 = chk_non_negative(dup(STDIN_FILENO), "Preserving STDOUT before compressing");
21 chk_zero(pipe(rw), "Opening pipe from compressor subprocess"); 21 chk_zero(pipe(rw), "Opening pipe from compressor subprocess");
22 gzpid = chk_non_negative(fork(), "Forking compressor subprocess"); 22 gzpid = chk_non_negative(fork(), "Forking compressor subprocess");
23 if(gzpid==0) { 23 if(gzpid==0) {
24 /* child */ 24 /* child */
25 chk_zero(close(rw[1]), "Closing write end of pipe in child"); 25 chk_zero(close(rw[1]), "Closing write end of pipe in child");
26 chk_zero(close(STDIN_FILENO), "Closing STDIN"); 26 chk_zero(close(STDIN_FILENO), "Closing STDIN");
27 chk_non_negative(dup2(rw[0],STDIN_FILENO), "Redirecting compressor input to stdin"); 27 chk_non_negative(dup2(rw[0],STDIN_FILENO), "Redirecting compressor input to stdin");
28 execlp(filter,filter,NULL); 28 execlp(filter,filter,NULL);
29 _exit(-1); 29 _exit(-1);
30 } 30 }
31 /* parent */ 31 /* parent */
32 chk_zero(close(rw[0]), "Closing read end of pipe"); 32 chk_zero(close(rw[0]), "Closing read end of pipe");
33 chk_non_negative(dup2(rw[1],STDOUT_FILENO), "Redirecting output to compressor"); 33 chk_non_negative(dup2(rw[1],STDOUT_FILENO), "Redirecting output to compressor");
34 34
35 rv = write_tar_archive(args); 35 rv = write_tar_archive(args);
36 36
37 chk_zero(close(STDOUT_FILENO), "Closing STDOUT redirected to compressor"); 37 chk_zero(close(STDOUT_FILENO), "Closing STDOUT redirected to compressor");
38 chk_non_negative(dup2(stdout2,STDOUT_FILENO), "Restoring uncompressed STDOUT"); 38 chk_non_negative(dup2(stdout2,STDOUT_FILENO), "Restoring uncompressed STDOUT");
39 chk_zero(close(stdout2), "Closing uncompressed STDOUT"); 39 chk_zero(close(stdout2), "Closing uncompressed STDOUT");
40 chk_zero(close(rw[1]), "Closing write end of pipe in parent"); 40 chk_zero(close(rw[1]), "Closing write end of pipe in parent");
41 chk_positive(waitpid(gzpid,&status,0), "Waiting on compressor process"); 41 chk_positive(waitpid(gzpid,&status,0), "Waiting on compressor process");
42 if(! ( WIFEXITED(status) && WEXITSTATUS(status)==0 ) ) 42 if(! ( WIFEXITED(status) && WEXITSTATUS(status)==0 ) )
43 cgit_print_error("Failed to compress archive"); 43 cgit_print_error("Failed to compress archive");
44 44
45 return rv; 45 return rv;
46} 46}
47 47
48static int write_tar_gzip_archive(struct archiver_args *args) 48static int write_tar_gzip_archive(struct archiver_args *args)
49{ 49{
50 return write_compressed_tar_archive(args,"gzip"); 50 return write_compressed_tar_archive(args,"gzip");
51} 51}
52 52
53static int write_tar_bzip2_archive(struct archiver_args *args) 53static int write_tar_bzip2_archive(struct archiver_args *args)
54{ 54{
55 return write_compressed_tar_archive(args,"bzip2"); 55 return write_compressed_tar_archive(args,"bzip2");
56} 56}
57 57
58static const struct snapshot_archive_t { 58static const struct snapshot_archive_t {
59 const char *suffix; 59 const char *suffix;
60 const char *mimetype; 60 const char *mimetype;
61 write_archive_fn_t write_func; 61 write_archive_fn_t write_func;
62 int bit; 62 int bit;
63 }snapshot_archives[] = { 63 }snapshot_archives[] = {
64 { ".zip", "application/x-zip", write_zip_archive, 0x1 }, 64 { ".zip", "application/x-zip", write_zip_archive, 0x1 },
65 { ".tar.gz", "application/x-tar", write_tar_gzip_archive, 0x2 }, 65 { ".tar.gz", "application/x-tar", write_tar_gzip_archive, 0x2 },
66 { ".tar.bz2", "application/x-tar", write_tar_bzip2_archive, 0x4 }, 66 { ".tar.bz2", "application/x-tar", write_tar_bzip2_archive, 0x4 },
67 { ".tar", "application/x-tar", write_tar_archive, 0x8 } 67 { ".tar", "application/x-tar", write_tar_archive, 0x8 }
68}; 68};
69 69
70#define snapshot_archives_len (sizeof(snapshot_archives) / sizeof(*snapshot_archives)) 70#define snapshot_archives_len (sizeof(snapshot_archives) / sizeof(*snapshot_archives))
71 71
72void cgit_print_snapshot(struct cacheitem *item, const char *head, 72void cgit_print_snapshot(const char *head, const char *hex, const char *prefix,
73 const char *hex, const char *prefix,
74 const char *filename, int snapshots) 73 const char *filename, int snapshots)
75{ 74{
76 const struct snapshot_archive_t* sat; 75 const struct snapshot_archive_t* sat;
77 struct archiver_args args; 76 struct archiver_args args;
78 struct commit *commit; 77 struct commit *commit;
79 unsigned char sha1[20]; 78 unsigned char sha1[20];
80 int f, sl, fnl = strlen(filename); 79 int f, sl, fnl = strlen(filename);
81 80
82 for(f=0; f<snapshot_archives_len; f++) { 81 for(f=0; f<snapshot_archives_len; f++) {
83 sat = &snapshot_archives[f]; 82 sat = &snapshot_archives[f];
84 if(!(snapshots & sat->bit)) 83 if(!(snapshots & sat->bit))
85 continue; 84 continue;
86 sl = strlen(sat->suffix); 85 sl = strlen(sat->suffix);
87 if(fnl<sl || strcmp(&filename[fnl-sl],sat->suffix)) 86 if(fnl<sl || strcmp(&filename[fnl-sl],sat->suffix))
88 continue; 87 continue;
89 if (!hex) 88 if (!hex)
90 hex = head; 89 hex = head;
91 if(get_sha1(hex, sha1)) { 90 if(get_sha1(hex, sha1)) {
92 cgit_print_error(fmt("Bad object id: %s", hex)); 91 cgit_print_error(fmt("Bad object id: %s", hex));
93 return; 92 return;
94 } 93 }
95 commit = lookup_commit_reference(sha1); 94 commit = lookup_commit_reference(sha1);
96 if(!commit) { 95 if(!commit) {
97 cgit_print_error(fmt("Not a commit reference: %s", hex)); 96 cgit_print_error(fmt("Not a commit reference: %s", hex));
98 return;; 97 return;;
99 } 98 }
100 memset(&args,0,sizeof(args)); 99 memset(&args,0,sizeof(args));
101 args.base = fmt("%s/", prefix); 100 args.base = fmt("%s/", prefix);
102 args.tree = commit->tree; 101 args.tree = commit->tree;
103 args.time = commit->date; 102 args.time = commit->date;
104 ctx.page.mimetype = xstrdup(sat->mimetype); 103 ctx.page.mimetype = xstrdup(sat->mimetype);
105 ctx.page.filename = xstrdup(filename); 104 ctx.page.filename = xstrdup(filename);
106 cgit_print_http_headers(&ctx); 105 cgit_print_http_headers(&ctx);
107 (*sat->write_func)(&args); 106 (*sat->write_func)(&args);
108 return; 107 return;
109 } 108 }
110 cgit_print_error(fmt("Unsupported snapshot format: %s", filename)); 109 cgit_print_error(fmt("Unsupported snapshot format: %s", filename));
111} 110}
112 111
113void cgit_print_snapshot_links(const char *repo, const char *head, 112void cgit_print_snapshot_links(const char *repo, const char *head,
114 const char *hex, int snapshots) 113 const char *hex, int snapshots)
115{ 114{
116 const struct snapshot_archive_t* sat; 115 const struct snapshot_archive_t* sat;
117 char *filename; 116 char *filename;
118 int f; 117 int f;
119 118
120 for(f=0; f<snapshot_archives_len; f++) { 119 for(f=0; f<snapshot_archives_len; f++) {
121 sat = &snapshot_archives[f]; 120 sat = &snapshot_archives[f];
122 if(!(snapshots & sat->bit)) 121 if(!(snapshots & sat->bit))
123 continue; 122 continue;
124 filename = fmt("%s-%s%s", cgit_repobasename(repo), hex, 123 filename = fmt("%s-%s%s", cgit_repobasename(repo), hex,
125 sat->suffix); 124 sat->suffix);
126 cgit_snapshot_link(filename, NULL, NULL, (char *)head, 125 cgit_snapshot_link(filename, NULL, NULL, (char *)head,
127 (char *)hex, filename); 126 (char *)hex, filename);
128 html("<br/>"); 127 html("<br/>");
129 } 128 }
130} 129}
131 130
132int cgit_parse_snapshots_mask(const char *str) 131int cgit_parse_snapshots_mask(const char *str)
133{ 132{
134 const struct snapshot_archive_t* sat; 133 const struct snapshot_archive_t* sat;
135 static const char *delim = " \t,:/|;"; 134 static const char *delim = " \t,:/|;";
136 int f, tl, sl, rv = 0; 135 int f, tl, sl, rv = 0;
137 136
138 /* favor legacy setting */ 137 /* favor legacy setting */
139 if(atoi(str)) 138 if(atoi(str))
140 return 1; 139 return 1;
141 for(;;) { 140 for(;;) {
142 str += strspn(str,delim); 141 str += strspn(str,delim);
143 tl = strcspn(str,delim); 142 tl = strcspn(str,delim);
144 if(!tl) 143 if(!tl)
145 break; 144 break;
146 for(f=0; f<snapshot_archives_len; f++) { 145 for(f=0; f<snapshot_archives_len; f++) {
147 sat = &snapshot_archives[f]; 146 sat = &snapshot_archives[f];
148 sl = strlen(sat->suffix); 147 sl = strlen(sat->suffix);
149 if((tl == sl && !strncmp(sat->suffix, str, tl)) || 148 if((tl == sl && !strncmp(sat->suffix, str, tl)) ||
150 (tl == sl-1 && !strncmp(sat->suffix+1, str, tl-1))) { 149 (tl == sl-1 && !strncmp(sat->suffix+1, str, tl-1))) {
151 rv |= sat->bit; 150 rv |= sat->bit;
152 break; 151 break;
153 } 152 }
154 } 153 }
155 str += tl; 154 str += tl;
156 } 155 }
157 return rv; 156 return rv;
158} 157}
159 158
160/* vim:set sw=8: */ 159/* vim:set sw=8: */