summaryrefslogtreecommitdiffabout
path: root/cgit.c
authorLars Hjemli <hjemli@gmail.com>2009-08-24 11:31:49 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2009-08-24 11:31:49 (UTC)
commitee554849ac7209fa8f7486327ec9f3b370e4c876 (patch) (unidiff)
tree63c284ebf72ea401067dd5d4d59ae8ede8f8743c /cgit.c
parent588fb8efc69778b85062e8fc2f482a8de43bad75 (diff)
downloadcgit-ee554849ac7209fa8f7486327ec9f3b370e4c876.zip
cgit-ee554849ac7209fa8f7486327ec9f3b370e4c876.tar.gz
cgit-ee554849ac7209fa8f7486327ec9f3b370e4c876.tar.bz2
cgit.c: respect repo-local 'snapshots' option for --scan-path
The repo-specific 'snapshots' option is bitwise AND'ed with the global 'snapshots' option during parsing, and since the global cgitrc hasn't been parsed when --scan-path is processed the global 'snapshots' will always be 0 (i.e. no repo-specific 'snapshots' setting will have any effect). This patch fixes the issue by setting the global 'snapshots' mask to 0xFF (hence relying on later parsing of the generated cgitrc repolist to do the right thing). Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'cgit.c') (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/cgit.c b/cgit.c
index 8381630..3fcca2a 100644
--- a/cgit.c
+++ b/cgit.c
@@ -527,179 +527,189 @@ static int generate_cached_repolist(const char *path, const char *cached_rc)
527 FILE *f; 527 FILE *f;
528 528
529 locked_rc = xstrdup(fmt("%s.lock", cached_rc)); 529 locked_rc = xstrdup(fmt("%s.lock", cached_rc));
530 f = fopen(locked_rc, "wx"); 530 f = fopen(locked_rc, "wx");
531 if (!f) { 531 if (!f) {
532 /* Inform about the error unless the lockfile already existed, 532 /* Inform about the error unless the lockfile already existed,
533 * since that only means we've got concurrent requests. 533 * since that only means we've got concurrent requests.
534 */ 534 */
535 if (errno != EEXIST) 535 if (errno != EEXIST)
536 fprintf(stderr, "[cgit] Error opening %s: %s (%d)\n", 536 fprintf(stderr, "[cgit] Error opening %s: %s (%d)\n",
537 locked_rc, strerror(errno), errno); 537 locked_rc, strerror(errno), errno);
538 return errno; 538 return errno;
539 } 539 }
540 idx = cgit_repolist.count; 540 idx = cgit_repolist.count;
541 scan_tree(path, repo_config); 541 scan_tree(path, repo_config);
542 print_repolist(f, &cgit_repolist, idx); 542 print_repolist(f, &cgit_repolist, idx);
543 if (rename(locked_rc, cached_rc)) 543 if (rename(locked_rc, cached_rc))
544 fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n", 544 fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n",
545 locked_rc, cached_rc, strerror(errno), errno); 545 locked_rc, cached_rc, strerror(errno), errno);
546 fclose(f); 546 fclose(f);
547 return 0; 547 return 0;
548} 548}
549 549
550static void process_cached_repolist(const char *path) 550static void process_cached_repolist(const char *path)
551{ 551{
552 struct stat st; 552 struct stat st;
553 char *cached_rc; 553 char *cached_rc;
554 time_t age; 554 time_t age;
555 555
556 cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root, 556 cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root,
557 hash_str(path))); 557 hash_str(path)));
558 558
559 if (stat(cached_rc, &st)) { 559 if (stat(cached_rc, &st)) {
560 /* Nothing is cached, we need to scan without forking. And 560 /* Nothing is cached, we need to scan without forking. And
561 * if we fail to generate a cached repolist, we need to 561 * if we fail to generate a cached repolist, we need to
562 * invoke scan_tree manually. 562 * invoke scan_tree manually.
563 */ 563 */
564 if (generate_cached_repolist(path, cached_rc)) 564 if (generate_cached_repolist(path, cached_rc))
565 scan_tree(path, repo_config); 565 scan_tree(path, repo_config);
566 return; 566 return;
567 } 567 }
568 568
569 parse_configfile(cached_rc, config_cb); 569 parse_configfile(cached_rc, config_cb);
570 570
571 /* If the cached configfile hasn't expired, lets exit now */ 571 /* If the cached configfile hasn't expired, lets exit now */
572 age = time(NULL) - st.st_mtime; 572 age = time(NULL) - st.st_mtime;
573 if (age <= (ctx.cfg.cache_scanrc_ttl * 60)) 573 if (age <= (ctx.cfg.cache_scanrc_ttl * 60))
574 return; 574 return;
575 575
576 /* The cached repolist has been parsed, but it was old. So lets 576 /* The cached repolist has been parsed, but it was old. So lets
577 * rescan the specified path and generate a new cached repolist 577 * rescan the specified path and generate a new cached repolist
578 * in a child-process to avoid latency for the current request. 578 * in a child-process to avoid latency for the current request.
579 */ 579 */
580 if (fork()) 580 if (fork())
581 return; 581 return;
582 582
583 exit(generate_cached_repolist(path, cached_rc)); 583 exit(generate_cached_repolist(path, cached_rc));
584} 584}
585 585
586static void cgit_parse_args(int argc, const char **argv) 586static void cgit_parse_args(int argc, const char **argv)
587{ 587{
588 int i; 588 int i;
589 int scan = 0; 589 int scan = 0;
590 590
591 for (i = 1; i < argc; i++) { 591 for (i = 1; i < argc; i++) {
592 if (!strncmp(argv[i], "--cache=", 8)) { 592 if (!strncmp(argv[i], "--cache=", 8)) {
593 ctx.cfg.cache_root = xstrdup(argv[i]+8); 593 ctx.cfg.cache_root = xstrdup(argv[i]+8);
594 } 594 }
595 if (!strcmp(argv[i], "--nocache")) { 595 if (!strcmp(argv[i], "--nocache")) {
596 ctx.cfg.nocache = 1; 596 ctx.cfg.nocache = 1;
597 } 597 }
598 if (!strcmp(argv[i], "--nohttp")) { 598 if (!strcmp(argv[i], "--nohttp")) {
599 ctx.env.no_http = "1"; 599 ctx.env.no_http = "1";
600 } 600 }
601 if (!strncmp(argv[i], "--query=", 8)) { 601 if (!strncmp(argv[i], "--query=", 8)) {
602 ctx.qry.raw = xstrdup(argv[i]+8); 602 ctx.qry.raw = xstrdup(argv[i]+8);
603 } 603 }
604 if (!strncmp(argv[i], "--repo=", 7)) { 604 if (!strncmp(argv[i], "--repo=", 7)) {
605 ctx.qry.repo = xstrdup(argv[i]+7); 605 ctx.qry.repo = xstrdup(argv[i]+7);
606 } 606 }
607 if (!strncmp(argv[i], "--page=", 7)) { 607 if (!strncmp(argv[i], "--page=", 7)) {
608 ctx.qry.page = xstrdup(argv[i]+7); 608 ctx.qry.page = xstrdup(argv[i]+7);
609 } 609 }
610 if (!strncmp(argv[i], "--head=", 7)) { 610 if (!strncmp(argv[i], "--head=", 7)) {
611 ctx.qry.head = xstrdup(argv[i]+7); 611 ctx.qry.head = xstrdup(argv[i]+7);
612 ctx.qry.has_symref = 1; 612 ctx.qry.has_symref = 1;
613 } 613 }
614 if (!strncmp(argv[i], "--sha1=", 7)) { 614 if (!strncmp(argv[i], "--sha1=", 7)) {
615 ctx.qry.sha1 = xstrdup(argv[i]+7); 615 ctx.qry.sha1 = xstrdup(argv[i]+7);
616 ctx.qry.has_sha1 = 1; 616 ctx.qry.has_sha1 = 1;
617 } 617 }
618 if (!strncmp(argv[i], "--ofs=", 6)) { 618 if (!strncmp(argv[i], "--ofs=", 6)) {
619 ctx.qry.ofs = atoi(argv[i]+6); 619 ctx.qry.ofs = atoi(argv[i]+6);
620 } 620 }
621 if (!strncmp(argv[i], "--scan-tree=", 12) || 621 if (!strncmp(argv[i], "--scan-tree=", 12) ||
622 !strncmp(argv[i], "--scan-path=", 12)) { 622 !strncmp(argv[i], "--scan-path=", 12)) {
623 /* HACK: the global snapshot bitmask defines the
624 * set of allowed snapshot formats, but the config
625 * file hasn't been parsed yet so the mask is
626 * currently 0. By setting all bits high before
627 * scanning we make sure that any in-repo cgitrc
628 * snapshot setting is respected by scan_tree().
629 * BTW: we assume that there'll never be more than
630 * 255 different snapshot formats supported by cgit...
631 */
632 ctx.cfg.snapshots = 0xFF;
623 scan++; 633 scan++;
624 scan_tree(argv[i] + 12, repo_config); 634 scan_tree(argv[i] + 12, repo_config);
625 } 635 }
626 } 636 }
627 if (scan) { 637 if (scan) {
628 qsort(cgit_repolist.repos, cgit_repolist.count, 638 qsort(cgit_repolist.repos, cgit_repolist.count,
629 sizeof(struct cgit_repo), cmp_repos); 639 sizeof(struct cgit_repo), cmp_repos);
630 print_repolist(stdout, &cgit_repolist, 0); 640 print_repolist(stdout, &cgit_repolist, 0);
631 exit(0); 641 exit(0);
632 } 642 }
633} 643}
634 644
635static int calc_ttl() 645static int calc_ttl()
636{ 646{
637 if (!ctx.repo) 647 if (!ctx.repo)
638 return ctx.cfg.cache_root_ttl; 648 return ctx.cfg.cache_root_ttl;
639 649
640 if (!ctx.qry.page) 650 if (!ctx.qry.page)
641 return ctx.cfg.cache_repo_ttl; 651 return ctx.cfg.cache_repo_ttl;
642 652
643 if (ctx.qry.has_symref) 653 if (ctx.qry.has_symref)
644 return ctx.cfg.cache_dynamic_ttl; 654 return ctx.cfg.cache_dynamic_ttl;
645 655
646 if (ctx.qry.has_sha1) 656 if (ctx.qry.has_sha1)
647 return ctx.cfg.cache_static_ttl; 657 return ctx.cfg.cache_static_ttl;
648 658
649 return ctx.cfg.cache_repo_ttl; 659 return ctx.cfg.cache_repo_ttl;
650} 660}
651 661
652int main(int argc, const char **argv) 662int main(int argc, const char **argv)
653{ 663{
654 const char *path; 664 const char *path;
655 char *qry; 665 char *qry;
656 int err, ttl; 666 int err, ttl;
657 667
658 prepare_context(&ctx); 668 prepare_context(&ctx);
659 cgit_repolist.length = 0; 669 cgit_repolist.length = 0;
660 cgit_repolist.count = 0; 670 cgit_repolist.count = 0;
661 cgit_repolist.repos = NULL; 671 cgit_repolist.repos = NULL;
662 672
663 cgit_parse_args(argc, argv); 673 cgit_parse_args(argc, argv);
664 parse_configfile(ctx.env.cgit_config, config_cb); 674 parse_configfile(ctx.env.cgit_config, config_cb);
665 ctx.repo = NULL; 675 ctx.repo = NULL;
666 http_parse_querystring(ctx.qry.raw, querystring_cb); 676 http_parse_querystring(ctx.qry.raw, querystring_cb);
667 677
668 /* If virtual-root isn't specified in cgitrc, lets pretend 678 /* If virtual-root isn't specified in cgitrc, lets pretend
669 * that virtual-root equals SCRIPT_NAME. 679 * that virtual-root equals SCRIPT_NAME.
670 */ 680 */
671 if (!ctx.cfg.virtual_root) 681 if (!ctx.cfg.virtual_root)
672 ctx.cfg.virtual_root = ctx.cfg.script_name; 682 ctx.cfg.virtual_root = ctx.cfg.script_name;
673 683
674 /* If no url parameter is specified on the querystring, lets 684 /* If no url parameter is specified on the querystring, lets
675 * use PATH_INFO as url. This allows cgit to work with virtual 685 * use PATH_INFO as url. This allows cgit to work with virtual
676 * urls without the need for rewriterules in the webserver (as 686 * urls without the need for rewriterules in the webserver (as
677 * long as PATH_INFO is included in the cache lookup key). 687 * long as PATH_INFO is included in the cache lookup key).
678 */ 688 */
679 path = ctx.env.path_info; 689 path = ctx.env.path_info;
680 if (!ctx.qry.url && path) { 690 if (!ctx.qry.url && path) {
681 if (path[0] == '/') 691 if (path[0] == '/')
682 path++; 692 path++;
683 ctx.qry.url = xstrdup(path); 693 ctx.qry.url = xstrdup(path);
684 if (ctx.qry.raw) { 694 if (ctx.qry.raw) {
685 qry = ctx.qry.raw; 695 qry = ctx.qry.raw;
686 ctx.qry.raw = xstrdup(fmt("%s?%s", path, qry)); 696 ctx.qry.raw = xstrdup(fmt("%s?%s", path, qry));
687 free(qry); 697 free(qry);
688 } else 698 } else
689 ctx.qry.raw = xstrdup(ctx.qry.url); 699 ctx.qry.raw = xstrdup(ctx.qry.url);
690 cgit_parse_url(ctx.qry.url); 700 cgit_parse_url(ctx.qry.url);
691 } 701 }
692 702
693 ttl = calc_ttl(); 703 ttl = calc_ttl();
694 ctx.page.expires += ttl*60; 704 ctx.page.expires += ttl*60;
695 if (ctx.env.request_method && !strcmp(ctx.env.request_method, "HEAD")) 705 if (ctx.env.request_method && !strcmp(ctx.env.request_method, "HEAD"))
696 ctx.cfg.nocache = 1; 706 ctx.cfg.nocache = 1;
697 if (ctx.cfg.nocache) 707 if (ctx.cfg.nocache)
698 ctx.cfg.cache_size = 0; 708 ctx.cfg.cache_size = 0;
699 err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root, 709 err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root,
700 ctx.qry.raw, ttl, process_request, &ctx); 710 ctx.qry.raw, ttl, process_request, &ctx);
701 if (err) 711 if (err)
702 cgit_print_error(fmt("Error processing page: %s (%d)", 712 cgit_print_error(fmt("Error processing page: %s (%d)",
703 strerror(err), err)); 713 strerror(err), err));
704 return err; 714 return err;
705} 715}