neocgit

a more 'modern' version of cgit
Log | Files | Refs | Submodules | README | LICENSE | git clone https://git.ne02ptzero.me/git/neocgit

commit 4675c4396345c0177d73c8927b2290fa4577ff8b
parent 6967dae190732352d8a0df2ac74177abe21bbdf6
Author: Ne02ptzero <louis@ne02ptzero.me>
Date:   Fri, 29 Jun 2018 18:46:02 +0200

WORK: Some work on the summary tree, still buggy

Signed-off-by: Ne02ptzero <louis@ne02ptzero.me>

Diffstat:
Mcgit.css | 167++++++++++---------------------------------------------------------------------
Mui-log.c | 151++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mui-log.h | 1+
Mui-shared.c | 8++++----
Mui-summary.c | 4++--
Mui-tree.c | 293++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
6 files changed, 324 insertions(+), 300 deletions(-)

diff --git a/cgit.css b/cgit.css @@ -382,51 +382,39 @@ div#cgit table { padding: 10px 15px; } -.repo-tree { - border: 1px solid black; -} - -div#cgit table.tabs { - border-collapse: collapse; - margin-bottom: 0px; - width: 100%; -} - -div#cgit table.tabs td { - padding: 0px 1em; - vertical-align: bottom; +.repo-tree table { + width: 100%; + border-top: 1px solid #e5e5e5; + border-bottom: 1px solid #e5e5e5; } -div#cgit table.tabs td a { - padding: 2px 0.75em; - color: #777; - font-size: 110%; +.repo-tree table tr { + border-top: 1px solid #f0f0f0; } -div#cgit table.tabs td a.active { - color: #000; - background-color: #ccc; +.repo-tree table tr td { + padding: 10px 16px; + color: #707070; } -div#cgit table.tabs a[href^="http://"]:after, div#cgit table.tabs a[href^="https://"]:after { - content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfgAhcJDQY+gm2TAAAAHWlUWHRDb21tZW50AAAAAABDcmVhdGVkIHdpdGggR0lNUGQuZQcAAABbSURBVAhbY2BABs4MU4CwhYHBh2Erww4wrGFQZHjI8B8IgUIscJWyDHcggltQhI4zGDCcRwhChPggHIggP1QoAVmQkSETrGoHsiAEsACtBYN0oDAMbgU6EBcAAL2eHUt4XUU4AAAAAElFTkSuQmCC); - opacity: 0.5; - margin: 0 0 0 5px; +.repo-tree table tr td a { + color: black !important; } -div#cgit table.tabs td.form { - text-align: right; +.repo-tree table tr th { + background-color: #fafafa; + font-weight: 400; + line-height: 21px; + border-bottom: 0; + padding: 10px 16px; } -div#cgit table.tabs td.form form { - padding-bottom: 2px; - font-size: 90%; - white-space: nowrap; +.repo-tree table .table-left { + text-align: left; } -div#cgit table.tabs td.form input, -div#cgit table.tabs td.form select { - font-size: 90%; +.repo-tree table .table-right { + text-align: right; } div#cgit div.path { @@ -438,119 +426,6 @@ div#cgit div.path { div#cgit div.content { margin: 0px; - /*padding: 2em;*/ - /*border-bottom: solid 3px #ccc;*/ -} - - -div#cgit table.list { - width: 100%; - border: none; - border-collapse: collapse; -} - -div#cgit table.list tr { - background: white; -} - -div#cgit table.list tr.logheader { - background: #eee; -} - -div#cgit table.list tr:nth-child(even) { - background: #f7f7f7; -} - -div#cgit table.list tr:nth-child(odd) { - background: white; -} - -div#cgit table.list tr:hover { - background: #eee; -} - -div#cgit table.list tr.nohover { - background: white; -} - -div#cgit table.list tr.nohover:hover { - background: white; -} - -div#cgit table.list tr.nohover-highlight:hover:nth-child(even) { - background: #f7f7f7; -} - -div#cgit table.list tr.nohover-highlight:hover:nth-child(odd) { - background: white; -} - -div#cgit table.list th { - font-weight: bold; - /* color: #888; - border-top: dashed 1px #888; - border-bottom: dashed 1px #888; - */ - padding: 0.1em 0.5em 0.05em 0.5em; - vertical-align: baseline; -} - -div#cgit table.list td { - border: none; - padding: 0.1em 0.5em 0.1em 0.5em; -} - -div#cgit table.list td.commitgraph { - font-family: monospace; - white-space: pre; -} - -div#cgit table.list td.commitgraph .column1 { - color: #a00; -} - -div#cgit table.list td.commitgraph .column2 { - color: #0a0; -} - -div#cgit table.list td.commitgraph .column3 { - color: #aa0; -} - -div#cgit table.list td.commitgraph .column4 { - color: #00a; -} - -div#cgit table.list td.commitgraph .column5 { - color: #a0a; -} - -div#cgit table.list td.commitgraph .column6 { - color: #0aa; -} - -div#cgit table.list td.logsubject { - font-family: monospace; - font-weight: bold; -} - -div#cgit table.list td.logmsg { - font-family: monospace; - white-space: pre; - padding: 0 0.5em; -} - -div#cgit table.list td a { - color: black; -} - -div#cgit table.list td a.ls-dir { - font-weight: bold; - color: #00f; -} - -div#cgit table.list td a:hover { - color: #00f; } div#cgit img { diff --git a/ui-log.c b/ui-log.c @@ -361,15 +361,52 @@ int cgit_count_commits(void) prepare_revision_walk(&rev); - for (ret = 0; (commit = get_revision(&rev)) != NULL; ret++) + for (ret = 0; (commit = get_revision(&rev)) != NULL; ret++) ; if (must_free_tip) free((char *)tip); + reset_revision_walk(); + return ret; } +struct commit *cgit_get_last_commit_from_path(const char *path) +{ + struct rev_info rev; + struct commit *commit = NULL; + struct argv_array rev_argv = ARGV_ARRAY_INIT; + int must_free_tip = 0; + const char *tip; + + + tip = ctx.qry.head; + argv_array_push(&rev_argv, "log_rev_setup"); + tip = disambiguate_ref(tip, &must_free_tip); + argv_array_push(&rev_argv, tip); + argv_array_push(&rev_argv, "--"); + argv_array_push(&rev_argv, path); + + init_revisions(&rev, NULL); + setup_revisions(rev_argv.argc, rev_argv.argv, &rev, NULL); + load_ref_decorations(NULL, DECORATE_FULL_REFS); + + prepare_revision_walk(&rev); + commit = get_revision(&rev); + + while (get_revision(&rev)) + ; + + object_array_clear(&rev.pending); + reset_revision_walk(); + + if (must_free_tip) + free((char *)tip); + + return commit; +} + static char *next_token(char **src) { char *result; @@ -401,84 +438,88 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern int i, columns = commit_graph ? 4 : 3; int must_free_tip = 0; + /* rev_argv.argv[0] will be ignored by setup_revisions */ argv_array_push(&rev_argv, "log_rev_setup"); + if (!tip) tip = ctx.qry.head; tip = disambiguate_ref(tip, &must_free_tip); + printf("Tip: %s, Path: %s\n", tip, path); argv_array_push(&rev_argv, tip); - if (grep && pattern && *pattern) { - pattern = xstrdup(pattern); - if (!strcmp(grep, "grep") || !strcmp(grep, "author") || - !strcmp(grep, "committer")) { - argv_array_pushf(&rev_argv, "--%s=%s", grep, pattern); - } else if (!strcmp(grep, "range")) { - char *arg; + if (grep && pattern && *pattern) { + pattern = xstrdup(pattern); + if (!strcmp(grep, "grep") || !strcmp(grep, "author") || + !strcmp(grep, "committer")) { + argv_array_pushf(&rev_argv, "--%s=%s", grep, pattern); + } else if (!strcmp(grep, "range")) { + char *arg; /* Split the pattern at whitespace and add each token * as a revision expression. Do not accept other * rev-list options. Also, replace the previously * pushed tip (it's no longer relevant). */ - argv_array_pop(&rev_argv); - while ((arg = next_token(&pattern))) { - if (*arg == '-') { - fprintf(stderr, "Bad range expr: %s\n", - arg); - break; - } - argv_array_push(&rev_argv, arg); - } - } - } - - if (!path || !ctx.cfg.enable_follow_links) { + argv_array_pop(&rev_argv); + while ((arg = next_token(&pattern))) { + if (*arg == '-') { + fprintf(stderr, "Bad range expr: %s\n", + arg); + break; + } + argv_array_push(&rev_argv, arg); + } + } + } + + if (!path || !ctx.cfg.enable_follow_links) { /* * If we don't have a path, "follow" is a no-op so make sure * the variable is set to false to avoid needing to check * both this and whether we have a path everywhere. */ - ctx.qry.follow = 0; - } - - if (commit_graph && !ctx.qry.follow) { - argv_array_push(&rev_argv, "--graph"); - argv_array_push(&rev_argv, "--color"); - graph_set_column_colors(column_colors_html, - COLUMN_COLORS_HTML_MAX); - } - - if (commit_sort == 1) - argv_array_push(&rev_argv, "--date-order"); - else if (commit_sort == 2) - argv_array_push(&rev_argv, "--topo-order"); - - if (path && ctx.qry.follow) - argv_array_push(&rev_argv, "--follow"); + ctx.qry.follow = 0; + } + + if (commit_graph && !ctx.qry.follow) { + argv_array_push(&rev_argv, "--graph"); + argv_array_push(&rev_argv, "--color"); + graph_set_column_colors(column_colors_html, + COLUMN_COLORS_HTML_MAX); + } + + if (commit_sort == 1) + argv_array_push(&rev_argv, "--date-order"); + else if (commit_sort == 2) + argv_array_push(&rev_argv, "--topo-order"); + + if (path && ctx.qry.follow) + argv_array_push(&rev_argv, "--follow"); argv_array_push(&rev_argv, "--"); if (path) argv_array_push(&rev_argv, path); init_revisions(&rev, NULL); - rev.abbrev = DEFAULT_ABBREV; - rev.commit_format = CMIT_FMT_DEFAULT; - rev.verbose_header = 1; - rev.show_root_diff = 0; - rev.ignore_missing = 1; - rev.simplify_history = 1; - setup_revisions(rev_argv.argc, rev_argv.argv, &rev, NULL); - load_ref_decorations(NULL, DECORATE_FULL_REFS); - rev.show_decorations = 1; - rev.grep_filter.ignore_case = 1; - - rev.diffopt.detect_rename = 1; - rev.diffopt.rename_limit = ctx.cfg.renamelimit; - if (ctx.qry.ignorews) - DIFF_XDL_SET(&rev.diffopt, IGNORE_WHITESPACE); - - compile_grep_patterns(&rev.grep_filter); + rev.abbrev = DEFAULT_ABBREV; + rev.commit_format = CMIT_FMT_DEFAULT; + rev.verbose_header = 1; + rev.show_root_diff = 0; + rev.ignore_missing = 1; + rev.simplify_history = 1; + setup_revisions(rev_argv.argc, rev_argv.argv, &rev, NULL); + load_ref_decorations(NULL, DECORATE_FULL_REFS); + rev.show_decorations = 1; + rev.grep_filter.ignore_case = 1; + + rev.diffopt.detect_rename = 1; + rev.diffopt.rename_limit = ctx.cfg.renamelimit; + if (ctx.qry.ignorews) + DIFF_XDL_SET(&rev.diffopt, IGNORE_WHITESPACE); + + compile_grep_patterns(&rev.grep_filter); prepare_revision_walk(&rev); + reset_revision_walk(); if (pager) { cgit_print_layout_start(); diff --git a/ui-log.h b/ui-log.h @@ -6,5 +6,6 @@ extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, int commit_graph, int commit_sort); extern void show_commit_decorations(struct commit *commit); extern int cgit_count_commits(void); +extern struct commit *cgit_get_last_commit_from_path(const char *path); #endif /* UI_LOG_H */ diff --git a/ui-shared.c b/ui-shared.c @@ -821,8 +821,8 @@ void cgit_print_error_page(int code, const char *msg, const char *fmt, ...) void cgit_print_layout_start(void) { cgit_print_http_headers(); - cgit_print_docstart(); - cgit_print_pageheader(); + cgit_print_docstart(); + cgit_print_pageheader(); } void cgit_print_layout_end(void) @@ -1022,9 +1022,9 @@ void cgit_print_pageheader(void) if (ctx.env.authenticated && ctx.repo) { _html("<div class='summary-header'>") { if (ctx.repo->logo != NULL) - htmlf("<img src='%s' />", ctx.repo->logo); + htmlf("<img src='/%s' />", ctx.repo->logo); else - htmlf("<img src='%s' />", ctx.cfg.logo); + htmlf("<img src='/%s' />", ctx.cfg.logo); html("<br />"); htmlf("<h3>%s</h3>", ctx.repo->name); htmlf("<span>%s</span>", ctx.repo->desc); diff --git a/ui-summary.c b/ui-summary.c @@ -52,9 +52,9 @@ void cgit_print_summary(void) cgit_print_layout_start(); cgit_print_tree(ctx.qry.sha1, ctx.qry.path, false); - cgit_print_repo_readme(ctx.qry.path, false); + /*cgit_print_repo_readme(ctx.qry.path, false);*/ - cgit_print_layout_end(); + /*cgit_print_layout_end();*/ } /* The caller must free the return value. */ diff --git a/ui-tree.c b/ui-tree.c @@ -10,11 +10,22 @@ #include "ui-tree.h" #include "html.h" #include "ui-shared.h" +#include "ui-log.h" + +struct tree_link { + const struct object_id *oid; + struct strbuf *base; + char *pathname; + unsigned mode; + int stage; + struct tree_link *next; +}; struct walk_tree_context { char *curr_rev; char *match_path; int state; + struct tree_link *head; }; static void print_text_buffer(const char *name, char *buf, unsigned long size) @@ -198,66 +209,153 @@ static void write_tree_link(const struct object_id *oid, char *name, strbuf_setlen(fullpath, initial_length); } +static void print_tree_item(struct tree_link *ptr, struct walk_tree_context *tree_ctx) +{ + struct strbuf class = STRBUF_INIT; + struct strbuf fullpath = STRBUF_INIT; + struct commitinfo *info = NULL; + struct commit *commit = NULL; + char *name; + + name = xstrdup(ptr->pathname); + strbuf_addf(&fullpath, "%s%s%s", ctx.qry.path ? ctx.qry.path : "", + ctx.qry.path ? "/" : "", name); + + commit = cgit_get_last_commit_from_path(name); + if (commit) + info = cgit_parse_commit(commit); + + _html("<tr>") { + _html("<td class='table-left'>") { + cgit_tree_link(name, NULL, class.buf, ctx.qry.head, tree_ctx->curr_rev, + fullpath.buf); + } _html("</td>"); + + _html("<td class='table-left'>") { + if (info) + htmlf("%s", info->subject); + else + html("[ERROR]"); + } _html("</td>"); + + _html("<td class='table-right'>") { + if (info) + { + cgit_print_age(info->author_date, info->author_tz, -1); + html(" ago"); + } + else + html("ERROR"); + } _html("</td>"); + } _html("</tr>"); + + if (commit) + free_commit_buffer(commit); +} + static int ls_item(const struct object_id *oid, struct strbuf *base, const char *pathname, unsigned mode, int stage, void *cbdata) { + struct tree_link *obj; struct walk_tree_context *walk_tree_ctx = cbdata; - char *name; - struct strbuf fullpath = STRBUF_INIT; - struct strbuf class = STRBUF_INIT; - enum object_type type; - unsigned long size = 0; - - name = xstrdup(pathname); - strbuf_addf(&fullpath, "%s%s%s", ctx.qry.path ? ctx.qry.path : "", - ctx.qry.path ? "/" : "", name); - - if (!S_ISGITLINK(mode)) { - type = oid_object_info(the_repository, oid, &size); - if (type == OBJ_BAD) { - htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", - name, - oid_to_hex(oid)); - free(name); - return 0; - } - } - html("<tr><td class='ls-mode'>"); - cgit_print_filemode(mode); - html("</td><td>"); - if (S_ISGITLINK(mode)) { - cgit_submodule_link("ls-mod", fullpath.buf, oid_to_hex(oid)); - } else if (S_ISDIR(mode)) { - write_tree_link(oid, name, walk_tree_ctx->curr_rev, - &fullpath); - } else { - char *ext = strrchr(name, '.'); - strbuf_addstr(&class, "ls-blob"); - if (ext) - strbuf_addf(&class, " %s", ext + 1); - cgit_tree_link(name, NULL, class.buf, ctx.qry.head, - walk_tree_ctx->curr_rev, fullpath.buf); - } - htmlf("</td><td class='ls-size'>%li</td>", size); - - html("<td>"); - cgit_log_link("log", NULL, "button", ctx.qry.head, - walk_tree_ctx->curr_rev, fullpath.buf, 0, NULL, NULL, - ctx.qry.showmsg, 0); - if (ctx.repo->max_stats) - cgit_stats_link("stats", NULL, "button", ctx.qry.head, - fullpath.buf); - if (!S_ISGITLINK(mode)) - cgit_plain_link("plain", NULL, "button", ctx.qry.head, - walk_tree_ctx->curr_rev, fullpath.buf); - if (!S_ISDIR(mode) && ctx.cfg.enable_blame) - cgit_blame_link("blame", NULL, "button", ctx.qry.head, - walk_tree_ctx->curr_rev, fullpath.buf); - html("</td></tr>\n"); - free(name); - strbuf_release(&fullpath); - strbuf_release(&class); + if (pathname[0] == '.') + return 0; + + obj = calloc(1, sizeof(*obj)); + obj->oid = oid; + obj->base = base; + obj->pathname = strdup(pathname); + obj->mode = mode; + obj->stage = stage; + + if (walk_tree_ctx->head == NULL) + walk_tree_ctx->head = obj; + else + { + struct tree_link *tmp; + for (tmp = walk_tree_ctx->head; tmp->next != NULL; tmp = tmp->next) + ; + + tmp->next = obj; + } + /* char *name;*/ + /*struct strbuf fullpath = STRBUF_INIT;*/ + /*struct strbuf class = STRBUF_INIT;*/ + /*enum object_type type;*/ + /*unsigned long size = 0;*/ + + /*name = xstrdup(pathname);*/ + /*strbuf_addf(&fullpath, "%s%s%s", ctx.qry.path ? ctx.qry.path : "",*/ + /*ctx.qry.path ? "/" : "", name);*/ + + /*if (!S_ISGITLINK(mode)) {*/ + /*type = oid_object_info(the_repository, oid, &size);*/ + /*if (type == OBJ_BAD) {*/ + /*htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",*/ + /*name,*/ + /*oid_to_hex(oid));*/ + /*free(name);*/ + /*return 0;*/ + /*}*/ + /*}*/ + + /*_html("<tr>") {*/ + + /*_html("<td class='table-left'>") {*/ + /*cgit_tree_link(name, NULL, class.buf, ctx.qry.head,*/ + /*walk_tree_ctx->curr_rev, fullpath.buf);*/ + /*} _html("</td>");*/ + + /*_html("<td class='table-left'>") {*/ + /*struct commit co = { 0 };*/ + + /*cgit_get_last_commit_from_path(name, &co);*/ + /*struct commitinfo *info = cgit_parse_commit(&co);*/ + /*htmlf("Msg: %s, Author: %s", info->subject, info->author);*/ + + /*} _html("</td>");*/ + + /*_html("<td class='table-right'>") {*/ + /*html("Update");*/ + /*} _html("</td>");*/ + /*} _html("</tr>");*/ + + /*html("<tr><td class='ls-mode'>");*/ + /*cgit_print_filemode(mode);*/ + /*html("</td><td>");*/ + /*if (S_ISGITLINK(mode)) {*/ + /*cgit_submodule_link("ls-mod", fullpath.buf, oid_to_hex(oid));*/ + /*} else if (S_ISDIR(mode)) {*/ + /*write_tree_link(oid, name, walk_tree_ctx->curr_rev,*/ + /*&fullpath);*/ + /*} else {*/ + /*char *ext = strrchr(name, '.');*/ + /*strbuf_addstr(&class, "ls-blob");*/ + /*if (ext)*/ + /*strbuf_addf(&class, " %s", ext + 1);*/ + /*cgit_tree_link(name, NULL, class.buf, ctx.qry.head,*/ + /*walk_tree_ctx->curr_rev, fullpath.buf);*/ + /*}*/ + /*htmlf("</td><td class='ls-size'>%li</td>", size);*/ + + /*html("<td>");*/ + /*cgit_log_link("log", NULL, "button", ctx.qry.head,*/ + /*walk_tree_ctx->curr_rev, fullpath.buf, 0, NULL, NULL,*/ + /*ctx.qry.showmsg, 0);*/ + /*if (ctx.repo->max_stats)*/ + /*cgit_stats_link("stats", NULL, "button", ctx.qry.head,*/ + /*fullpath.buf);*/ + /*if (!S_ISGITLINK(mode))*/ + /*cgit_plain_link("plain", NULL, "button", ctx.qry.head,*/ + /*walk_tree_ctx->curr_rev, fullpath.buf);*/ + /*if (!S_ISDIR(mode) && ctx.cfg.enable_blame)*/ + /*cgit_blame_link("blame", NULL, "button", ctx.qry.head,*/ + /*walk_tree_ctx->curr_rev, fullpath.buf);*/ + /*html("</td></tr>\n");*/ + /*free(name);*/ + /*strbuf_release(&fullpath);*/ + /*strbuf_release(&class);*/ return 0; } @@ -286,19 +384,33 @@ static void ls_tree(const struct object_id *oid, char *path, struct walk_tree_co .nr = 0 }; - tree = parse_tree_indirect(oid); - if (!tree) { - cgit_print_error_page(404, "Not found", - "Not a tree object: %s", oid_to_hex(oid)); - return; - } + tree = parse_tree_indirect(oid); + if (!tree) { + cgit_print_error_page(404, "Not found", + "Not a tree object: %s", oid_to_hex(oid)); + return; + } if (layout) cgit_print_layout_start(); html("<div class='repository-tree'><div class='repo-tree'><table>"); - html("<th>Name</th><th>Last commit</th><th>Last update</th>"); + _html("<tr class='table-title'>") { + html("<th class='table-left'>Name</th>"); + html("<th class='table-left'>Last commit</th>"); + html("<th class='table-right'>Last update</th>"); + } _html("</tr>"); + + walk_tree_ctx->head = NULL; read_tree_recursive(tree, "", 0, 1, &paths, ls_item, walk_tree_ctx); + free_tree_buffer(tree); + reset_revision_walk(); + update_main_cache_tree(0); + for (struct tree_link *tmp = walk_tree_ctx->head; tmp; tmp = tmp->next) + { + print_tree_item(tmp, walk_tree_ctx); + } + html("</table></div></div>"); if (layout) @@ -336,11 +448,6 @@ static int walk_tree(const struct object_id *oid, struct strbuf *base, return 0; } -void cgit_print_tree_no_layout(const char *rev, char *path) -{ - -} - /* * Show a tree or a blob * rev: the commit pointing at the root tree object @@ -363,32 +470,32 @@ void cgit_print_tree(const char *rev, char *path, bool layout) .state = 0 }; - if (!rev) - rev = ctx.qry.head; - - if (get_oid(rev, &oid)) { - cgit_print_error_page(404, "Not found", - "Invalid revision name: %s", rev); - return; - } - commit = lookup_commit_reference(&oid); - if (!commit || parse_commit(commit)) { - cgit_print_error_page(404, "Not found", - "Invalid commit reference: %s", rev); - return; - } - - walk_tree_ctx.curr_rev = xstrdup(rev); - - if (path == NULL) { - ls_tree(&commit->maybe_tree->object.oid, NULL, &walk_tree_ctx, layout); - goto cleanup; - } - - read_tree_recursive(commit->maybe_tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); - if (walk_tree_ctx.state == 1) - ls_tail(); - else if (walk_tree_ctx.state == 2) + if (!rev) + rev = ctx.qry.head; + + if (get_oid(rev, &oid)) { + cgit_print_error_page(404, "Not found", + "Invalid revision name: %s", rev); + return; + } + commit = lookup_commit_reference(&oid); + if (!commit || parse_commit(commit)) { + cgit_print_error_page(404, "Not found", + "Invalid commit reference: %s", rev); + return; + } + + walk_tree_ctx.curr_rev = xstrdup(rev); + + if (path == NULL) { + ls_tree(&commit->maybe_tree->object.oid, NULL, &walk_tree_ctx, layout); + goto cleanup; + } + + read_tree_recursive(commit->maybe_tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); + if (walk_tree_ctx.state == 1) + ls_tail(); + else if (walk_tree_ctx.state == 2) cgit_print_layout_end(); else cgit_print_error_page(404, "Not found", "Path not found");