author | Lars Hjemli <hjemli@gmail.com> | 2008-04-28 23:01:30 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2008-04-28 23:01:30 (UTC) |
commit | 651ef79768dde30aabc61189974c9047ee43752f (patch) (unidiff) | |
tree | c01edea9d585784a50c2335c1ddfb36944cba889 | |
parent | 4c9916043d6aabb8278e0d78f5fa71a59f82889d (diff) | |
download | cgit-651ef79768dde30aabc61189974c9047ee43752f.zip cgit-651ef79768dde30aabc61189974c9047ee43752f.tar.gz cgit-651ef79768dde30aabc61189974c9047ee43752f.tar.bz2 |
Make it possible for a single cmd to work both with and without a repo
When cgit_cmd.want_repo was 0, we used to assume that the cmd would never
be invoked for a repo. But soon this will become untrue (the 'about' cmd
is rapidly approching), so from now on we will initialize any requested
repo even if want_repo==0 (and return an error if want_repo==1 but no repo
is specified).
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | cgit.c | 11 |
1 files changed, 10 insertions, 1 deletions
@@ -214,193 +214,202 @@ struct refmatch { | |||
214 | char *first_ref; | 214 | char *first_ref; |
215 | int match; | 215 | int match; |
216 | }; | 216 | }; |
217 | 217 | ||
218 | int find_current_ref(const char *refname, const unsigned char *sha1, | 218 | int find_current_ref(const char *refname, const unsigned char *sha1, |
219 | int flags, void *cb_data) | 219 | int flags, void *cb_data) |
220 | { | 220 | { |
221 | struct refmatch *info; | 221 | struct refmatch *info; |
222 | 222 | ||
223 | info = (struct refmatch *)cb_data; | 223 | info = (struct refmatch *)cb_data; |
224 | if (!strcmp(refname, info->req_ref)) | 224 | if (!strcmp(refname, info->req_ref)) |
225 | info->match = 1; | 225 | info->match = 1; |
226 | if (!info->first_ref) | 226 | if (!info->first_ref) |
227 | info->first_ref = xstrdup(refname); | 227 | info->first_ref = xstrdup(refname); |
228 | return info->match; | 228 | return info->match; |
229 | } | 229 | } |
230 | 230 | ||
231 | char *find_default_branch(struct cgit_repo *repo) | 231 | char *find_default_branch(struct cgit_repo *repo) |
232 | { | 232 | { |
233 | struct refmatch info; | 233 | struct refmatch info; |
234 | 234 | ||
235 | info.req_ref = repo->defbranch; | 235 | info.req_ref = repo->defbranch; |
236 | info.first_ref = NULL; | 236 | info.first_ref = NULL; |
237 | info.match = 0; | 237 | info.match = 0; |
238 | for_each_branch_ref(find_current_ref, &info); | 238 | for_each_branch_ref(find_current_ref, &info); |
239 | if (info.match) | 239 | if (info.match) |
240 | return info.req_ref; | 240 | return info.req_ref; |
241 | else | 241 | else |
242 | return info.first_ref; | 242 | return info.first_ref; |
243 | } | 243 | } |
244 | 244 | ||
245 | static int prepare_repo_cmd(struct cgit_context *ctx) | 245 | static int prepare_repo_cmd(struct cgit_context *ctx) |
246 | { | 246 | { |
247 | char *tmp; | 247 | char *tmp; |
248 | unsigned char sha1[20]; | 248 | unsigned char sha1[20]; |
249 | int nongit = 0; | 249 | int nongit = 0; |
250 | 250 | ||
251 | setenv("GIT_DIR", ctx->repo->path, 1); | 251 | setenv("GIT_DIR", ctx->repo->path, 1); |
252 | setup_git_directory_gently(&nongit); | 252 | setup_git_directory_gently(&nongit); |
253 | if (nongit) { | 253 | if (nongit) { |
254 | ctx->page.title = fmt("%s - %s", ctx->cfg.root_title, | 254 | ctx->page.title = fmt("%s - %s", ctx->cfg.root_title, |
255 | "config error"); | 255 | "config error"); |
256 | tmp = fmt("Not a git repository: '%s'", ctx->repo->path); | 256 | tmp = fmt("Not a git repository: '%s'", ctx->repo->path); |
257 | ctx->repo = NULL; | 257 | ctx->repo = NULL; |
258 | cgit_print_http_headers(ctx); | 258 | cgit_print_http_headers(ctx); |
259 | cgit_print_docstart(ctx); | 259 | cgit_print_docstart(ctx); |
260 | cgit_print_pageheader(ctx); | 260 | cgit_print_pageheader(ctx); |
261 | cgit_print_error(tmp); | 261 | cgit_print_error(tmp); |
262 | cgit_print_docend(); | 262 | cgit_print_docend(); |
263 | return 1; | 263 | return 1; |
264 | } | 264 | } |
265 | ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc); | 265 | ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc); |
266 | 266 | ||
267 | if (!ctx->qry.head) { | 267 | if (!ctx->qry.head) { |
268 | ctx->qry.head = xstrdup(find_default_branch(ctx->repo)); | 268 | ctx->qry.head = xstrdup(find_default_branch(ctx->repo)); |
269 | ctx->repo->defbranch = ctx->qry.head; | 269 | ctx->repo->defbranch = ctx->qry.head; |
270 | } | 270 | } |
271 | 271 | ||
272 | if (!ctx->qry.head) { | 272 | if (!ctx->qry.head) { |
273 | cgit_print_http_headers(ctx); | 273 | cgit_print_http_headers(ctx); |
274 | cgit_print_docstart(ctx); | 274 | cgit_print_docstart(ctx); |
275 | cgit_print_pageheader(ctx); | 275 | cgit_print_pageheader(ctx); |
276 | cgit_print_error("Repository seems to be empty"); | 276 | cgit_print_error("Repository seems to be empty"); |
277 | cgit_print_docend(); | 277 | cgit_print_docend(); |
278 | return 1; | 278 | return 1; |
279 | } | 279 | } |
280 | 280 | ||
281 | if (get_sha1(ctx->qry.head, sha1)) { | 281 | if (get_sha1(ctx->qry.head, sha1)) { |
282 | tmp = xstrdup(ctx->qry.head); | 282 | tmp = xstrdup(ctx->qry.head); |
283 | ctx->qry.head = ctx->repo->defbranch; | 283 | ctx->qry.head = ctx->repo->defbranch; |
284 | cgit_print_http_headers(ctx); | 284 | cgit_print_http_headers(ctx); |
285 | cgit_print_docstart(ctx); | 285 | cgit_print_docstart(ctx); |
286 | cgit_print_pageheader(ctx); | 286 | cgit_print_pageheader(ctx); |
287 | cgit_print_error(fmt("Invalid branch: %s", tmp)); | 287 | cgit_print_error(fmt("Invalid branch: %s", tmp)); |
288 | cgit_print_docend(); | 288 | cgit_print_docend(); |
289 | return 1; | 289 | return 1; |
290 | } | 290 | } |
291 | return 0; | 291 | return 0; |
292 | } | 292 | } |
293 | 293 | ||
294 | static void process_request(struct cgit_context *ctx) | 294 | static void process_request(struct cgit_context *ctx) |
295 | { | 295 | { |
296 | struct cgit_cmd *cmd; | 296 | struct cgit_cmd *cmd; |
297 | 297 | ||
298 | cmd = cgit_get_cmd(ctx); | 298 | cmd = cgit_get_cmd(ctx); |
299 | if (!cmd) { | 299 | if (!cmd) { |
300 | ctx->page.title = "cgit error"; | 300 | ctx->page.title = "cgit error"; |
301 | ctx->repo = NULL; | 301 | ctx->repo = NULL; |
302 | cgit_print_http_headers(ctx); | 302 | cgit_print_http_headers(ctx); |
303 | cgit_print_docstart(ctx); | 303 | cgit_print_docstart(ctx); |
304 | cgit_print_pageheader(ctx); | 304 | cgit_print_pageheader(ctx); |
305 | cgit_print_error("Invalid request"); | 305 | cgit_print_error("Invalid request"); |
306 | cgit_print_docend(); | 306 | cgit_print_docend(); |
307 | return; | 307 | return; |
308 | } | 308 | } |
309 | 309 | ||
310 | if (cmd->want_repo && prepare_repo_cmd(ctx)) | 310 | if (cmd->want_repo && !ctx->repo) { |
311 | cgit_print_http_headers(ctx); | ||
312 | cgit_print_docstart(ctx); | ||
313 | cgit_print_pageheader(ctx); | ||
314 | cgit_print_error(fmt("No repository selected")); | ||
315 | cgit_print_docend(); | ||
316 | return; | ||
317 | } | ||
318 | |||
319 | if (ctx->repo && prepare_repo_cmd(ctx)) | ||
311 | return; | 320 | return; |
312 | 321 | ||
313 | if (cmd->want_layout) { | 322 | if (cmd->want_layout) { |
314 | cgit_print_http_headers(ctx); | 323 | cgit_print_http_headers(ctx); |
315 | cgit_print_docstart(ctx); | 324 | cgit_print_docstart(ctx); |
316 | cgit_print_pageheader(ctx); | 325 | cgit_print_pageheader(ctx); |
317 | } | 326 | } |
318 | 327 | ||
319 | cmd->fn(ctx); | 328 | cmd->fn(ctx); |
320 | 329 | ||
321 | if (cmd->want_layout) | 330 | if (cmd->want_layout) |
322 | cgit_print_docend(); | 331 | cgit_print_docend(); |
323 | } | 332 | } |
324 | 333 | ||
325 | static long ttl_seconds(long ttl) | 334 | static long ttl_seconds(long ttl) |
326 | { | 335 | { |
327 | if (ttl<0) | 336 | if (ttl<0) |
328 | return 60 * 60 * 24 * 365; | 337 | return 60 * 60 * 24 * 365; |
329 | else | 338 | else |
330 | return ttl * 60; | 339 | return ttl * 60; |
331 | } | 340 | } |
332 | 341 | ||
333 | static void cgit_fill_cache(struct cacheitem *item, int use_cache) | 342 | static void cgit_fill_cache(struct cacheitem *item, int use_cache) |
334 | { | 343 | { |
335 | int stdout2; | 344 | int stdout2; |
336 | 345 | ||
337 | if (use_cache) { | 346 | if (use_cache) { |
338 | stdout2 = chk_positive(dup(STDOUT_FILENO), | 347 | stdout2 = chk_positive(dup(STDOUT_FILENO), |
339 | "Preserving STDOUT"); | 348 | "Preserving STDOUT"); |
340 | chk_zero(close(STDOUT_FILENO), "Closing STDOUT"); | 349 | chk_zero(close(STDOUT_FILENO), "Closing STDOUT"); |
341 | chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)"); | 350 | chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)"); |
342 | } | 351 | } |
343 | 352 | ||
344 | ctx.page.modified = time(NULL); | 353 | ctx.page.modified = time(NULL); |
345 | ctx.page.expires = ctx.page.modified + ttl_seconds(item->ttl); | 354 | ctx.page.expires = ctx.page.modified + ttl_seconds(item->ttl); |
346 | process_request(&ctx); | 355 | process_request(&ctx); |
347 | 356 | ||
348 | if (use_cache) { | 357 | if (use_cache) { |
349 | chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT"); | 358 | chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT"); |
350 | chk_positive(dup2(stdout2, STDOUT_FILENO), | 359 | chk_positive(dup2(stdout2, STDOUT_FILENO), |
351 | "Restoring original STDOUT"); | 360 | "Restoring original STDOUT"); |
352 | chk_zero(close(stdout2), "Closing temporary STDOUT"); | 361 | chk_zero(close(stdout2), "Closing temporary STDOUT"); |
353 | } | 362 | } |
354 | } | 363 | } |
355 | 364 | ||
356 | static void cgit_check_cache(struct cacheitem *item) | 365 | static void cgit_check_cache(struct cacheitem *item) |
357 | { | 366 | { |
358 | int i = 0; | 367 | int i = 0; |
359 | 368 | ||
360 | top: | 369 | top: |
361 | if (++i > ctx.cfg.max_lock_attempts) { | 370 | if (++i > ctx.cfg.max_lock_attempts) { |
362 | die("cgit_refresh_cache: unable to lock %s: %s", | 371 | die("cgit_refresh_cache: unable to lock %s: %s", |
363 | item->name, strerror(errno)); | 372 | item->name, strerror(errno)); |
364 | } | 373 | } |
365 | if (!cache_exist(item)) { | 374 | if (!cache_exist(item)) { |
366 | if (!cache_lock(item)) { | 375 | if (!cache_lock(item)) { |
367 | sleep(1); | 376 | sleep(1); |
368 | goto top; | 377 | goto top; |
369 | } | 378 | } |
370 | if (!cache_exist(item)) { | 379 | if (!cache_exist(item)) { |
371 | cgit_fill_cache(item, 1); | 380 | cgit_fill_cache(item, 1); |
372 | cache_unlock(item); | 381 | cache_unlock(item); |
373 | } else { | 382 | } else { |
374 | cache_cancel_lock(item); | 383 | cache_cancel_lock(item); |
375 | } | 384 | } |
376 | } else if (cache_expired(item) && cache_lock(item)) { | 385 | } else if (cache_expired(item) && cache_lock(item)) { |
377 | if (cache_expired(item)) { | 386 | if (cache_expired(item)) { |
378 | cgit_fill_cache(item, 1); | 387 | cgit_fill_cache(item, 1); |
379 | cache_unlock(item); | 388 | cache_unlock(item); |
380 | } else { | 389 | } else { |
381 | cache_cancel_lock(item); | 390 | cache_cancel_lock(item); |
382 | } | 391 | } |
383 | } | 392 | } |
384 | } | 393 | } |
385 | 394 | ||
386 | static void cgit_print_cache(struct cacheitem *item) | 395 | static void cgit_print_cache(struct cacheitem *item) |
387 | { | 396 | { |
388 | static char buf[4096]; | 397 | static char buf[4096]; |
389 | ssize_t i; | 398 | ssize_t i; |
390 | 399 | ||
391 | int fd = open(item->name, O_RDONLY); | 400 | int fd = open(item->name, O_RDONLY); |
392 | if (fd<0) | 401 | if (fd<0) |
393 | die("Unable to open cached file %s", item->name); | 402 | die("Unable to open cached file %s", item->name); |
394 | 403 | ||
395 | while((i=read(fd, buf, sizeof(buf))) > 0) | 404 | while((i=read(fd, buf, sizeof(buf))) > 0) |
396 | write(STDOUT_FILENO, buf, i); | 405 | write(STDOUT_FILENO, buf, i); |
397 | 406 | ||
398 | close(fd); | 407 | close(fd); |
399 | } | 408 | } |
400 | 409 | ||
401 | static void cgit_parse_args(int argc, const char **argv) | 410 | static void cgit_parse_args(int argc, const char **argv) |
402 | { | 411 | { |
403 | int i; | 412 | int i; |
404 | 413 | ||
405 | for (i = 1; i < argc; i++) { | 414 | for (i = 1; i < argc; i++) { |
406 | if (!strncmp(argv[i], "--cache=", 8)) { | 415 | if (!strncmp(argv[i], "--cache=", 8)) { |