author | Johan Herland <johan@herland.net> | 2010-06-09 23:09:26 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2010-06-19 08:40:22 (UTC) |
commit | 0ff143df7043b7dd87c31c50fa875bc96d1a7779 (patch) (unidiff) | |
tree | d1625ba2aafed1ddfebc429921abdbb0d692042f /cgit.c | |
parent | 0e34c6d1ef32ea8f69019272fe72dbf2aeaba392 (diff) | |
download | cgit-0ff143df7043b7dd87c31c50fa875bc96d1a7779.zip cgit-0ff143df7043b7dd87c31c50fa875bc96d1a7779.tar.gz cgit-0ff143df7043b7dd87c31c50fa875bc96d1a7779.tar.bz2 |
struct cgit_cmd: Differentiate between various usages of ctx.qry.path
For many commands/pages (e.g. 'tree', 'diff', 'plain', etc.), the
ctx.qry.path argument is interpreted as a path within the "virtual" project
directory structure. However, for some other commands (notably 'refs', and
the clone-related commands) ctx.qry.path is used in a different context (as
a more or less "real" path within the '.git' directory).
This patch differentiates between these two usages of ctx.qry.path, by
introducing a new variable - ctx.qry.vpath - which is equal to ctx.qry.path
in the former case, and NULL in the latter.
This will become useful in future patches when we want various pages and the
links between them to preserve existing in-project paths.
Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | cgit.c | 6 |
1 files changed, 6 insertions, 0 deletions
@@ -299,256 +299,262 @@ static void prepare_context(struct cgit_context *ctx) | |||
299 | ctx->env.no_http = xstrdupn(getenv("NO_HTTP")); | 299 | ctx->env.no_http = xstrdupn(getenv("NO_HTTP")); |
300 | ctx->env.path_info = xstrdupn(getenv("PATH_INFO")); | 300 | ctx->env.path_info = xstrdupn(getenv("PATH_INFO")); |
301 | ctx->env.query_string = xstrdupn(getenv("QUERY_STRING")); | 301 | ctx->env.query_string = xstrdupn(getenv("QUERY_STRING")); |
302 | ctx->env.request_method = xstrdupn(getenv("REQUEST_METHOD")); | 302 | ctx->env.request_method = xstrdupn(getenv("REQUEST_METHOD")); |
303 | ctx->env.script_name = xstrdupn(getenv("SCRIPT_NAME")); | 303 | ctx->env.script_name = xstrdupn(getenv("SCRIPT_NAME")); |
304 | ctx->env.server_name = xstrdupn(getenv("SERVER_NAME")); | 304 | ctx->env.server_name = xstrdupn(getenv("SERVER_NAME")); |
305 | ctx->env.server_port = xstrdupn(getenv("SERVER_PORT")); | 305 | ctx->env.server_port = xstrdupn(getenv("SERVER_PORT")); |
306 | ctx->page.mimetype = "text/html"; | 306 | ctx->page.mimetype = "text/html"; |
307 | ctx->page.charset = PAGE_ENCODING; | 307 | ctx->page.charset = PAGE_ENCODING; |
308 | ctx->page.filename = NULL; | 308 | ctx->page.filename = NULL; |
309 | ctx->page.size = 0; | 309 | ctx->page.size = 0; |
310 | ctx->page.modified = time(NULL); | 310 | ctx->page.modified = time(NULL); |
311 | ctx->page.expires = ctx->page.modified; | 311 | ctx->page.expires = ctx->page.modified; |
312 | ctx->page.etag = NULL; | 312 | ctx->page.etag = NULL; |
313 | memset(&ctx->cfg.mimetypes, 0, sizeof(struct string_list)); | 313 | memset(&ctx->cfg.mimetypes, 0, sizeof(struct string_list)); |
314 | if (ctx->env.script_name) | 314 | if (ctx->env.script_name) |
315 | ctx->cfg.script_name = ctx->env.script_name; | 315 | ctx->cfg.script_name = ctx->env.script_name; |
316 | if (ctx->env.query_string) | 316 | if (ctx->env.query_string) |
317 | ctx->qry.raw = ctx->env.query_string; | 317 | ctx->qry.raw = ctx->env.query_string; |
318 | if (!ctx->env.cgit_config) | 318 | if (!ctx->env.cgit_config) |
319 | ctx->env.cgit_config = CGIT_CONFIG; | 319 | ctx->env.cgit_config = CGIT_CONFIG; |
320 | } | 320 | } |
321 | 321 | ||
322 | struct refmatch { | 322 | struct refmatch { |
323 | char *req_ref; | 323 | char *req_ref; |
324 | char *first_ref; | 324 | char *first_ref; |
325 | int match; | 325 | int match; |
326 | }; | 326 | }; |
327 | 327 | ||
328 | int find_current_ref(const char *refname, const unsigned char *sha1, | 328 | int find_current_ref(const char *refname, const unsigned char *sha1, |
329 | int flags, void *cb_data) | 329 | int flags, void *cb_data) |
330 | { | 330 | { |
331 | struct refmatch *info; | 331 | struct refmatch *info; |
332 | 332 | ||
333 | info = (struct refmatch *)cb_data; | 333 | info = (struct refmatch *)cb_data; |
334 | if (!strcmp(refname, info->req_ref)) | 334 | if (!strcmp(refname, info->req_ref)) |
335 | info->match = 1; | 335 | info->match = 1; |
336 | if (!info->first_ref) | 336 | if (!info->first_ref) |
337 | info->first_ref = xstrdup(refname); | 337 | info->first_ref = xstrdup(refname); |
338 | return info->match; | 338 | return info->match; |
339 | } | 339 | } |
340 | 340 | ||
341 | char *find_default_branch(struct cgit_repo *repo) | 341 | char *find_default_branch(struct cgit_repo *repo) |
342 | { | 342 | { |
343 | struct refmatch info; | 343 | struct refmatch info; |
344 | char *ref; | 344 | char *ref; |
345 | 345 | ||
346 | info.req_ref = repo->defbranch; | 346 | info.req_ref = repo->defbranch; |
347 | info.first_ref = NULL; | 347 | info.first_ref = NULL; |
348 | info.match = 0; | 348 | info.match = 0; |
349 | for_each_branch_ref(find_current_ref, &info); | 349 | for_each_branch_ref(find_current_ref, &info); |
350 | if (info.match) | 350 | if (info.match) |
351 | ref = info.req_ref; | 351 | ref = info.req_ref; |
352 | else | 352 | else |
353 | ref = info.first_ref; | 353 | ref = info.first_ref; |
354 | if (ref) | 354 | if (ref) |
355 | ref = xstrdup(ref); | 355 | ref = xstrdup(ref); |
356 | return ref; | 356 | return ref; |
357 | } | 357 | } |
358 | 358 | ||
359 | static int prepare_repo_cmd(struct cgit_context *ctx) | 359 | static int prepare_repo_cmd(struct cgit_context *ctx) |
360 | { | 360 | { |
361 | char *tmp; | 361 | char *tmp; |
362 | unsigned char sha1[20]; | 362 | unsigned char sha1[20]; |
363 | int nongit = 0; | 363 | int nongit = 0; |
364 | 364 | ||
365 | setenv("GIT_DIR", ctx->repo->path, 1); | 365 | setenv("GIT_DIR", ctx->repo->path, 1); |
366 | setup_git_directory_gently(&nongit); | 366 | setup_git_directory_gently(&nongit); |
367 | if (nongit) { | 367 | if (nongit) { |
368 | ctx->page.title = fmt("%s - %s", ctx->cfg.root_title, | 368 | ctx->page.title = fmt("%s - %s", ctx->cfg.root_title, |
369 | "config error"); | 369 | "config error"); |
370 | tmp = fmt("Not a git repository: '%s'", ctx->repo->path); | 370 | tmp = fmt("Not a git repository: '%s'", ctx->repo->path); |
371 | ctx->repo = NULL; | 371 | ctx->repo = NULL; |
372 | cgit_print_http_headers(ctx); | 372 | cgit_print_http_headers(ctx); |
373 | cgit_print_docstart(ctx); | 373 | cgit_print_docstart(ctx); |
374 | cgit_print_pageheader(ctx); | 374 | cgit_print_pageheader(ctx); |
375 | cgit_print_error(tmp); | 375 | cgit_print_error(tmp); |
376 | cgit_print_docend(); | 376 | cgit_print_docend(); |
377 | return 1; | 377 | return 1; |
378 | } | 378 | } |
379 | ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc); | 379 | ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc); |
380 | 380 | ||
381 | if (!ctx->qry.head) { | 381 | if (!ctx->qry.head) { |
382 | ctx->qry.nohead = 1; | 382 | ctx->qry.nohead = 1; |
383 | ctx->qry.head = find_default_branch(ctx->repo); | 383 | ctx->qry.head = find_default_branch(ctx->repo); |
384 | ctx->repo->defbranch = ctx->qry.head; | 384 | ctx->repo->defbranch = ctx->qry.head; |
385 | } | 385 | } |
386 | 386 | ||
387 | if (!ctx->qry.head) { | 387 | if (!ctx->qry.head) { |
388 | cgit_print_http_headers(ctx); | 388 | cgit_print_http_headers(ctx); |
389 | cgit_print_docstart(ctx); | 389 | cgit_print_docstart(ctx); |
390 | cgit_print_pageheader(ctx); | 390 | cgit_print_pageheader(ctx); |
391 | cgit_print_error("Repository seems to be empty"); | 391 | cgit_print_error("Repository seems to be empty"); |
392 | cgit_print_docend(); | 392 | cgit_print_docend(); |
393 | return 1; | 393 | return 1; |
394 | } | 394 | } |
395 | 395 | ||
396 | if (get_sha1(ctx->qry.head, sha1)) { | 396 | if (get_sha1(ctx->qry.head, sha1)) { |
397 | tmp = xstrdup(ctx->qry.head); | 397 | tmp = xstrdup(ctx->qry.head); |
398 | ctx->qry.head = ctx->repo->defbranch; | 398 | ctx->qry.head = ctx->repo->defbranch; |
399 | ctx->page.status = 404; | 399 | ctx->page.status = 404; |
400 | ctx->page.statusmsg = "not found"; | 400 | ctx->page.statusmsg = "not found"; |
401 | cgit_print_http_headers(ctx); | 401 | cgit_print_http_headers(ctx); |
402 | cgit_print_docstart(ctx); | 402 | cgit_print_docstart(ctx); |
403 | cgit_print_pageheader(ctx); | 403 | cgit_print_pageheader(ctx); |
404 | cgit_print_error(fmt("Invalid branch: %s", tmp)); | 404 | cgit_print_error(fmt("Invalid branch: %s", tmp)); |
405 | cgit_print_docend(); | 405 | cgit_print_docend(); |
406 | return 1; | 406 | return 1; |
407 | } | 407 | } |
408 | return 0; | 408 | return 0; |
409 | } | 409 | } |
410 | 410 | ||
411 | static void process_request(void *cbdata) | 411 | static void process_request(void *cbdata) |
412 | { | 412 | { |
413 | struct cgit_context *ctx = cbdata; | 413 | struct cgit_context *ctx = cbdata; |
414 | struct cgit_cmd *cmd; | 414 | struct cgit_cmd *cmd; |
415 | 415 | ||
416 | cmd = cgit_get_cmd(ctx); | 416 | cmd = cgit_get_cmd(ctx); |
417 | if (!cmd) { | 417 | if (!cmd) { |
418 | ctx->page.title = "cgit error"; | 418 | ctx->page.title = "cgit error"; |
419 | cgit_print_http_headers(ctx); | 419 | cgit_print_http_headers(ctx); |
420 | cgit_print_docstart(ctx); | 420 | cgit_print_docstart(ctx); |
421 | cgit_print_pageheader(ctx); | 421 | cgit_print_pageheader(ctx); |
422 | cgit_print_error("Invalid request"); | 422 | cgit_print_error("Invalid request"); |
423 | cgit_print_docend(); | 423 | cgit_print_docend(); |
424 | return; | 424 | return; |
425 | } | 425 | } |
426 | 426 | ||
427 | /* If cmd->want_vpath is set, assume ctx->qry.path contains a "virtual" | ||
428 | * in-project path limit to be made available at ctx->qry.vpath. | ||
429 | * Otherwise, no path limit is in effect (ctx->qry.vpath = NULL). | ||
430 | */ | ||
431 | ctx->qry.vpath = cmd->want_vpath ? ctx->qry.path : NULL; | ||
432 | |||
427 | if (cmd->want_repo && !ctx->repo) { | 433 | if (cmd->want_repo && !ctx->repo) { |
428 | cgit_print_http_headers(ctx); | 434 | cgit_print_http_headers(ctx); |
429 | cgit_print_docstart(ctx); | 435 | cgit_print_docstart(ctx); |
430 | cgit_print_pageheader(ctx); | 436 | cgit_print_pageheader(ctx); |
431 | cgit_print_error(fmt("No repository selected")); | 437 | cgit_print_error(fmt("No repository selected")); |
432 | cgit_print_docend(); | 438 | cgit_print_docend(); |
433 | return; | 439 | return; |
434 | } | 440 | } |
435 | 441 | ||
436 | if (ctx->repo && prepare_repo_cmd(ctx)) | 442 | if (ctx->repo && prepare_repo_cmd(ctx)) |
437 | return; | 443 | return; |
438 | 444 | ||
439 | if (cmd->want_layout) { | 445 | if (cmd->want_layout) { |
440 | cgit_print_http_headers(ctx); | 446 | cgit_print_http_headers(ctx); |
441 | cgit_print_docstart(ctx); | 447 | cgit_print_docstart(ctx); |
442 | cgit_print_pageheader(ctx); | 448 | cgit_print_pageheader(ctx); |
443 | } | 449 | } |
444 | 450 | ||
445 | cmd->fn(ctx); | 451 | cmd->fn(ctx); |
446 | 452 | ||
447 | if (cmd->want_layout) | 453 | if (cmd->want_layout) |
448 | cgit_print_docend(); | 454 | cgit_print_docend(); |
449 | } | 455 | } |
450 | 456 | ||
451 | int cmp_repos(const void *a, const void *b) | 457 | int cmp_repos(const void *a, const void *b) |
452 | { | 458 | { |
453 | const struct cgit_repo *ra = a, *rb = b; | 459 | const struct cgit_repo *ra = a, *rb = b; |
454 | return strcmp(ra->url, rb->url); | 460 | return strcmp(ra->url, rb->url); |
455 | } | 461 | } |
456 | 462 | ||
457 | char *build_snapshot_setting(int bitmap) | 463 | char *build_snapshot_setting(int bitmap) |
458 | { | 464 | { |
459 | const struct cgit_snapshot_format *f; | 465 | const struct cgit_snapshot_format *f; |
460 | char *result = xstrdup(""); | 466 | char *result = xstrdup(""); |
461 | char *tmp; | 467 | char *tmp; |
462 | int len; | 468 | int len; |
463 | 469 | ||
464 | for (f = cgit_snapshot_formats; f->suffix; f++) { | 470 | for (f = cgit_snapshot_formats; f->suffix; f++) { |
465 | if (f->bit & bitmap) { | 471 | if (f->bit & bitmap) { |
466 | tmp = result; | 472 | tmp = result; |
467 | result = xstrdup(fmt("%s%s ", tmp, f->suffix)); | 473 | result = xstrdup(fmt("%s%s ", tmp, f->suffix)); |
468 | free(tmp); | 474 | free(tmp); |
469 | } | 475 | } |
470 | } | 476 | } |
471 | len = strlen(result); | 477 | len = strlen(result); |
472 | if (len) | 478 | if (len) |
473 | result[len - 1] = '\0'; | 479 | result[len - 1] = '\0'; |
474 | return result; | 480 | return result; |
475 | } | 481 | } |
476 | 482 | ||
477 | char *get_first_line(char *txt) | 483 | char *get_first_line(char *txt) |
478 | { | 484 | { |
479 | char *t = xstrdup(txt); | 485 | char *t = xstrdup(txt); |
480 | char *p = strchr(t, '\n'); | 486 | char *p = strchr(t, '\n'); |
481 | if (p) | 487 | if (p) |
482 | *p = '\0'; | 488 | *p = '\0'; |
483 | return t; | 489 | return t; |
484 | } | 490 | } |
485 | 491 | ||
486 | void print_repo(FILE *f, struct cgit_repo *repo) | 492 | void print_repo(FILE *f, struct cgit_repo *repo) |
487 | { | 493 | { |
488 | fprintf(f, "repo.url=%s\n", repo->url); | 494 | fprintf(f, "repo.url=%s\n", repo->url); |
489 | fprintf(f, "repo.name=%s\n", repo->name); | 495 | fprintf(f, "repo.name=%s\n", repo->name); |
490 | fprintf(f, "repo.path=%s\n", repo->path); | 496 | fprintf(f, "repo.path=%s\n", repo->path); |
491 | if (repo->owner) | 497 | if (repo->owner) |
492 | fprintf(f, "repo.owner=%s\n", repo->owner); | 498 | fprintf(f, "repo.owner=%s\n", repo->owner); |
493 | if (repo->desc) { | 499 | if (repo->desc) { |
494 | char *tmp = get_first_line(repo->desc); | 500 | char *tmp = get_first_line(repo->desc); |
495 | fprintf(f, "repo.desc=%s\n", tmp); | 501 | fprintf(f, "repo.desc=%s\n", tmp); |
496 | free(tmp); | 502 | free(tmp); |
497 | } | 503 | } |
498 | if (repo->readme) | 504 | if (repo->readme) |
499 | fprintf(f, "repo.readme=%s\n", repo->readme); | 505 | fprintf(f, "repo.readme=%s\n", repo->readme); |
500 | if (repo->defbranch) | 506 | if (repo->defbranch) |
501 | fprintf(f, "repo.defbranch=%s\n", repo->defbranch); | 507 | fprintf(f, "repo.defbranch=%s\n", repo->defbranch); |
502 | if (repo->module_link) | 508 | if (repo->module_link) |
503 | fprintf(f, "repo.module-link=%s\n", repo->module_link); | 509 | fprintf(f, "repo.module-link=%s\n", repo->module_link); |
504 | if (repo->section) | 510 | if (repo->section) |
505 | fprintf(f, "repo.section=%s\n", repo->section); | 511 | fprintf(f, "repo.section=%s\n", repo->section); |
506 | if (repo->clone_url) | 512 | if (repo->clone_url) |
507 | fprintf(f, "repo.clone-url=%s\n", repo->clone_url); | 513 | fprintf(f, "repo.clone-url=%s\n", repo->clone_url); |
508 | fprintf(f, "repo.enable-log-filecount=%d\n", | 514 | fprintf(f, "repo.enable-log-filecount=%d\n", |
509 | repo->enable_log_filecount); | 515 | repo->enable_log_filecount); |
510 | fprintf(f, "repo.enable-log-linecount=%d\n", | 516 | fprintf(f, "repo.enable-log-linecount=%d\n", |
511 | repo->enable_log_linecount); | 517 | repo->enable_log_linecount); |
512 | if (repo->about_filter && repo->about_filter != ctx.cfg.about_filter) | 518 | if (repo->about_filter && repo->about_filter != ctx.cfg.about_filter) |
513 | fprintf(f, "repo.about-filter=%s\n", repo->about_filter->cmd); | 519 | fprintf(f, "repo.about-filter=%s\n", repo->about_filter->cmd); |
514 | if (repo->commit_filter && repo->commit_filter != ctx.cfg.commit_filter) | 520 | if (repo->commit_filter && repo->commit_filter != ctx.cfg.commit_filter) |
515 | fprintf(f, "repo.commit-filter=%s\n", repo->commit_filter->cmd); | 521 | fprintf(f, "repo.commit-filter=%s\n", repo->commit_filter->cmd); |
516 | if (repo->source_filter && repo->source_filter != ctx.cfg.source_filter) | 522 | if (repo->source_filter && repo->source_filter != ctx.cfg.source_filter) |
517 | fprintf(f, "repo.source-filter=%s\n", repo->source_filter->cmd); | 523 | fprintf(f, "repo.source-filter=%s\n", repo->source_filter->cmd); |
518 | if (repo->snapshots != ctx.cfg.snapshots) { | 524 | if (repo->snapshots != ctx.cfg.snapshots) { |
519 | char *tmp = build_snapshot_setting(repo->snapshots); | 525 | char *tmp = build_snapshot_setting(repo->snapshots); |
520 | fprintf(f, "repo.snapshots=%s\n", tmp); | 526 | fprintf(f, "repo.snapshots=%s\n", tmp); |
521 | free(tmp); | 527 | free(tmp); |
522 | } | 528 | } |
523 | if (repo->max_stats != ctx.cfg.max_stats) | 529 | if (repo->max_stats != ctx.cfg.max_stats) |
524 | fprintf(f, "repo.max-stats=%s\n", | 530 | fprintf(f, "repo.max-stats=%s\n", |
525 | cgit_find_stats_periodname(repo->max_stats)); | 531 | cgit_find_stats_periodname(repo->max_stats)); |
526 | fprintf(f, "\n"); | 532 | fprintf(f, "\n"); |
527 | } | 533 | } |
528 | 534 | ||
529 | void print_repolist(FILE *f, struct cgit_repolist *list, int start) | 535 | void print_repolist(FILE *f, struct cgit_repolist *list, int start) |
530 | { | 536 | { |
531 | int i; | 537 | int i; |
532 | 538 | ||
533 | for(i = start; i < list->count; i++) | 539 | for(i = start; i < list->count; i++) |
534 | print_repo(f, &list->repos[i]); | 540 | print_repo(f, &list->repos[i]); |
535 | } | 541 | } |
536 | 542 | ||
537 | /* Scan 'path' for git repositories, save the resulting repolist in 'cached_rc' | 543 | /* Scan 'path' for git repositories, save the resulting repolist in 'cached_rc' |
538 | * and return 0 on success. | 544 | * and return 0 on success. |
539 | */ | 545 | */ |
540 | static int generate_cached_repolist(const char *path, const char *cached_rc) | 546 | static int generate_cached_repolist(const char *path, const char *cached_rc) |
541 | { | 547 | { |
542 | char *locked_rc; | 548 | char *locked_rc; |
543 | int idx; | 549 | int idx; |
544 | FILE *f; | 550 | FILE *f; |
545 | 551 | ||
546 | locked_rc = xstrdup(fmt("%s.lock", cached_rc)); | 552 | locked_rc = xstrdup(fmt("%s.lock", cached_rc)); |
547 | f = fopen(locked_rc, "wx"); | 553 | f = fopen(locked_rc, "wx"); |
548 | if (!f) { | 554 | if (!f) { |
549 | /* Inform about the error unless the lockfile already existed, | 555 | /* Inform about the error unless the lockfile already existed, |
550 | * since that only means we've got concurrent requests. | 556 | * since that only means we've got concurrent requests. |
551 | */ | 557 | */ |
552 | if (errno != EEXIST) | 558 | if (errno != EEXIST) |
553 | fprintf(stderr, "[cgit] Error opening %s: %s (%d)\n", | 559 | fprintf(stderr, "[cgit] Error opening %s: %s (%d)\n", |
554 | locked_rc, strerror(errno), errno); | 560 | locked_rc, strerror(errno), errno); |