diff options
| author | 2013-05-26 22:20:02 (JST) | |
|---|---|---|
| committer | 2013-05-26 23:30:03 (JST) | |
| commit | dcbc0438b2543a733858d62170f3110a89edbed6 (patch) | |
| tree | bdacfe4546c88bf6b03860ea69a0cad885fa6af4 | |
| parent | fe36f84d843cd755c6dab629a0758264de5bcc00 (diff) | |
| download | cgit-dcbc0438b2543a733858d62170f3110a89edbed6.zip cgit-dcbc0438b2543a733858d62170f3110a89edbed6.tar.gz | |
readme: use string_list instead of space deliminations
Now this is possible in cgitrc -
readme=:README.md
readme=:readme.md
readme=:README.mkd
readme=:readme.mkd
readme=:README.rst
readme=:readme.rst
readme=:README.html
readme=:readme.html
readme=:README.htm
readme=:readme.htm
readme=:README.txt
readme=:readme.txt
readme=:README
readme=:readme
readme=:INSTALL.txt
readme=:install.txt
readme=:INSTALL
readme=:install
Suggested-by: John Keeping <john@keeping.me.uk>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
| -rw-r--r-- | cgit.c | 92 | ||||
| -rw-r--r-- | cgit.h | 4 | ||||
| -rw-r--r-- | cgitrc.5.txt | 5 | ||||
| -rw-r--r-- | cmd.c | 3 | ||||
| -rw-r--r-- | scan-tree.c | 8 | ||||
| -rw-r--r-- | ui-blob.c | 61 | ||||
| -rw-r--r-- | ui-blob.h | 6 | ||||
| -rw-r--r-- | ui-shared.c | 2 | ||||
| -rw-r--r-- | ui-summary.c | 100 | ||||
| -rw-r--r-- | ui-summary.h | 1 |
10 files changed, 160 insertions, 122 deletions
| @@ -1,7 +1,7 @@ | |||
| 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 | * Copyright (C) 2010, 2012 Jason A. Donenfeld <Jason@zx2c4.com> | 4 | * Copyright (C) 2010-2013 Jason A. Donenfeld <Jason@zx2c4.com> |
| 5 | * | 5 | * |
| 6 | * Licensed under GNU General Public License v2 | 6 | * Licensed under GNU General Public License v2 |
| 7 | * (see COPYING for full license text) | 7 | * (see COPYING for full license text) |
| @@ -101,13 +101,15 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va | |||
| 101 | else if (!strcmp(name, "module-link")) | 101 | else if (!strcmp(name, "module-link")) |
| 102 | repo->module_link= xstrdup(value); | 102 | repo->module_link= xstrdup(value); |
| 103 | else if (!prefixcmp(name, "module-link.")) { | 103 | else if (!prefixcmp(name, "module-link.")) { |
| 104 | item = string_list_append(&repo->submodules, name + 12); | 104 | item = string_list_append(&repo->submodules, xstrdup(name + 12)); |
| 105 | item->util = xstrdup(value); | 105 | item->util = xstrdup(value); |
| 106 | } else if (!strcmp(name, "section")) | 106 | } else if (!strcmp(name, "section")) |
| 107 | repo->section = xstrdup(value); | 107 | repo->section = xstrdup(value); |
| 108 | else if (!strcmp(name, "readme") && value != NULL) | 108 | else if (!strcmp(name, "readme") && value != NULL) { |
| 109 | repo->readme = xstrdup(value); | 109 | if (repo->readme.items == ctx.cfg.readme.items) |
| 110 | else if (!strcmp(name, "logo") && value != NULL) | 110 | memset(&repo->readme, 0, sizeof(repo->readme)); |
| 111 | string_list_append(&repo->readme, xstrdup(value)); | ||
| 112 | } else if (!strcmp(name, "logo") && value != NULL) | ||
| 111 | repo->logo = xstrdup(value); | 113 | repo->logo = xstrdup(value); |
| 112 | else if (!strcmp(name, "logo-link") && value != NULL) | 114 | else if (!strcmp(name, "logo-link") && value != NULL) |
| 113 | repo->logo_link = xstrdup(value); | 115 | repo->logo_link = xstrdup(value); |
| @@ -131,8 +133,8 @@ static void config_cb(const char *name, const char *value) | |||
| 131 | ctx.repo->path = trim_end(value, '/'); | 133 | ctx.repo->path = trim_end(value, '/'); |
| 132 | else if (ctx.repo && !prefixcmp(name, "repo.")) | 134 | else if (ctx.repo && !prefixcmp(name, "repo.")) |
| 133 | repo_config(ctx.repo, name + 5, value); | 135 | repo_config(ctx.repo, name + 5, value); |
| 134 | else if (!strcmp(name, "readme")) | 136 | else if (!strcmp(name, "readme") && value != NULL) |
| 135 | ctx.cfg.readme = xstrdup(value); | 137 | string_list_append(&ctx.cfg.readme, xstrdup(value)); |
| 136 | else if (!strcmp(name, "root-title")) | 138 | else if (!strcmp(name, "root-title")) |
| 137 | ctx.cfg.root_title = xstrdup(value); | 139 | ctx.cfg.root_title = xstrdup(value); |
| 138 | else if (!strcmp(name, "root-desc")) | 140 | else if (!strcmp(name, "root-desc")) |
| @@ -470,37 +472,76 @@ static char *guess_defbranch(void) | |||
| 470 | return "master"; | 472 | return "master"; |
| 471 | return xstrdup(ref + 11); | 473 | return xstrdup(ref + 11); |
| 472 | } | 474 | } |
| 475 | /* The caller must free filename and ref after calling this. */ | ||
| 476 | static inline void parse_readme(const char *readme, char **filename, char **ref, struct cgit_repo *repo) | ||
| 477 | { | ||
| 478 | const char *colon; | ||
| 479 | |||
| 480 | *filename = NULL; | ||
| 481 | *ref = NULL; | ||
| 482 | |||
| 483 | if (!readme || !readme[0]) | ||
| 484 | return; | ||
| 473 | 485 | ||
| 486 | /* Check if the readme is tracked in the git repo. */ | ||
| 487 | colon = strchr(readme, ':'); | ||
| 488 | if (colon && strlen(colon) > 1) { | ||
| 489 | /* If it starts with a colon, we want to use | ||
| 490 | * the default branch */ | ||
| 491 | if (colon == readme && repo->defbranch) | ||
| 492 | *ref = xstrdup(repo->defbranch); | ||
| 493 | else | ||
| 494 | *ref = xstrndup(readme, colon - readme); | ||
| 495 | readme = colon + 1; | ||
| 496 | } | ||
| 497 | |||
| 498 | /* Prepend repo path to relative readme path unless tracked. */ | ||
| 499 | if (!(*ref) && readme[0] != '/') | ||
| 500 | *filename = fmtalloc("%s/%s", repo->path, readme); | ||
| 501 | else | ||
| 502 | *filename = xstrdup(readme); | ||
| 503 | } | ||
| 474 | static void choose_readme(struct cgit_repo *repo) | 504 | static void choose_readme(struct cgit_repo *repo) |
| 475 | { | 505 | { |
| 476 | char *entry, *filename, *ref; | 506 | int found; |
| 507 | char *filename, *ref; | ||
| 508 | struct string_list_item *entry; | ||
| 477 | 509 | ||
| 478 | /* If there's no space, we skip the possibly expensive | 510 | if (!repo->readme.nr) |
| 479 | * selection process. */ | ||
| 480 | if (!repo->readme || !strchr(repo->readme, ' ')) | ||
| 481 | return; | 511 | return; |
| 482 | 512 | ||
| 483 | for (entry = strtok(repo->readme, " "); entry; entry = strtok(NULL, " ")) { | 513 | found = 0; |
| 484 | cgit_parse_readme(entry, NULL, &filename, &ref, repo); | 514 | for_each_string_list_item(entry, &repo->readme) { |
| 485 | if (!(*filename)) { | 515 | parse_readme(entry->string, &filename, &ref, repo); |
| 516 | if (!filename) { | ||
| 486 | free(filename); | 517 | free(filename); |
| 487 | free(ref); | 518 | free(ref); |
| 488 | continue; | 519 | continue; |
| 489 | } | 520 | } |
| 490 | if (*ref && cgit_ref_path_exists(filename, ref)) { | 521 | /* If there's only one item, we skip the possibly expensive |
| 491 | free(filename); | 522 | * selection process. */ |
| 492 | free(ref); | 523 | if (repo->readme.nr == 1) { |
| 524 | found = 1; | ||
| 493 | break; | 525 | break; |
| 494 | } | 526 | } |
| 495 | if (!access(filename, R_OK)) { | 527 | if (ref) { |
| 496 | free(filename); | 528 | if (cgit_ref_path_exists(filename, ref, 1)) { |
| 497 | free(ref); | 529 | found = 1; |
| 530 | break; | ||
| 531 | } | ||
| 532 | } | ||
| 533 | else if (!access(filename, R_OK)) { | ||
| 534 | found = 1; | ||
| 498 | break; | 535 | break; |
| 499 | } | 536 | } |
| 500 | free(filename); | 537 | free(filename); |
| 501 | free(ref); | 538 | free(ref); |
| 502 | } | 539 | } |
| 503 | repo->readme = entry; | 540 | repo->readme.strdup_strings = 1; |
| 541 | string_list_clear(&repo->readme, 0); | ||
| 542 | repo->readme.strdup_strings = 0; | ||
| 543 | if (found) | ||
| 544 | string_list_append(&repo->readme, filename)->util = ref; | ||
| 504 | } | 545 | } |
| 505 | 546 | ||
| 506 | static int prepare_repo_cmd(struct cgit_context *ctx) | 547 | static int prepare_repo_cmd(struct cgit_context *ctx) |
| @@ -660,6 +701,7 @@ static char *get_first_line(char *txt) | |||
| 660 | 701 | ||
| 661 | static void print_repo(FILE *f, struct cgit_repo *repo) | 702 | static void print_repo(FILE *f, struct cgit_repo *repo) |
| 662 | { | 703 | { |
| 704 | struct string_list_item *item; | ||
| 663 | fprintf(f, "repo.url=%s\n", repo->url); | 705 | fprintf(f, "repo.url=%s\n", repo->url); |
| 664 | fprintf(f, "repo.name=%s\n", repo->name); | 706 | fprintf(f, "repo.name=%s\n", repo->name); |
| 665 | fprintf(f, "repo.path=%s\n", repo->path); | 707 | fprintf(f, "repo.path=%s\n", repo->path); |
| @@ -670,8 +712,12 @@ static void print_repo(FILE *f, struct cgit_repo *repo) | |||
| 670 | fprintf(f, "repo.desc=%s\n", tmp); | 712 | fprintf(f, "repo.desc=%s\n", tmp); |
| 671 | free(tmp); | 713 | free(tmp); |
| 672 | } | 714 | } |
| 673 | if (repo->readme) | 715 | for_each_string_list_item(item, &repo->readme) { |
| 674 | fprintf(f, "repo.readme=%s\n", repo->readme); | 716 | if (item->util) |
| 717 | fprintf(f, "repo.readme=%s:%s\n", (char *)item->util, item->string); | ||
| 718 | else | ||
| 719 | fprintf(f, "repo.readme=%s\n", item->string); | ||
| 720 | } | ||
| 675 | if (repo->defbranch) | 721 | if (repo->defbranch) |
| 676 | fprintf(f, "repo.defbranch=%s\n", repo->defbranch); | 722 | fprintf(f, "repo.defbranch=%s\n", repo->defbranch); |
| 677 | if (repo->module_link) | 723 | if (repo->module_link) |
| @@ -73,7 +73,7 @@ struct cgit_repo { | |||
| 73 | char *owner; | 73 | char *owner; |
| 74 | char *defbranch; | 74 | char *defbranch; |
| 75 | char *module_link; | 75 | char *module_link; |
| 76 | char *readme; | 76 | struct string_list readme; |
| 77 | char *section; | 77 | char *section; |
| 78 | char *clone_url; | 78 | char *clone_url; |
| 79 | char *logo; | 79 | char *logo; |
| @@ -183,7 +183,7 @@ struct cgit_config { | |||
| 183 | char *mimetype_file; | 183 | char *mimetype_file; |
| 184 | char *module_link; | 184 | char *module_link; |
| 185 | char *project_list; | 185 | char *project_list; |
| 186 | char *readme; | 186 | struct string_list readme; |
| 187 | char *robots; | 187 | char *robots; |
| 188 | char *root_title; | 188 | char *root_title; |
| 189 | char *root_desc; | 189 | char *root_desc; |
diff --git a/cgitrc.5.txt b/cgitrc.5.txt index 12a843b..6437ef4 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt | |||
| @@ -290,8 +290,9 @@ project-list:: | |||
| 290 | 290 | ||
| 291 | readme:: | 291 | readme:: |
| 292 | Text which will be used as default value for "repo.readme". Multiple | 292 | Text which will be used as default value for "repo.readme". Multiple |
| 293 | files may be specified, separated by a space, and cgit will use the | 293 | config keys may be specified, and cgit will use the first found file |
| 294 | first found file in this list. Default value: none. | 294 | in this list. This is useful in conjunction with scan-path. Default |
| 295 | value: none. See also: scan-path, repo.readme. | ||
| 295 | 296 | ||
| 296 | remove-suffix:: | 297 | remove-suffix:: |
| 297 | If set to "1" and scan-path is enabled, if any repositories are found | 298 | If set to "1" and scan-path is enabled, if any repositories are found |
| @@ -1,6 +1,7 @@ | |||
| 1 | /* cmd.c: the cgit command dispatcher | 1 | /* cmd.c: the cgit command dispatcher |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2008 Lars Hjemli | 3 | * Copyright (C) 2008 Lars Hjemli |
| 4 | * Copyright (C) 2013 Jason A. Donenfeld <Jason@zx2c4.com>. | ||
| 4 | * | 5 | * |
| 5 | * Licensed under GNU General Public License v2 | 6 | * Licensed under GNU General Public License v2 |
| 6 | * (see COPYING for full license text) | 7 | * (see COPYING for full license text) |
| @@ -46,7 +47,7 @@ static void about_fn(struct cgit_context *ctx) | |||
| 46 | 47 | ||
| 47 | static void blob_fn(struct cgit_context *ctx) | 48 | static void blob_fn(struct cgit_context *ctx) |
| 48 | { | 49 | { |
| 49 | cgit_print_blob(ctx->qry.sha1, ctx->qry.path, ctx->qry.head); | 50 | cgit_print_blob(ctx->qry.sha1, ctx->qry.path, ctx->qry.head, 0); |
| 50 | } | 51 | } |
| 51 | 52 | ||
| 52 | static void commit_fn(struct cgit_context *ctx) | 53 | static void commit_fn(struct cgit_context *ctx) |
diff --git a/scan-tree.c b/scan-tree.c index a1ec8fb..2684b44 100644 --- a/scan-tree.c +++ b/scan-tree.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* scan-tree.c | 1 | /* scan-tree.c |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2008-2009 Lars Hjemli | 3 | * Copyright (C) 2008-2009 Lars Hjemli |
| 4 | * Copyright (C) 2010, 2012 Jason A. Donenfeld <Jason@zx2c4.com> | 4 | * Copyright (C) 2010-2013 Jason A. Donenfeld <Jason@zx2c4.com> |
| 5 | * | 5 | * |
| 6 | * Licensed under GNU General Public License v2 | 6 | * Licensed under GNU General Public License v2 |
| 7 | * (see COPYING for full license text) | 7 | * (see COPYING for full license text) |
| @@ -147,12 +147,6 @@ static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn) | |||
| 147 | strbuf_setlen(path, pathlen); | 147 | strbuf_setlen(path, pathlen); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | if (!repo->readme) { | ||
| 151 | strbuf_addstr(path, "README.html"); | ||
| 152 | if (!stat(path->buf, &st)) | ||
| 153 | repo->readme = "README.html"; | ||
| 154 | strbuf_setlen(path, pathlen); | ||
| 155 | } | ||
| 156 | if (ctx.cfg.section_from_path) { | 150 | if (ctx.cfg.section_from_path) { |
| 157 | n = ctx.cfg.section_from_path; | 151 | n = ctx.cfg.section_from_path; |
| 158 | if (n > 0) { | 152 | if (n > 0) { |
| @@ -1,7 +1,7 @@ | |||
| 1 | /* ui-blob.c: show blob content | 1 | /* ui-blob.c: show blob content |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2008 Lars Hjemli | 3 | * Copyright (C) 2008 Lars Hjemli |
| 4 | * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com> | 4 | * Copyright (C) 2010-2013 Jason A. Donenfeld <Jason@zx2c4.com> |
| 5 | * | 5 | * |
| 6 | * Licensed under GNU General Public License v2 | 6 | * Licensed under GNU General Public License v2 |
| 7 | * (see COPYING for full license text) | 7 | * (see COPYING for full license text) |
| @@ -15,7 +15,8 @@ | |||
| 15 | struct walk_tree_context { | 15 | struct walk_tree_context { |
| 16 | const char *match_path; | 16 | const char *match_path; |
| 17 | unsigned char *matched_sha1; | 17 | unsigned char *matched_sha1; |
| 18 | int found_path; | 18 | int found_path:1; |
| 19 | int file_only:1; | ||
| 19 | }; | 20 | }; |
| 20 | 21 | ||
| 21 | static int walk_tree(const unsigned char *sha1, const char *base, int baselen, | 22 | static int walk_tree(const unsigned char *sha1, const char *base, int baselen, |
| @@ -23,6 +24,8 @@ static int walk_tree(const unsigned char *sha1, const char *base, int baselen, | |||
| 23 | { | 24 | { |
| 24 | struct walk_tree_context *walk_tree_ctx = cbdata; | 25 | struct walk_tree_context *walk_tree_ctx = cbdata; |
| 25 | 26 | ||
| 27 | if (walk_tree_ctx->file_only && !S_ISREG(mode)) | ||
| 28 | return READ_TREE_RECURSIVE; | ||
| 26 | if (strncmp(base, walk_tree_ctx->match_path, baselen) | 29 | if (strncmp(base, walk_tree_ctx->match_path, baselen) |
| 27 | || strcmp(walk_tree_ctx->match_path + baselen, pathname)) | 30 | || strcmp(walk_tree_ctx->match_path + baselen, pathname)) |
| 28 | return READ_TREE_RECURSIVE; | 31 | return READ_TREE_RECURSIVE; |
| @@ -31,33 +34,34 @@ static int walk_tree(const unsigned char *sha1, const char *base, int baselen, | |||
| 31 | return 0; | 34 | return 0; |
| 32 | } | 35 | } |
| 33 | 36 | ||
| 34 | int cgit_ref_path_exists(const char *path, const char *ref) | 37 | int cgit_ref_path_exists(const char *path, const char *ref, int file_only) |
| 35 | { | 38 | { |
| 36 | unsigned char sha1[20]; | 39 | unsigned char sha1[20]; |
| 37 | unsigned long size; | 40 | unsigned long size; |
| 38 | struct pathspec_item path_items = { | 41 | struct pathspec_item path_items = { |
| 39 | .match = path, | 42 | .match = path, |
| 40 | .len = strlen(path) | 43 | .len = strlen(path) |
| 41 | }; | 44 | }; |
| 42 | struct pathspec paths = { | 45 | struct pathspec paths = { |
| 43 | .nr = 1, | 46 | .nr = 1, |
| 44 | .items = &path_items | 47 | .items = &path_items |
| 45 | }; | 48 | }; |
| 46 | struct walk_tree_context walk_tree_ctx = { | 49 | struct walk_tree_context walk_tree_ctx = { |
| 47 | .match_path = path, | 50 | .match_path = path, |
| 48 | .matched_sha1 = sha1, | 51 | .matched_sha1 = sha1, |
| 49 | .found_path = 0 | 52 | .found_path = 0, |
| 50 | }; | 53 | .file_only = file_only |
| 54 | }; | ||
| 51 | 55 | ||
| 52 | if (get_sha1(ref, sha1)) | 56 | if (get_sha1(ref, sha1)) |
| 53 | return 0; | 57 | return 0; |
| 54 | if (sha1_object_info(sha1, &size) != OBJ_COMMIT) | 58 | if (sha1_object_info(sha1, &size) != OBJ_COMMIT) |
| 55 | return 0; | 59 | return 0; |
| 56 | read_tree_recursive(lookup_commit_reference(sha1)->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); | 60 | read_tree_recursive(lookup_commit_reference(sha1)->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); |
| 57 | return walk_tree_ctx.found_path; | 61 | return walk_tree_ctx.found_path; |
| 58 | } | 62 | } |
| 59 | 63 | ||
| 60 | int cgit_print_file(char *path, const char *head) | 64 | int cgit_print_file(char *path, const char *head, int file_only) |
| 61 | { | 65 | { |
| 62 | unsigned char sha1[20]; | 66 | unsigned char sha1[20]; |
| 63 | enum object_type type; | 67 | enum object_type type; |
| @@ -75,7 +79,8 @@ int cgit_print_file(char *path, const char *head) | |||
| 75 | struct walk_tree_context walk_tree_ctx = { | 79 | struct walk_tree_context walk_tree_ctx = { |
| 76 | .match_path = path, | 80 | .match_path = path, |
| 77 | .matched_sha1 = sha1, | 81 | .matched_sha1 = sha1, |
| 78 | .found_path = 0 | 82 | .found_path = 0, |
| 83 | .file_only = file_only | ||
| 79 | }; | 84 | }; |
| 80 | 85 | ||
| 81 | if (get_sha1(head, sha1)) | 86 | if (get_sha1(head, sha1)) |
| @@ -98,7 +103,7 @@ int cgit_print_file(char *path, const char *head) | |||
| 98 | return 0; | 103 | return 0; |
| 99 | } | 104 | } |
| 100 | 105 | ||
| 101 | void cgit_print_blob(const char *hex, char *path, const char *head) | 106 | void cgit_print_blob(const char *hex, char *path, const char *head, int file_only) |
| 102 | { | 107 | { |
| 103 | unsigned char sha1[20]; | 108 | unsigned char sha1[20]; |
| 104 | enum object_type type; | 109 | enum object_type type; |
| @@ -116,6 +121,8 @@ void cgit_print_blob(const char *hex, char *path, const char *head) | |||
| 116 | struct walk_tree_context walk_tree_ctx = { | 121 | struct walk_tree_context walk_tree_ctx = { |
| 117 | .match_path = path, | 122 | .match_path = path, |
| 118 | .matched_sha1 = sha1, | 123 | .matched_sha1 = sha1, |
| 124 | .found_path = 0, | ||
| 125 | .file_only = file_only | ||
| 119 | }; | 126 | }; |
| 120 | 127 | ||
| 121 | if (hex) { | 128 | if (hex) { |
| @@ -1,8 +1,8 @@ | |||
| 1 | #ifndef UI_BLOB_H | 1 | #ifndef UI_BLOB_H |
| 2 | #define UI_BLOB_H | 2 | #define UI_BLOB_H |
| 3 | 3 | ||
| 4 | extern int cgit_ref_path_exists(const char *path, const char *ref); | 4 | extern int cgit_ref_path_exists(const char *path, const char *ref, int file_only); |
| 5 | extern int cgit_print_file(char *path, const char *head); | 5 | extern int cgit_print_file(char *path, const char *head, int file_only); |
| 6 | extern void cgit_print_blob(const char *hex, char *path, const char *head); | 6 | extern void cgit_print_blob(const char *hex, char *path, const char *head, int file_only); |
| 7 | 7 | ||
| 8 | #endif /* UI_BLOB_H */ | 8 | #endif /* UI_BLOB_H */ |
diff --git a/ui-shared.c b/ui-shared.c index 519eef7..7ab2ab1 100644 --- a/ui-shared.c +++ b/ui-shared.c | |||
| @@ -864,7 +864,7 @@ void cgit_print_pageheader(struct cgit_context *ctx) | |||
| 864 | if (ctx->repo->max_stats) | 864 | if (ctx->repo->max_stats) |
| 865 | cgit_stats_link("stats", NULL, hc(ctx, "stats"), | 865 | cgit_stats_link("stats", NULL, hc(ctx, "stats"), |
| 866 | ctx->qry.head, ctx->qry.vpath); | 866 | ctx->qry.head, ctx->qry.vpath); |
| 867 | if (ctx->repo->readme) | 867 | if (ctx->repo->readme.nr) |
| 868 | reporevlink("about", "about", NULL, | 868 | reporevlink("about", "about", NULL, |
| 869 | hc(ctx, "about"), ctx->qry.head, NULL, | 869 | hc(ctx, "about"), ctx->qry.head, NULL, |
| 870 | NULL); | 870 | NULL); |
diff --git a/ui-summary.c b/ui-summary.c index 57206dd..d8500d6 100644 --- a/ui-summary.c +++ b/ui-summary.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* ui-summary.c: functions for generating repo summary page | 1 | /* ui-summary.c: functions for generating repo summary page |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2006 Lars Hjemli | 3 | * Copyright (C) 2006 Lars Hjemli |
| 4 | * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com> | 4 | * Copyright (C) 2010-2013 Jason A. Donenfeld <Jason@zx2c4.com> |
| 5 | * | 5 | * |
| 6 | * Licensed under GNU General Public License v2 | 6 | * Licensed under GNU General Public License v2 |
| 7 | * (see COPYING for full license text) | 7 | * (see COPYING for full license text) |
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "ui-log.h" | 13 | #include "ui-log.h" |
| 14 | #include "ui-refs.h" | 14 | #include "ui-refs.h" |
| 15 | #include "ui-blob.h" | 15 | #include "ui-blob.h" |
| 16 | #include <libgen.h> | ||
| 16 | 17 | ||
| 17 | static void print_url(char *base, char *suffix) | 18 | static void print_url(char *base, char *suffix) |
| 18 | { | 19 | { |
| @@ -95,69 +96,57 @@ void cgit_print_summary() | |||
| 95 | html("</table>"); | 96 | html("</table>"); |
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | /* The caller must free filename and ref after calling this. */ | 99 | /* The caller must free the return value. */ |
| 99 | void cgit_parse_readme(const char *readme, const char *path, char **filename, char **ref, struct cgit_repo *repo) | 100 | static char* append_readme_path(const char *filename, const char *ref, const char *path) |
| 100 | { | 101 | { |
| 101 | const char *slash, *colon; | 102 | char *file, *base_dir, *full_path, *resolved_base = NULL, *resolved_full = NULL; |
| 102 | char *resolved_base, *resolved_full; | ||
