summaryrefslogtreecommitdiffabout
path: root/cgit.c
authorLars Hjemli <hjemli@gmail.com>2009-08-23 22:04:58 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2009-08-24 08:22:58 (UTC)
commit74061ed5f03e72796450aa3b8ca1cf6ced5d59e2 (patch) (unidiff)
tree235ab2c29c027f19b00da815af3bf1d2856edc21 /cgit.c
parenta1b3938f711c9b0e5eedad1678535e5779da82c1 (diff)
downloadcgit-74061ed5f03e72796450aa3b8ca1cf6ced5d59e2.zip
cgit-74061ed5f03e72796450aa3b8ca1cf6ced5d59e2.tar.gz
cgit-74061ed5f03e72796450aa3b8ca1cf6ced5d59e2.tar.bz2
Add support for repo-local cgitrc file
When recursively scanning a directory tree looking for git repositories, cgit will now parse cgitrc files found within such repositories. The repo-specific config files can include any repo-specific options except 'repo.url' and 'repo.path'. Also, in such config files the 'repo.' prefix can not be used, i.e. the valid options then becomes: * name * clone-url * desc * ower * defbranch * snapshots * enable-log-filecount * enable-log-linecount * max-stats * module-link * section * about-filter * commit-filter * source-filter * readme Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'cgit.c') (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/cgit.c b/cgit.c
index 90ae124..e281aa9 100644
--- a/cgit.c
+++ b/cgit.c
@@ -123,97 +123,97 @@ void config_cb(const char *name, const char *value)
123 } else if (!strcmp(name, "nocache")) 123 } else if (!strcmp(name, "nocache"))
124 ctx.cfg.nocache = atoi(value); 124 ctx.cfg.nocache = atoi(value);
125 else if (!strcmp(name, "noplainemail")) 125 else if (!strcmp(name, "noplainemail"))
126 ctx.cfg.noplainemail = atoi(value); 126 ctx.cfg.noplainemail = atoi(value);
127 else if (!strcmp(name, "noheader")) 127 else if (!strcmp(name, "noheader"))
128 ctx.cfg.noheader = atoi(value); 128 ctx.cfg.noheader = atoi(value);
129 else if (!strcmp(name, "snapshots")) 129 else if (!strcmp(name, "snapshots"))
130 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); 130 ctx.cfg.snapshots = cgit_parse_snapshots_mask(value);
131 else if (!strcmp(name, "enable-index-links")) 131 else if (!strcmp(name, "enable-index-links"))
132 ctx.cfg.enable_index_links = atoi(value); 132 ctx.cfg.enable_index_links = atoi(value);
133 else if (!strcmp(name, "enable-log-filecount")) 133 else if (!strcmp(name, "enable-log-filecount"))
134 ctx.cfg.enable_log_filecount = atoi(value); 134 ctx.cfg.enable_log_filecount = atoi(value);
135 else if (!strcmp(name, "enable-log-linecount")) 135 else if (!strcmp(name, "enable-log-linecount"))
136 ctx.cfg.enable_log_linecount = atoi(value); 136 ctx.cfg.enable_log_linecount = atoi(value);
137 else if (!strcmp(name, "max-stats")) 137 else if (!strcmp(name, "max-stats"))
138 ctx.cfg.max_stats = cgit_find_stats_period(value, NULL); 138 ctx.cfg.max_stats = cgit_find_stats_period(value, NULL);
139 else if (!strcmp(name, "cache-size")) 139 else if (!strcmp(name, "cache-size"))
140 ctx.cfg.cache_size = atoi(value); 140 ctx.cfg.cache_size = atoi(value);
141 else if (!strcmp(name, "cache-root")) 141 else if (!strcmp(name, "cache-root"))
142 ctx.cfg.cache_root = xstrdup(value); 142 ctx.cfg.cache_root = xstrdup(value);
143 else if (!strcmp(name, "cache-root-ttl")) 143 else if (!strcmp(name, "cache-root-ttl"))
144 ctx.cfg.cache_root_ttl = atoi(value); 144 ctx.cfg.cache_root_ttl = atoi(value);
145 else if (!strcmp(name, "cache-repo-ttl")) 145 else if (!strcmp(name, "cache-repo-ttl"))
146 ctx.cfg.cache_repo_ttl = atoi(value); 146 ctx.cfg.cache_repo_ttl = atoi(value);
147 else if (!strcmp(name, "cache-scanrc-ttl")) 147 else if (!strcmp(name, "cache-scanrc-ttl"))
148 ctx.cfg.cache_scanrc_ttl = atoi(value); 148 ctx.cfg.cache_scanrc_ttl = atoi(value);
149 else if (!strcmp(name, "cache-static-ttl")) 149 else if (!strcmp(name, "cache-static-ttl"))
150 ctx.cfg.cache_static_ttl = atoi(value); 150 ctx.cfg.cache_static_ttl = atoi(value);
151 else if (!strcmp(name, "cache-dynamic-ttl")) 151 else if (!strcmp(name, "cache-dynamic-ttl"))
152 ctx.cfg.cache_dynamic_ttl = atoi(value); 152 ctx.cfg.cache_dynamic_ttl = atoi(value);
153 else if (!strcmp(name, "about-filter")) 153 else if (!strcmp(name, "about-filter"))
154 ctx.cfg.about_filter = new_filter(value, 0); 154 ctx.cfg.about_filter = new_filter(value, 0);
155 else if (!strcmp(name, "commit-filter")) 155 else if (!strcmp(name, "commit-filter"))
156 ctx.cfg.commit_filter = new_filter(value, 0); 156 ctx.cfg.commit_filter = new_filter(value, 0);
157 else if (!strcmp(name, "embedded")) 157 else if (!strcmp(name, "embedded"))
158 ctx.cfg.embedded = atoi(value); 158 ctx.cfg.embedded = atoi(value);
159 else if (!strcmp(name, "max-message-length")) 159 else if (!strcmp(name, "max-message-length"))
160 ctx.cfg.max_msg_len = atoi(value); 160 ctx.cfg.max_msg_len = atoi(value);
161 else if (!strcmp(name, "max-repodesc-length")) 161 else if (!strcmp(name, "max-repodesc-length"))
162 ctx.cfg.max_repodesc_len = atoi(value); 162 ctx.cfg.max_repodesc_len = atoi(value);
163 else if (!strcmp(name, "max-repo-count")) 163 else if (!strcmp(name, "max-repo-count"))
164 ctx.cfg.max_repo_count = atoi(value); 164 ctx.cfg.max_repo_count = atoi(value);
165 else if (!strcmp(name, "max-commit-count")) 165 else if (!strcmp(name, "max-commit-count"))
166 ctx.cfg.max_commit_count = atoi(value); 166 ctx.cfg.max_commit_count = atoi(value);
167 else if (!strcmp(name, "scan-path")) 167 else if (!strcmp(name, "scan-path"))
168 if (!ctx.cfg.nocache && ctx.cfg.cache_size) 168 if (!ctx.cfg.nocache && ctx.cfg.cache_size)
169 process_cached_repolist(value); 169 process_cached_repolist(value);
170 else 170 else
171 scan_tree(value); 171 scan_tree(value, repo_config);
172 else if (!strcmp(name, "source-filter")) 172 else if (!strcmp(name, "source-filter"))
173 ctx.cfg.source_filter = new_filter(value, 1); 173 ctx.cfg.source_filter = new_filter(value, 1);
174 else if (!strcmp(name, "summary-log")) 174 else if (!strcmp(name, "summary-log"))
175 ctx.cfg.summary_log = atoi(value); 175 ctx.cfg.summary_log = atoi(value);
176 else if (!strcmp(name, "summary-branches")) 176 else if (!strcmp(name, "summary-branches"))
177 ctx.cfg.summary_branches = atoi(value); 177 ctx.cfg.summary_branches = atoi(value);
178 else if (!strcmp(name, "summary-tags")) 178 else if (!strcmp(name, "summary-tags"))
179 ctx.cfg.summary_tags = atoi(value); 179 ctx.cfg.summary_tags = atoi(value);
180 else if (!strcmp(name, "agefile")) 180 else if (!strcmp(name, "agefile"))
181 ctx.cfg.agefile = xstrdup(value); 181 ctx.cfg.agefile = xstrdup(value);
182 else if (!strcmp(name, "renamelimit")) 182 else if (!strcmp(name, "renamelimit"))
183 ctx.cfg.renamelimit = atoi(value); 183 ctx.cfg.renamelimit = atoi(value);
184 else if (!strcmp(name, "robots")) 184 else if (!strcmp(name, "robots"))
185 ctx.cfg.robots = xstrdup(value); 185 ctx.cfg.robots = xstrdup(value);
186 else if (!strcmp(name, "clone-prefix")) 186 else if (!strcmp(name, "clone-prefix"))
187 ctx.cfg.clone_prefix = xstrdup(value); 187 ctx.cfg.clone_prefix = xstrdup(value);
188 else if (!strcmp(name, "local-time")) 188 else if (!strcmp(name, "local-time"))
189 ctx.cfg.local_time = atoi(value); 189 ctx.cfg.local_time = atoi(value);
190 else if (!prefixcmp(name, "mimetype.")) 190 else if (!prefixcmp(name, "mimetype."))
191 add_mimetype(name + 9, value); 191 add_mimetype(name + 9, value);
192 else if (!strcmp(name, "include")) 192 else if (!strcmp(name, "include"))
193 parse_configfile(value, config_cb); 193 parse_configfile(value, config_cb);
194} 194}
195 195
196static void querystring_cb(const char *name, const char *value) 196static void querystring_cb(const char *name, const char *value)
197{ 197{
198 if (!value) 198 if (!value)
199 value = ""; 199 value = "";
200 200
201 if (!strcmp(name,"r")) { 201 if (!strcmp(name,"r")) {
202 ctx.qry.repo = xstrdup(value); 202 ctx.qry.repo = xstrdup(value);
203 ctx.repo = cgit_get_repoinfo(value); 203 ctx.repo = cgit_get_repoinfo(value);
204 } else if (!strcmp(name, "p")) { 204 } else if (!strcmp(name, "p")) {
205 ctx.qry.page = xstrdup(value); 205 ctx.qry.page = xstrdup(value);
206 } else if (!strcmp(name, "url")) { 206 } else if (!strcmp(name, "url")) {
207 ctx.qry.url = xstrdup(value); 207 ctx.qry.url = xstrdup(value);
208 cgit_parse_url(value); 208 cgit_parse_url(value);
209 } else if (!strcmp(name, "qt")) { 209 } else if (!strcmp(name, "qt")) {
210 ctx.qry.grep = xstrdup(value); 210 ctx.qry.grep = xstrdup(value);
211 } else if (!strcmp(name, "q")) { 211 } else if (!strcmp(name, "q")) {
212 ctx.qry.search = xstrdup(value); 212 ctx.qry.search = xstrdup(value);
213 } else if (!strcmp(name, "h")) { 213 } else if (!strcmp(name, "h")) {
214 ctx.qry.head = xstrdup(value); 214 ctx.qry.head = xstrdup(value);
215 ctx.qry.has_symref = 1; 215 ctx.qry.has_symref = 1;
216 } else if (!strcmp(name, "id")) { 216 } else if (!strcmp(name, "id")) {
217 ctx.qry.sha1 = xstrdup(value); 217 ctx.qry.sha1 = xstrdup(value);
218 ctx.qry.has_sha1 = 1; 218 ctx.qry.has_sha1 = 1;
219 } else if (!strcmp(name, "id2")) { 219 } else if (!strcmp(name, "id2")) {
@@ -431,180 +431,180 @@ int cmp_repos(const void *a, const void *b)
431{ 431{
432 const struct cgit_repo *ra = a, *rb = b; 432 const struct cgit_repo *ra = a, *rb = b;
433 return strcmp(ra->url, rb->url); 433 return strcmp(ra->url, rb->url);
434} 434}
435 435
436void print_repo(FILE *f, struct cgit_repo *repo) 436void print_repo(FILE *f, struct cgit_repo *repo)
437{ 437{
438 fprintf(f, "repo.url=%s\n", repo->url); 438 fprintf(f, "repo.url=%s\n", repo->url);
439 fprintf(f, "repo.name=%s\n", repo->name); 439 fprintf(f, "repo.name=%s\n", repo->name);
440 fprintf(f, "repo.path=%s\n", repo->path); 440 fprintf(f, "repo.path=%s\n", repo->path);
441 if (repo->owner) 441 if (repo->owner)
442 fprintf(f, "repo.owner=%s\n", repo->owner); 442 fprintf(f, "repo.owner=%s\n", repo->owner);
443 if (repo->desc) 443 if (repo->desc)
444 fprintf(f, "repo.desc=%s\n", repo->desc); 444 fprintf(f, "repo.desc=%s\n", repo->desc);
445 if (repo->readme) 445 if (repo->readme)
446 fprintf(f, "repo.readme=%s\n", repo->readme); 446 fprintf(f, "repo.readme=%s\n", repo->readme);
447 fprintf(f, "\n"); 447 fprintf(f, "\n");
448} 448}
449 449
450void print_repolist(FILE *f, struct cgit_repolist *list, int start) 450void print_repolist(FILE *f, struct cgit_repolist *list, int start)
451{ 451{
452 int i; 452 int i;
453 453
454 for(i = start; i < list->count; i++) 454 for(i = start; i < list->count; i++)
455 print_repo(f, &list->repos[i]); 455 print_repo(f, &list->repos[i]);
456} 456}
457 457
458/* Scan 'path' for git repositories, save the resulting repolist in 'cached_rc' 458/* Scan 'path' for git repositories, save the resulting repolist in 'cached_rc'
459 * and return 0 on success. 459 * and return 0 on success.
460 */ 460 */
461static int generate_cached_repolist(const char *path, const char *cached_rc) 461static int generate_cached_repolist(const char *path, const char *cached_rc)
462{ 462{
463 char *locked_rc; 463 char *locked_rc;
464 int idx; 464 int idx;
465 FILE *f; 465 FILE *f;
466 466
467 locked_rc = xstrdup(fmt("%s.lock", cached_rc)); 467 locked_rc = xstrdup(fmt("%s.lock", cached_rc));
468 f = fopen(locked_rc, "wx"); 468 f = fopen(locked_rc, "wx");
469 if (!f) { 469 if (!f) {
470 /* Inform about the error unless the lockfile already existed, 470 /* Inform about the error unless the lockfile already existed,
471 * since that only means we've got concurrent requests. 471 * since that only means we've got concurrent requests.
472 */ 472 */
473 if (errno != EEXIST) 473 if (errno != EEXIST)
474 fprintf(stderr, "[cgit] Error opening %s: %s (%d)\n", 474 fprintf(stderr, "[cgit] Error opening %s: %s (%d)\n",
475 locked_rc, strerror(errno), errno); 475 locked_rc, strerror(errno), errno);
476 return errno; 476 return errno;
477 } 477 }
478 idx = cgit_repolist.count; 478 idx = cgit_repolist.count;
479 scan_tree(path); 479 scan_tree(path, repo_config);
480 print_repolist(f, &cgit_repolist, idx); 480 print_repolist(f, &cgit_repolist, idx);
481 if (rename(locked_rc, cached_rc)) 481 if (rename(locked_rc, cached_rc))
482 fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n", 482 fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n",
483 locked_rc, cached_rc, strerror(errno), errno); 483 locked_rc, cached_rc, strerror(errno), errno);
484 fclose(f); 484 fclose(f);
485 return 0; 485 return 0;
486} 486}
487 487
488static void process_cached_repolist(const char *path) 488static void process_cached_repolist(const char *path)
489{ 489{
490 struct stat st; 490 struct stat st;
491 char *cached_rc; 491 char *cached_rc;
492 time_t age; 492 time_t age;
493 493
494 cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root, 494 cached_rc = xstrdup(fmt("%s/rc-%8x", ctx.cfg.cache_root,
495 hash_str(path))); 495 hash_str(path)));
496 496
497 if (stat(cached_rc, &st)) { 497 if (stat(cached_rc, &st)) {
498 /* Nothing is cached, we need to scan without forking. And 498 /* Nothing is cached, we need to scan without forking. And
499 * if we fail to generate a cached repolist, we need to 499 * if we fail to generate a cached repolist, we need to
500 * invoke scan_tree manually. 500 * invoke scan_tree manually.
501 */ 501 */
502 if (generate_cached_repolist(path, cached_rc)) 502 if (generate_cached_repolist(path, cached_rc))
503 scan_tree(path); 503 scan_tree(path, repo_config);
504 return; 504 return;
505 } 505 }
506 506
507 parse_configfile(cached_rc, config_cb); 507 parse_configfile(cached_rc, config_cb);
508 508
509 /* If the cached configfile hasn't expired, lets exit now */ 509 /* If the cached configfile hasn't expired, lets exit now */
510 age = time(NULL) - st.st_mtime; 510 age = time(NULL) - st.st_mtime;
511 if (age <= (ctx.cfg.cache_scanrc_ttl * 60)) 511 if (age <= (ctx.cfg.cache_scanrc_ttl * 60))
512 return; 512 return;
513 513
514 /* The cached repolist has been parsed, but it was old. So lets 514 /* The cached repolist has been parsed, but it was old. So lets
515 * rescan the specified path and generate a new cached repolist 515 * rescan the specified path and generate a new cached repolist
516 * in a child-process to avoid latency for the current request. 516 * in a child-process to avoid latency for the current request.
517 */ 517 */
518 if (fork()) 518 if (fork())
519 return; 519 return;
520 520
521 exit(generate_cached_repolist(path, cached_rc)); 521 exit(generate_cached_repolist(path, cached_rc));
522} 522}
523 523
524static void cgit_parse_args(int argc, const char **argv) 524static void cgit_parse_args(int argc, const char **argv)
525{ 525{
526 int i; 526 int i;
527 int scan = 0; 527 int scan = 0;
528 528
529 for (i = 1; i < argc; i++) { 529 for (i = 1; i < argc; i++) {
530 if (!strncmp(argv[i], "--cache=", 8)) { 530 if (!strncmp(argv[i], "--cache=", 8)) {
531 ctx.cfg.cache_root = xstrdup(argv[i]+8); 531 ctx.cfg.cache_root = xstrdup(argv[i]+8);
532 } 532 }
533 if (!strcmp(argv[i], "--nocache")) { 533 if (!strcmp(argv[i], "--nocache")) {
534 ctx.cfg.nocache = 1; 534 ctx.cfg.nocache = 1;
535 } 535 }
536 if (!strcmp(argv[i], "--nohttp")) { 536 if (!strcmp(argv[i], "--nohttp")) {
537 ctx.env.no_http = "1"; 537 ctx.env.no_http = "1";
538 } 538 }
539 if (!strncmp(argv[i], "--query=", 8)) { 539 if (!strncmp(argv[i], "--query=", 8)) {
540 ctx.qry.raw = xstrdup(argv[i]+8); 540 ctx.qry.raw = xstrdup(argv[i]+8);
541 } 541 }
542 if (!strncmp(argv[i], "--repo=", 7)) { 542 if (!strncmp(argv[i], "--repo=", 7)) {
543 ctx.qry.repo = xstrdup(argv[i]+7); 543 ctx.qry.repo = xstrdup(argv[i]+7);
544 } 544 }
545 if (!strncmp(argv[i], "--page=", 7)) { 545 if (!strncmp(argv[i], "--page=", 7)) {
546 ctx.qry.page = xstrdup(argv[i]+7); 546 ctx.qry.page = xstrdup(argv[i]+7);
547 } 547 }
548 if (!strncmp(argv[i], "--head=", 7)) { 548 if (!strncmp(argv[i], "--head=", 7)) {
549 ctx.qry.head = xstrdup(argv[i]+7); 549 ctx.qry.head = xstrdup(argv[i]+7);
550 ctx.qry.has_symref = 1; 550 ctx.qry.has_symref = 1;
551 } 551 }
552 if (!strncmp(argv[i], "--sha1=", 7)) { 552 if (!strncmp(argv[i], "--sha1=", 7)) {
553 ctx.qry.sha1 = xstrdup(argv[i]+7); 553 ctx.qry.sha1 = xstrdup(argv[i]+7);
554 ctx.qry.has_sha1 = 1; 554 ctx.qry.has_sha1 = 1;
555 } 555 }
556 if (!strncmp(argv[i], "--ofs=", 6)) { 556 if (!strncmp(argv[i], "--ofs=", 6)) {
557 ctx.qry.ofs = atoi(argv[i]+6); 557 ctx.qry.ofs = atoi(argv[i]+6);
558 } 558 }
559 if (!strncmp(argv[i], "--scan-tree=", 12) || 559 if (!strncmp(argv[i], "--scan-tree=", 12) ||
560 !strncmp(argv[i], "--scan-path=", 12)) { 560 !strncmp(argv[i], "--scan-path=", 12)) {
561 scan++; 561 scan++;
562 scan_tree(argv[i] + 12); 562 scan_tree(argv[i] + 12, repo_config);
563 } 563 }
564 } 564 }
565 if (scan) { 565 if (scan) {
566 qsort(cgit_repolist.repos, cgit_repolist.count, 566 qsort(cgit_repolist.repos, cgit_repolist.count,
567 sizeof(struct cgit_repo), cmp_repos); 567 sizeof(struct cgit_repo), cmp_repos);
568 print_repolist(stdout, &cgit_repolist, 0); 568 print_repolist(stdout, &cgit_repolist, 0);
569 exit(0); 569 exit(0);
570 } 570 }
571} 571}
572 572
573static int calc_ttl() 573static int calc_ttl()
574{ 574{
575 if (!ctx.repo) 575 if (!ctx.repo)
576 return ctx.cfg.cache_root_ttl; 576 return ctx.cfg.cache_root_ttl;
577 577
578 if (!ctx.qry.page) 578 if (!ctx.qry.page)
579 return ctx.cfg.cache_repo_ttl; 579 return ctx.cfg.cache_repo_ttl;
580 580
581 if (ctx.qry.has_symref) 581 if (ctx.qry.has_symref)
582 return ctx.cfg.cache_dynamic_ttl; 582 return ctx.cfg.cache_dynamic_ttl;
583 583
584 if (ctx.qry.has_sha1) 584 if (ctx.qry.has_sha1)
585 return ctx.cfg.cache_static_ttl; 585 return ctx.cfg.cache_static_ttl;
586 586
587 return ctx.cfg.cache_repo_ttl; 587 return ctx.cfg.cache_repo_ttl;
588} 588}
589 589
590int main(int argc, const char **argv) 590int main(int argc, const char **argv)
591{ 591{
592 const char *path; 592 const char *path;
593 char *qry; 593 char *qry;
594 int err, ttl; 594 int err, ttl;
595 595
596 prepare_context(&ctx); 596 prepare_context(&ctx);
597 cgit_repolist.length = 0; 597 cgit_repolist.length = 0;
598 cgit_repolist.count = 0; 598 cgit_repolist.count = 0;
599 cgit_repolist.repos = NULL; 599 cgit_repolist.repos = NULL;
600 600
601 cgit_parse_args(argc, argv); 601 cgit_parse_args(argc, argv);
602 parse_configfile(ctx.env.cgit_config, config_cb); 602 parse_configfile(ctx.env.cgit_config, config_cb);
603 ctx.repo = NULL; 603 ctx.repo = NULL;
604 http_parse_querystring(ctx.qry.raw, querystring_cb); 604 http_parse_querystring(ctx.qry.raw, querystring_cb);
605 605
606 /* If virtual-root isn't specified in cgitrc, lets pretend 606 /* If virtual-root isn't specified in cgitrc, lets pretend
607 * that virtual-root equals SCRIPT_NAME. 607 * that virtual-root equals SCRIPT_NAME.
608 */ 608 */
609 if (!ctx.cfg.virtual_root) 609 if (!ctx.cfg.virtual_root)
610 ctx.cfg.virtual_root = ctx.cfg.script_name; 610 ctx.cfg.virtual_root = ctx.cfg.script_name;