diff options
| -rw-r--r-- | ui-tree.c | 58 |
1 files changed, 54 insertions, 4 deletions
@@ -11,14 +11,51 @@ #include "cgit.h" #include "ui-tree.h" #include "html.h" +#include "ui-blob.h" #include "ui-shared.h" struct walk_tree_context { char *curr_rev; char *match_path; int state; + /* Best README found in the directory currently being listed, so we can + * render it (GitHub-style) under the file list. */ + char *readme_path; + int readme_rank; }; +/* Rank a directory entry as a renderable README: 0 = not a readme, higher = + * more preferred. "readme" + a known extension, case-insensitive. */ +static int readme_rank(const char *name) +{ + static const char * const exts[] = { + "", ".txt", ".rst", ".mkd", ".mdown", ".markdown", ".md" + }; + const char *rest; + int i; + + if (strncasecmp(name, "readme", 6)) + return 0; + rest = name + 6; + for (i = ARRAY_SIZE(exts) - 1; i >= 0; i--) + if (!strcasecmp(rest, exts[i])) + return i + 1; + return 0; +} + +/* Render the best README of the just-listed directory through the about-filter, + * so browsing a tree shows the folder's readme beneath the listing. */ +static void print_dir_readme(struct walk_tree_context *walk_tree_ctx) +{ + if (!walk_tree_ctx->readme_path || !ctx.repo->about_filter) + return; + html("<div id='summary' class='dir-readme'>"); + cgit_open_filter(ctx.repo->about_filter, walk_tree_ctx->readme_path); + cgit_print_file(walk_tree_ctx->readme_path, walk_tree_ctx->curr_rev, 1); + cgit_close_filter(ctx.repo->about_filter); + html("</div>\n"); +} + static void print_text_buffer(const char *name, char *buf, unsigned long size) { unsigned long lineno, idx; @@ -216,6 +253,15 @@ static int ls_item(const struct object_id *oid, struct strbuf *base, strbuf_addf(&fullpath, "%s%s%s", ctx.qry.path ? ctx.qry.path : "", ctx.qry.path ? "/" : "", name); + if (S_ISREG(mode)) { + int rank = readme_rank(name); + if (rank > walk_tree_ctx->readme_rank) { + walk_tree_ctx->readme_rank = rank; + free(walk_tree_ctx->readme_path); + walk_tree_ctx->readme_path = xstrdup(fullpath.buf); + } + } + if (!S_ISGITLINK(mode)) { type = odb_read_object_info(the_repository->objects, oid, &size); if (type == OBJ_BAD) { @@ -293,9 +339,10 @@ static void ls_head(void) html("</tr>\n"); } -static void ls_tail(void) +static void ls_tail(struct walk_tree_context *walk_tree_ctx) { html("</table>\n"); + print_dir_readme(walk_tree_ctx); cgit_print_layout_end(); } @@ -315,7 +362,7 @@ static void ls_tree(const struct object_id *oid, const char *path, struct walk_t ls_head(); read_tree(the_repository, tree, &paths, ls_item, walk_tree_ctx); - ls_tail(); + ls_tail(walk_tree_ctx); } @@ -368,7 +415,9 @@ void cgit_print_tree(const char *rev, char *path) }; struct walk_tree_context walk_tree_ctx = { .match_path = path, - .state = 0 + .state = 0, + .readme_path = NULL, + .readme_rank = 0 }; if (!rev) @@ -396,7 +445,7 @@ void cgit_print_tree(const char *rev, char *path) read_tree(the_repository, repo_get_commit_tree(the_repository, commit), &paths, walk_tree, &walk_tree_ctx); if (walk_tree_ctx.state == 1) - ls_tail(); + ls_tail(&walk_tree_ctx); else if (walk_tree_ctx.state == 2) cgit_print_layout_end(); else @@ -404,4 +453,5 @@ void cgit_print_tree(const char *rev, char *path) cleanup: free(walk_tree_ctx.curr_rev); + free(walk_tree_ctx.readme_path); } |
