summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2008-04-08 19:27:12 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2008-04-08 19:27:12 (UTC)
commitc6f747649ace1a92ed5dfaae9cc1ea3affe0bf51 (patch) (unidiff)
treec2d8ccd19974b6dfe32c5d3bffcfdf22dd526ae1
parente87e89633383b8b75c68c98be3e0c14212109de2 (diff)
downloadcgit-c6f747649ace1a92ed5dfaae9cc1ea3affe0bf51.zip
cgit-c6f747649ace1a92ed5dfaae9cc1ea3affe0bf51.tar.gz
cgit-c6f747649ace1a92ed5dfaae9cc1ea3affe0bf51.tar.bz2
Reset ctx.repo to NULL when the config parser is finished
This global variable is used by the config parsing callback to keep track of the currently configured repository. If it is not reset to NULL when the config parser is finished, and neither `url` or `r` is specified on the querystring, cgit will wrongly consider the last configured repo as selected. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/cgit.c b/cgit.c
index 763242a..6ec763f 100644
--- a/cgit.c
+++ b/cgit.c
@@ -1,458 +1,459 @@
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 "cache.h" 10#include "cache.h"
11#include "cmd.h" 11#include "cmd.h"
12#include "configfile.h" 12#include "configfile.h"
13#include "html.h" 13#include "html.h"
14#include "ui-shared.h" 14#include "ui-shared.h"
15 15
16const char *cgit_version = CGIT_VERSION; 16const char *cgit_version = CGIT_VERSION;
17 17
18void config_cb(const char *name, const char *value) 18void config_cb(const char *name, const char *value)
19{ 19{
20 if (!strcmp(name, "root-title")) 20 if (!strcmp(name, "root-title"))
21 ctx.cfg.root_title = xstrdup(value); 21 ctx.cfg.root_title = xstrdup(value);
22 else if (!strcmp(name, "css")) 22 else if (!strcmp(name, "css"))
23 ctx.cfg.css = xstrdup(value); 23 ctx.cfg.css = xstrdup(value);
24 else if (!strcmp(name, "logo")) 24 else if (!strcmp(name, "logo"))
25 ctx.cfg.logo = xstrdup(value); 25 ctx.cfg.logo = xstrdup(value);
26 else if (!strcmp(name, "index-header")) 26 else if (!strcmp(name, "index-header"))
27 ctx.cfg.index_header = xstrdup(value); 27 ctx.cfg.index_header = xstrdup(value);
28 else if (!strcmp(name, "index-info")) 28 else if (!strcmp(name, "index-info"))
29 ctx.cfg.index_info = xstrdup(value); 29 ctx.cfg.index_info = xstrdup(value);
30 else if (!strcmp(name, "logo-link")) 30 else if (!strcmp(name, "logo-link"))
31 ctx.cfg.logo_link = xstrdup(value); 31 ctx.cfg.logo_link = xstrdup(value);
32 else if (!strcmp(name, "module-link")) 32 else if (!strcmp(name, "module-link"))
33 ctx.cfg.module_link = xstrdup(value); 33 ctx.cfg.module_link = xstrdup(value);
34 else if (!strcmp(name, "virtual-root")) { 34 else if (!strcmp(name, "virtual-root")) {
35 ctx.cfg.virtual_root = trim_end(value, '/'); 35 ctx.cfg.virtual_root = trim_end(value, '/');
36 if (!ctx.cfg.virtual_root && (!strcmp(value, "/"))) 36 if (!ctx.cfg.virtual_root && (!strcmp(value, "/")))
37 ctx.cfg.virtual_root = ""; 37 ctx.cfg.virtual_root = "";
38 } else if (!strcmp(name, "nocache")) 38 } else if (!strcmp(name, "nocache"))
39 ctx.cfg.nocache = atoi(value); 39 ctx.cfg.nocache = atoi(value);
40 else if (!strcmp(name, "snapshots")) 40 else if (!strcmp(name, "snapshots"))
41 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); 41 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);
42 else if (!strcmp(name, "enable-index-links")) 42 else if (!strcmp(name, "enable-index-links"))
43 ctx.cfg.enable_index_links = atoi(value); 43 ctx.cfg.enable_index_links = atoi(value);
44 else if (!strcmp(name, "enable-log-filecount")) 44 else if (!strcmp(name, "enable-log-filecount"))
45 ctx.cfg.enable_log_filecount = atoi(value); 45 ctx.cfg.enable_log_filecount = atoi(value);
46 else if (!strcmp(name, "enable-log-linecount")) 46 else if (!strcmp(name, "enable-log-linecount"))
47 ctx.cfg.enable_log_linecount = atoi(value); 47 ctx.cfg.enable_log_linecount = atoi(value);
48 else if (!strcmp(name, "cache-root")) 48 else if (!strcmp(name, "cache-root"))
49 ctx.cfg.cache_root = xstrdup(value); 49 ctx.cfg.cache_root = xstrdup(value);
50 else if (!strcmp(name, "cache-root-ttl")) 50 else if (!strcmp(name, "cache-root-ttl"))
51 ctx.cfg.cache_root_ttl = atoi(value); 51 ctx.cfg.cache_root_ttl = atoi(value);
52 else if (!strcmp(name, "cache-repo-ttl")) 52 else if (!strcmp(name, "cache-repo-ttl"))
53 ctx.cfg.cache_repo_ttl = atoi(value); 53 ctx.cfg.cache_repo_ttl = atoi(value);
54 else if (!strcmp(name, "cache-static-ttl")) 54 else if (!strcmp(name, "cache-static-ttl"))
55 ctx.cfg.cache_static_ttl = atoi(value); 55 ctx.cfg.cache_static_ttl = atoi(value);
56 else if (!strcmp(name, "cache-dynamic-ttl")) 56 else if (!strcmp(name, "cache-dynamic-ttl"))
57 ctx.cfg.cache_dynamic_ttl = atoi(value); 57 ctx.cfg.cache_dynamic_ttl = atoi(value);
58 else if (!strcmp(name, "max-message-length")) 58 else if (!strcmp(name, "max-message-length"))
59 ctx.cfg.max_msg_len = atoi(value); 59 ctx.cfg.max_msg_len = atoi(value);
60 else if (!strcmp(name, "max-repodesc-length")) 60 else if (!strcmp(name, "max-repodesc-length"))
61 ctx.cfg.max_repodesc_len = atoi(value); 61 ctx.cfg.max_repodesc_len = atoi(value);
62 else if (!strcmp(name, "max-commit-count")) 62 else if (!strcmp(name, "max-commit-count"))
63 ctx.cfg.max_commit_count = atoi(value); 63 ctx.cfg.max_commit_count = atoi(value);
64 else if (!strcmp(name, "summary-log")) 64 else if (!strcmp(name, "summary-log"))
65 ctx.cfg.summary_log = atoi(value); 65 ctx.cfg.summary_log = atoi(value);
66 else if (!strcmp(name, "summary-branches")) 66 else if (!strcmp(name, "summary-branches"))
67 ctx.cfg.summary_branches = atoi(value); 67 ctx.cfg.summary_branches = atoi(value);
68 else if (!strcmp(name, "summary-tags")) 68 else if (!strcmp(name, "summary-tags"))
69 ctx.cfg.summary_tags = atoi(value); 69 ctx.cfg.summary_tags = atoi(value);
70 else if (!strcmp(name, "agefile")) 70 else if (!strcmp(name, "agefile"))
71 ctx.cfg.agefile = xstrdup(value); 71 ctx.cfg.agefile = xstrdup(value);
72 else if (!strcmp(name, "renamelimit")) 72 else if (!strcmp(name, "renamelimit"))
73 ctx.cfg.renamelimit = atoi(value); 73 ctx.cfg.renamelimit = atoi(value);
74 else if (!strcmp(name, "robots")) 74 else if (!strcmp(name, "robots"))
75 ctx.cfg.robots = xstrdup(value); 75 ctx.cfg.robots = xstrdup(value);
76 else if (!strcmp(name, "clone-prefix")) 76 else if (!strcmp(name, "clone-prefix"))
77 ctx.cfg.clone_prefix = xstrdup(value); 77 ctx.cfg.clone_prefix = xstrdup(value);
78 else if (!strcmp(name, "repo.group")) 78 else if (!strcmp(name, "repo.group"))
79 ctx.cfg.repo_group = xstrdup(value); 79 ctx.cfg.repo_group = xstrdup(value);
80 else if (!strcmp(name, "repo.url")) 80 else if (!strcmp(name, "repo.url"))
81 ctx.repo = cgit_add_repo(value); 81 ctx.repo = cgit_add_repo(value);
82 else if (!strcmp(name, "repo.name")) 82 else if (!strcmp(name, "repo.name"))
83 ctx.repo->name = xstrdup(value); 83 ctx.repo->name = xstrdup(value);
84 else if (ctx.repo && !strcmp(name, "repo.path")) 84 else if (ctx.repo && !strcmp(name, "repo.path"))
85 ctx.repo->path = trim_end(value, '/'); 85 ctx.repo->path = trim_end(value, '/');
86 else if (ctx.repo && !strcmp(name, "repo.clone-url")) 86 else if (ctx.repo && !strcmp(name, "repo.clone-url"))
87 ctx.repo->clone_url = xstrdup(value); 87 ctx.repo->clone_url = xstrdup(value);
88 else if (ctx.repo && !strcmp(name, "repo.desc")) 88 else if (ctx.repo && !strcmp(name, "repo.desc"))
89 ctx.repo->desc = xstrdup(value); 89 ctx.repo->desc = xstrdup(value);
90 else if (ctx.repo && !strcmp(name, "repo.owner")) 90 else if (ctx.repo && !strcmp(name, "repo.owner"))
91 ctx.repo->owner = xstrdup(value); 91 ctx.repo->owner = xstrdup(value);
92 else if (ctx.repo && !strcmp(name, "repo.defbranch")) 92 else if (ctx.repo && !strcmp(name, "repo.defbranch"))
93 ctx.repo->defbranch = xstrdup(value); 93 ctx.repo->defbranch = xstrdup(value);
94 else if (ctx.repo && !strcmp(name, "repo.snapshots")) 94 else if (ctx.repo && !strcmp(name, "repo.snapshots"))
95 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */ 95 ctx.repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */
96 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount")) 96 else if (ctx.repo && !strcmp(name, "repo.enable-log-filecount"))
97 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value); 97 ctx.repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value);
98 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount")) 98 else if (ctx.repo && !strcmp(name, "repo.enable-log-linecount"))
99 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); 99 ctx.repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value);
100 else if (ctx.repo && !strcmp(name, "repo.module-link")) 100 else if (ctx.repo && !strcmp(name, "repo.module-link"))
101 ctx.repo->module_link= xstrdup(value); 101 ctx.repo->module_link= xstrdup(value);
102 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) { 102 else if (ctx.repo && !strcmp(name, "repo.readme") && value != NULL) {
103 if (*value == '/') 103 if (*value == '/')
104 ctx.repo->readme = xstrdup(value); 104 ctx.repo->readme = xstrdup(value);
105 else 105 else
106 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value)); 106 ctx.repo->readme = xstrdup(fmt("%s/%s", ctx.repo->path, value));
107 } else if (!strcmp(name, "include")) 107 } else if (!strcmp(name, "include"))
108 parse_configfile(value, config_cb); 108 parse_configfile(value, config_cb);
109} 109}
110 110
111static void querystring_cb(const char *name, const char *value) 111static void querystring_cb(const char *name, const char *value)
112{ 112{
113 if (!strcmp(name,"r")) { 113 if (!strcmp(name,"r")) {
114 ctx.qry.repo = xstrdup(value); 114 ctx.qry.repo = xstrdup(value);
115 ctx.repo = cgit_get_repoinfo(value); 115 ctx.repo = cgit_get_repoinfo(value);
116 } else if (!strcmp(name, "p")) { 116 } else if (!strcmp(name, "p")) {
117 ctx.qry.page = xstrdup(value); 117 ctx.qry.page = xstrdup(value);
118 } else if (!strcmp(name, "url")) { 118 } else if (!strcmp(name, "url")) {
119 cgit_parse_url(value); 119 cgit_parse_url(value);
120 } else if (!strcmp(name, "qt")) { 120 } else if (!strcmp(name, "qt")) {
121 ctx.qry.grep = xstrdup(value); 121 ctx.qry.grep = xstrdup(value);
122 } else if (!strcmp(name, "q")) { 122 } else if (!strcmp(name, "q")) {
123 ctx.qry.search = xstrdup(value); 123 ctx.qry.search = xstrdup(value);
124 } else if (!strcmp(name, "h")) { 124 } else if (!strcmp(name, "h")) {
125 ctx.qry.head = xstrdup(value); 125 ctx.qry.head = xstrdup(value);
126 ctx.qry.has_symref = 1; 126 ctx.qry.has_symref = 1;
127 } else if (!strcmp(name, "id")) { 127 } else if (!strcmp(name, "id")) {
128 ctx.qry.sha1 = xstrdup(value); 128 ctx.qry.sha1 = xstrdup(value);
129 ctx.qry.has_sha1 = 1; 129 ctx.qry.has_sha1 = 1;
130 } else if (!strcmp(name, "id2")) { 130 } else if (!strcmp(name, "id2")) {
131 ctx.qry.sha2 = xstrdup(value); 131 ctx.qry.sha2 = xstrdup(value);
132 ctx.qry.has_sha1 = 1; 132 ctx.qry.has_sha1 = 1;
133 } else if (!strcmp(name, "ofs")) { 133 } else if (!strcmp(name, "ofs")) {
134 ctx.qry.ofs = atoi(value); 134 ctx.qry.ofs = atoi(value);
135 } else if (!strcmp(name, "path")) { 135 } else if (!strcmp(name, "path")) {
136 ctx.qry.path = trim_end(value, '/'); 136 ctx.qry.path = trim_end(value, '/');
137 } else if (!strcmp(name, "name")) { 137 } else if (!strcmp(name, "name")) {
138 ctx.qry.name = xstrdup(value); 138 ctx.qry.name = xstrdup(value);
139 } 139 }
140} 140}
141 141
142static void prepare_context(struct cgit_context *ctx) 142static void prepare_context(struct cgit_context *ctx)
143{ 143{
144 memset(ctx, 0, sizeof(ctx)); 144 memset(ctx, 0, sizeof(ctx));
145 ctx->cfg.agefile = "info/web/last-modified"; 145 ctx->cfg.agefile = "info/web/last-modified";
146 ctx->cfg.cache_dynamic_ttl = 5; 146 ctx->cfg.cache_dynamic_ttl = 5;
147 ctx->cfg.cache_max_create_time = 5; 147 ctx->cfg.cache_max_create_time = 5;
148 ctx->cfg.cache_repo_ttl = 5; 148 ctx->cfg.cache_repo_ttl = 5;
149 ctx->cfg.cache_root = CGIT_CACHE_ROOT; 149 ctx->cfg.cache_root = CGIT_CACHE_ROOT;
150 ctx->cfg.cache_root_ttl = 5; 150 ctx->cfg.cache_root_ttl = 5;
151 ctx->cfg.cache_static_ttl = -1; 151 ctx->cfg.cache_static_ttl = -1;
152 ctx->cfg.css = "/cgit.css"; 152 ctx->cfg.css = "/cgit.css";
153 ctx->cfg.logo = "/git-logo.png"; 153 ctx->cfg.logo = "/git-logo.png";
154 ctx->cfg.max_commit_count = 50; 154 ctx->cfg.max_commit_count = 50;
155 ctx->cfg.max_lock_attempts = 5; 155 ctx->cfg.max_lock_attempts = 5;
156 ctx->cfg.max_msg_len = 60; 156 ctx->cfg.max_msg_len = 60;
157 ctx->cfg.max_repodesc_len = 60; 157 ctx->cfg.max_repodesc_len = 60;
158 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s"; 158 ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s";
159 ctx->cfg.renamelimit = -1; 159 ctx->cfg.renamelimit = -1;
160 ctx->cfg.robots = "index, nofollow"; 160 ctx->cfg.robots = "index, nofollow";
161 ctx->cfg.root_title = "Git repository browser"; 161 ctx->cfg.root_title = "Git repository browser";
162 ctx->cfg.script_name = CGIT_SCRIPT_NAME; 162 ctx->cfg.script_name = CGIT_SCRIPT_NAME;
163 ctx->page.mimetype = "text/html"; 163 ctx->page.mimetype = "text/html";
164 ctx->page.charset = PAGE_ENCODING; 164 ctx->page.charset = PAGE_ENCODING;
165 ctx->page.filename = NULL; 165 ctx->page.filename = NULL;
166} 166}
167 167
168static int cgit_prepare_cache(struct cacheitem *item) 168static int cgit_prepare_cache(struct cacheitem *item)
169{ 169{
170 if (!ctx.repo && ctx.qry.repo) { 170 if (!ctx.repo && ctx.qry.repo) {
171 ctx.page.title = fmt("%s - %s", ctx.cfg.root_title, 171 ctx.page.title = fmt("%s - %s", ctx.cfg.root_title,
172 "Bad request"); 172 "Bad request");
173 cgit_print_http_headers(&ctx); 173 cgit_print_http_headers(&ctx);
174 cgit_print_docstart(&ctx); 174 cgit_print_docstart(&ctx);
175 cgit_print_pageheader(&ctx); 175 cgit_print_pageheader(&ctx);
176 cgit_print_error(fmt("Unknown repo: %s", ctx.qry.repo)); 176 cgit_print_error(fmt("Unknown repo: %s", ctx.qry.repo));
177 cgit_print_docend(); 177 cgit_print_docend();
178 return 0; 178 return 0;
179 } 179 }
180 180
181 if (!ctx.repo) { 181 if (!ctx.repo) {
182 item->name = xstrdup(fmt("%s/index.html", ctx.cfg.cache_root)); 182 item->name = xstrdup(fmt("%s/index.html", ctx.cfg.cache_root));
183 item->ttl = ctx.cfg.cache_root_ttl; 183 item->ttl = ctx.cfg.cache_root_ttl;
184 return 1; 184 return 1;
185 } 185 }
186 186
187 if (!ctx.qry.page) { 187 if (!ctx.qry.page) {
188 item->name = xstrdup(fmt("%s/%s/index.%s.html", ctx.cfg.cache_root, 188 item->name = xstrdup(fmt("%s/%s/index.%s.html", ctx.cfg.cache_root,
189 cache_safe_filename(ctx.repo->url), 189 cache_safe_filename(ctx.repo->url),
190 cache_safe_filename(ctx.qry.raw))); 190 cache_safe_filename(ctx.qry.raw)));
191 item->ttl = ctx.cfg.cache_repo_ttl; 191 item->ttl = ctx.cfg.cache_repo_ttl;
192 } else { 192 } else {
193 item->name = xstrdup(fmt("%s/%s/%s/%s.html", ctx.cfg.cache_root, 193 item->name = xstrdup(fmt("%s/%s/%s/%s.html", ctx.cfg.cache_root,
194 cache_safe_filename(ctx.repo->url), 194 cache_safe_filename(ctx.repo->url),
195 ctx.qry.page, 195 ctx.qry.page,
196 cache_safe_filename(ctx.qry.raw))); 196 cache_safe_filename(ctx.qry.raw)));
197 if (ctx.qry.has_symref) 197 if (ctx.qry.has_symref)
198 item->ttl = ctx.cfg.cache_dynamic_ttl; 198 item->ttl = ctx.cfg.cache_dynamic_ttl;
199 else if (ctx.qry.has_sha1) 199 else if (ctx.qry.has_sha1)
200 item->ttl = ctx.cfg.cache_static_ttl; 200 item->ttl = ctx.cfg.cache_static_ttl;
201 else 201 else
202 item->ttl = ctx.cfg.cache_repo_ttl; 202 item->ttl = ctx.cfg.cache_repo_ttl;
203 } 203 }
204 return 1; 204 return 1;
205} 205}
206 206
207struct refmatch { 207struct refmatch {
208 char *req_ref; 208 char *req_ref;
209 char *first_ref; 209 char *first_ref;
210 int match; 210 int match;
211}; 211};
212 212
213int find_current_ref(const char *refname, const unsigned char *sha1, 213int find_current_ref(const char *refname, const unsigned char *sha1,
214 int flags, void *cb_data) 214 int flags, void *cb_data)
215{ 215{
216 struct refmatch *info; 216 struct refmatch *info;
217 217
218 info = (struct refmatch *)cb_data; 218 info = (struct refmatch *)cb_data;
219 if (!strcmp(refname, info->req_ref)) 219 if (!strcmp(refname, info->req_ref))
220 info->match = 1; 220 info->match = 1;
221 if (!info->first_ref) 221 if (!info->first_ref)
222 info->first_ref = xstrdup(refname); 222 info->first_ref = xstrdup(refname);
223 return info->match; 223 return info->match;
224} 224}
225 225
226char *find_default_branch(struct cgit_repo *repo) 226char *find_default_branch(struct cgit_repo *repo)
227{ 227{
228 struct refmatch info; 228 struct refmatch info;
229 229
230 info.req_ref = repo->defbranch; 230 info.req_ref = repo->defbranch;
231 info.first_ref = NULL; 231 info.first_ref = NULL;
232 info.match = 0; 232 info.match = 0;
233 for_each_branch_ref(find_current_ref, &info); 233 for_each_branch_ref(find_current_ref, &info);
234 if (info.match) 234 if (info.match)
235 return info.req_ref; 235 return info.req_ref;
236 else 236 else
237 return info.first_ref; 237 return info.first_ref;
238} 238}
239 239
240static int prepare_repo_cmd(struct cgit_context *ctx) 240static int prepare_repo_cmd(struct cgit_context *ctx)
241{ 241{
242 char *tmp; 242 char *tmp;
243 unsigned char sha1[20]; 243 unsigned char sha1[20];
244 int nongit = 0; 244 int nongit = 0;
245 245
246 setenv("GIT_DIR", ctx->repo->path, 1); 246 setenv("GIT_DIR", ctx->repo->path, 1);
247 setup_git_directory_gently(&nongit); 247 setup_git_directory_gently(&nongit);
248 if (nongit) { 248 if (nongit) {
249 ctx->page.title = fmt("%s - %s", ctx->cfg.root_title, 249 ctx->page.title = fmt("%s - %s", ctx->cfg.root_title,
250 "config error"); 250 "config error");
251 tmp = fmt("Not a git repository: '%s'", ctx->repo->path); 251 tmp = fmt("Not a git repository: '%s'", ctx->repo->path);
252 ctx->repo = NULL; 252 ctx->repo = NULL;
253 cgit_print_http_headers(ctx); 253 cgit_print_http_headers(ctx);
254 cgit_print_docstart(ctx); 254 cgit_print_docstart(ctx);
255 cgit_print_pageheader(ctx); 255 cgit_print_pageheader(ctx);
256 cgit_print_error(tmp); 256 cgit_print_error(tmp);
257 cgit_print_docend(); 257 cgit_print_docend();
258 return 1; 258 return 1;
259 } 259 }
260 ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc); 260 ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc);
261 261
262 if (!ctx->qry.head) { 262 if (!ctx->qry.head) {
263 ctx->qry.head = xstrdup(find_default_branch(ctx->repo)); 263 ctx->qry.head = xstrdup(find_default_branch(ctx->repo));
264 ctx->repo->defbranch = ctx->qry.head; 264 ctx->repo->defbranch = ctx->qry.head;
265 } 265 }
266 266
267 if (!ctx->qry.head) { 267 if (!ctx->qry.head) {
268 cgit_print_http_headers(ctx); 268 cgit_print_http_headers(ctx);
269 cgit_print_docstart(ctx); 269 cgit_print_docstart(ctx);
270 cgit_print_pageheader(ctx); 270 cgit_print_pageheader(ctx);
271 cgit_print_error("Repository seems to be empty"); 271 cgit_print_error("Repository seems to be empty");
272 cgit_print_docend(); 272 cgit_print_docend();
273 return 1; 273 return 1;
274 } 274 }
275 275
276 if (get_sha1(ctx->qry.head, sha1)) { 276 if (get_sha1(ctx->qry.head, sha1)) {
277 tmp = xstrdup(ctx->qry.head); 277 tmp = xstrdup(ctx->qry.head);
278 ctx->qry.head = ctx->repo->defbranch; 278 ctx->qry.head = ctx->repo->defbranch;
279 cgit_print_http_headers(ctx); 279 cgit_print_http_headers(ctx);
280 cgit_print_docstart(ctx); 280 cgit_print_docstart(ctx);
281 cgit_print_pageheader(ctx); 281 cgit_print_pageheader(ctx);
282 cgit_print_error(fmt("Invalid branch: %s", tmp)); 282 cgit_print_error(fmt("Invalid branch: %s", tmp));
283 cgit_print_docend(); 283 cgit_print_docend();
284 return 1; 284 return 1;
285 } 285 }
286 return 0; 286 return 0;
287} 287}
288 288
289static void process_request(struct cgit_context *ctx) 289static void process_request(struct cgit_context *ctx)
290{ 290{
291 struct cgit_cmd *cmd; 291 struct cgit_cmd *cmd;
292 292
293 cmd = cgit_get_cmd(ctx); 293 cmd = cgit_get_cmd(ctx);
294 if (!cmd) { 294 if (!cmd) {
295 ctx->page.title = "cgit error"; 295 ctx->page.title = "cgit error";
296 ctx->repo = NULL; 296 ctx->repo = NULL;
297 cgit_print_http_headers(ctx); 297 cgit_print_http_headers(ctx);
298 cgit_print_docstart(ctx); 298 cgit_print_docstart(ctx);
299 cgit_print_pageheader(ctx); 299 cgit_print_pageheader(ctx);
300 cgit_print_error("Invalid request"); 300 cgit_print_error("Invalid request");
301 cgit_print_docend(); 301 cgit_print_docend();
302 return; 302 return;
303 } 303 }
304 304
305 if (cmd->want_repo && prepare_repo_cmd(ctx)) 305 if (cmd->want_repo && prepare_repo_cmd(ctx))
306 return; 306 return;
307 307
308 if (cmd->want_layout) { 308 if (cmd->want_layout) {
309 cgit_print_http_headers(ctx); 309 cgit_print_http_headers(ctx);
310 cgit_print_docstart(ctx); 310 cgit_print_docstart(ctx);
311 cgit_print_pageheader(ctx); 311 cgit_print_pageheader(ctx);
312 } 312 }
313 313
314 cmd->fn(ctx); 314 cmd->fn(ctx);
315 315
316 if (cmd->want_layout) 316 if (cmd->want_layout)
317 cgit_print_docend(); 317 cgit_print_docend();
318} 318}
319 319
320static long ttl_seconds(long ttl) 320static long ttl_seconds(long ttl)
321{ 321{
322 if (ttl<0) 322 if (ttl<0)
323 return 60 * 60 * 24 * 365; 323 return 60 * 60 * 24 * 365;
324 else 324 else
325 return ttl * 60; 325 return ttl * 60;
326} 326}
327 327
328static void cgit_fill_cache(struct cacheitem *item, int use_cache) 328static void cgit_fill_cache(struct cacheitem *item, int use_cache)
329{ 329{
330 int stdout2; 330 int stdout2;
331 331
332 if (use_cache) { 332 if (use_cache) {
333 stdout2 = chk_positive(dup(STDOUT_FILENO), 333 stdout2 = chk_positive(dup(STDOUT_FILENO),
334 "Preserving STDOUT"); 334 "Preserving STDOUT");
335 chk_zero(close(STDOUT_FILENO), "Closing STDOUT"); 335 chk_zero(close(STDOUT_FILENO), "Closing STDOUT");
336 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)"); 336 chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)");
337 } 337 }
338 338
339 ctx.page.modified = time(NULL); 339 ctx.page.modified = time(NULL);
340 ctx.page.expires = ctx.page.modified + ttl_seconds(item->ttl); 340 ctx.page.expires = ctx.page.modified + ttl_seconds(item->ttl);
341 process_request(&ctx); 341 process_request(&ctx);
342 342
343 if (use_cache) { 343 if (use_cache) {
344 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT"); 344 chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT");
345 chk_positive(dup2(stdout2, STDOUT_FILENO), 345 chk_positive(dup2(stdout2, STDOUT_FILENO),
346 "Restoring original STDOUT"); 346 "Restoring original STDOUT");
347 chk_zero(close(stdout2), "Closing temporary STDOUT"); 347 chk_zero(close(stdout2), "Closing temporary STDOUT");
348 } 348 }
349} 349}
350 350
351static void cgit_check_cache(struct cacheitem *item) 351static void cgit_check_cache(struct cacheitem *item)
352{ 352{
353 int i = 0; 353 int i = 0;
354 354
355 top: 355 top:
356 if (++i > ctx.cfg.max_lock_attempts) { 356 if (++i > ctx.cfg.max_lock_attempts) {
357 die("cgit_refresh_cache: unable to lock %s: %s", 357 die("cgit_refresh_cache: unable to lock %s: %s",
358 item->name, strerror(errno)); 358 item->name, strerror(errno));
359 } 359 }
360 if (!cache_exist(item)) { 360 if (!cache_exist(item)) {
361 if (!cache_lock(item)) { 361 if (!cache_lock(item)) {
362 sleep(1); 362 sleep(1);
363 goto top; 363 goto top;
364 } 364 }
365 if (!cache_exist(item)) { 365 if (!cache_exist(item)) {
366 cgit_fill_cache(item, 1); 366 cgit_fill_cache(item, 1);
367 cache_unlock(item); 367 cache_unlock(item);
368 } else { 368 } else {
369 cache_cancel_lock(item); 369 cache_cancel_lock(item);
370 } 370 }
371 } else if (cache_expired(item) && cache_lock(item)) { 371 } else if (cache_expired(item) && cache_lock(item)) {
372 if (cache_expired(item)) { 372 if (cache_expired(item)) {
373 cgit_fill_cache(item, 1); 373 cgit_fill_cache(item, 1);
374 cache_unlock(item); 374 cache_unlock(item);
375 } else { 375 } else {
376 cache_cancel_lock(item); 376 cache_cancel_lock(item);
377 } 377 }
378 } 378 }
379} 379}
380 380
381static void cgit_print_cache(struct cacheitem *item) 381static void cgit_print_cache(struct cacheitem *item)
382{ 382{
383 static char buf[4096]; 383 static char buf[4096];
384 ssize_t i; 384 ssize_t i;
385 385
386 int fd = open(item->name, O_RDONLY); 386 int fd = open(item->name, O_RDONLY);
387 if (fd<0) 387 if (fd<0)
388 die("Unable to open cached file %s", item->name); 388 die("Unable to open cached file %s", item->name);
389 389
390 while((i=read(fd, buf, sizeof(buf))) > 0) 390 while((i=read(fd, buf, sizeof(buf))) > 0)
391 write(STDOUT_FILENO, buf, i); 391 write(STDOUT_FILENO, buf, i);
392 392
393 close(fd); 393 close(fd);
394} 394}
395 395
396static void cgit_parse_args(int argc, const char **argv) 396static void cgit_parse_args(int argc, const char **argv)
397{ 397{
398 int i; 398 int i;
399 399
400 for (i = 1; i < argc; i++) { 400 for (i = 1; i < argc; i++) {
401 if (!strncmp(argv[i], "--cache=", 8)) { 401 if (!strncmp(argv[i], "--cache=", 8)) {
402 ctx.cfg.cache_root = xstrdup(argv[i]+8); 402 ctx.cfg.cache_root = xstrdup(argv[i]+8);
403 } 403 }
404 if (!strcmp(argv[i], "--nocache")) { 404 if (!strcmp(argv[i], "--nocache")) {
405 ctx.cfg.nocache = 1; 405 ctx.cfg.nocache = 1;
406 } 406 }
407 if (!strncmp(argv[i], "--query=", 8)) { 407 if (!strncmp(argv[i], "--query=", 8)) {
408 ctx.qry.raw = xstrdup(argv[i]+8); 408 ctx.qry.raw = xstrdup(argv[i]+8);
409 } 409 }
410 if (!strncmp(argv[i], "--repo=", 7)) { 410 if (!strncmp(argv[i], "--repo=", 7)) {
411 ctx.qry.repo = xstrdup(argv[i]+7); 411 ctx.qry.repo = xstrdup(argv[i]+7);
412 } 412 }
413 if (!strncmp(argv[i], "--page=", 7)) { 413 if (!strncmp(argv[i], "--page=", 7)) {
414 ctx.qry.page = xstrdup(argv[i]+7); 414 ctx.qry.page = xstrdup(argv[i]+7);
415 } 415 }
416 if (!strncmp(argv[i], "--head=", 7)) { 416 if (!strncmp(argv[i], "--head=", 7)) {
417 ctx.qry.head = xstrdup(argv[i]+7); 417 ctx.qry.head = xstrdup(argv[i]+7);
418 ctx.qry.has_symref = 1; 418 ctx.qry.has_symref = 1;
419 } 419 }
420 if (!strncmp(argv[i], "--sha1=", 7)) { 420 if (!strncmp(argv[i], "--sha1=", 7)) {
421 ctx.qry.sha1 = xstrdup(argv[i]+7); 421 ctx.qry.sha1 = xstrdup(argv[i]+7);
422 ctx.qry.has_sha1 = 1; 422 ctx.qry.has_sha1 = 1;
423 } 423 }
424 if (!strncmp(argv[i], "--ofs=", 6)) { 424 if (!strncmp(argv[i], "--ofs=", 6)) {
425 ctx.qry.ofs = atoi(argv[i]+6); 425 ctx.qry.ofs = atoi(argv[i]+6);
426 } 426 }
427 } 427 }
428} 428}
429 429
430int main(int argc, const char **argv) 430int main(int argc, const char **argv)
431{ 431{
432 struct cacheitem item; 432 struct cacheitem item;
433 const char *cgit_config_env = getenv("CGIT_CONFIG"); 433 const char *cgit_config_env = getenv("CGIT_CONFIG");
434 434
435 prepare_context(&ctx); 435 prepare_context(&ctx);
436 item.st.st_mtime = time(NULL); 436 item.st.st_mtime = time(NULL);
437 cgit_repolist.length = 0; 437 cgit_repolist.length = 0;
438 cgit_repolist.count = 0; 438 cgit_repolist.count = 0;
439 cgit_repolist.repos = NULL; 439 cgit_repolist.repos = NULL;
440 440
441 parse_configfile(cgit_config_env ? cgit_config_env : CGIT_CONFIG, 441 parse_configfile(cgit_config_env ? cgit_config_env : CGIT_CONFIG,
442 config_cb); 442 config_cb);
443 ctx.repo = NULL;
443 if (getenv("SCRIPT_NAME")) 444 if (getenv("SCRIPT_NAME"))
444 ctx.cfg.script_name = xstrdup(getenv("SCRIPT_NAME")); 445 ctx.cfg.script_name = xstrdup(getenv("SCRIPT_NAME"));
445 if (getenv("QUERY_STRING")) 446 if (getenv("QUERY_STRING"))
446 ctx.qry.raw = xstrdup(getenv("QUERY_STRING")); 447 ctx.qry.raw = xstrdup(getenv("QUERY_STRING"));
447 cgit_parse_args(argc, argv); 448 cgit_parse_args(argc, argv);
448 http_parse_querystring(ctx.qry.raw, querystring_cb); 449 http_parse_querystring(ctx.qry.raw, querystring_cb);
449 if (!cgit_prepare_cache(&item)) 450 if (!cgit_prepare_cache(&item))
450 return 0; 451 return 0;
451 if (ctx.cfg.nocache) { 452 if (ctx.cfg.nocache) {
452 cgit_fill_cache(&item, 0); 453 cgit_fill_cache(&item, 0);
453 } else { 454 } else {
454 cgit_check_cache(&item); 455 cgit_check_cache(&item);
455 cgit_print_cache(&item); 456 cgit_print_cache(&item);
456 } 457 }
457 return 0; 458 return 0;
458} 459}