From 180ecdad0c0d9d2587c70ac893e881f7217a49e8 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Sun, 1 Nov 2026 17:21:33 -1000 Subject: Answer a submodule path with the submodule The tree page read the gitlink's commit as a blob, which outside the repository is a bad object id and inside it is the commit's raw text. --- source/ui-shared.c | 42 ++++++++++++++++++++++++++++++------------ source/ui-shared.h | 6 ++++++ source/ui-tree.c | 9 +++++++-- 3 files changed, 43 insertions(+), 14 deletions(-) (limited to 'source') diff --git a/source/ui-shared.c b/source/ui-shared.c index e346cbd..c3eee0b 100644 --- a/source/ui-shared.c +++ b/source/ui-shared.c @@ -1522,24 +1522,21 @@ static void print_docstart(void) html_include(ctx.cfg.header); } -void cgit_print_error_page(int code, const char *msg, const char *fmt, ...) +/* + * Start the page an error is printed into, and answer whether it started. + * Once the status line is out the error can only join the body under way, + * and the page that hit it carries on to its own end. + */ +static int start_error_page(int code, const char *msg) { - va_list ap; - // An error page describes a condition that may not outlast the slot // holding it. A request naming a commit not yet pushed would cache its // 404 under the never-expiring static ttl and keep serving it after // the push, so the error is rendered straight to the visitor instead. html_flush(); cache_abandon_fill(); - va_start(ap, fmt); - // Once the status line is out the error can only join the body under - // way, and the page that hit it carries on to its own end. - if (ctx.page.headers_sent) { - vprint_error(fmt, ap); - va_end(ap); - return; - } + if (ctx.page.headers_sent) + return 0; ctx.page.status = code; ctx.page.statusmsg = msg; // The error stands where a page would name itself, ahead of the @@ -1554,9 +1551,30 @@ void cgit_print_error_page(int code, const char *msg, const char *fmt, ...) ctx.page.charset = PAGE_ENCODING; ctx.page.filename = NULL; cgit_print_layout_start(); + return 1; +} + +void cgit_print_error_page(int code, const char *msg, const char *fmt, ...) +{ + int started = start_error_page(code, msg); + va_list ap; + + va_start(ap, fmt); vprint_error(fmt, ap); va_end(ap); - cgit_print_layout_end(); + if (started) + cgit_print_layout_end(); +} + +void cgit_print_submodule_page(char *path, const char *rev) +{ + int started = start_error_page(404, "Not Found"); + + html("
This path is a submodule: "); + cgit_submodule_link("ls-mod", path, rev); + html("
\n"); + if (started) + cgit_print_layout_end(); } void cgit_print_blob_too_large(size_t size) diff --git a/source/ui-shared.h b/source/ui-shared.h index fa73c83..e52a3ae 100644 --- a/source/ui-shared.h +++ b/source/ui-shared.h @@ -142,6 +142,12 @@ extern void cgit_print_error_page(int code, const char *msg, const char *fmt, .. */ extern void cgit_print_blob_too_large(size_t size); +/* + * Answer with the 404 page for a path naming a submodule, whose commit rev + * lives in another repository, linking it the way a tree listing does. + */ +extern void cgit_print_submodule_page(char *path, const char *rev); + /* * Resolve rev to the parsed commit it names, peeling a tag, with oid set to * what rev itself names. Returns NULL once the 404 page naming rev is out. diff --git a/source/ui-tree.c b/source/ui-tree.c index 63b8984..f1b995a 100644 --- a/source/ui-tree.c +++ b/source/ui-tree.c @@ -470,6 +470,11 @@ static int walk_tree(const struct object_id *oid, struct strbuf *base, strbuf_release(&fullpath); ls_head(); return READ_TREE_RECURSIVE; + } else if (S_ISGITLINK(mode)) { + cgit_print_submodule_page(fullpath.buf, oid_to_hex(oid)); + walk->state = WALK_ERROR_SHOWN; + strbuf_release(&fullpath); + return 0; } else { bool shown = print_object(oid, mode, fullpath.buf, pathname, walk->rev); @@ -524,6 +529,6 @@ void cgit_print_tree(const char *rev, char *path) } else if (walk.state == WALK_LOOKING) { cgit_print_error_page(404, "Not Found", "Path not found"); } - // WALK_ERROR_SHOWN is left alone, since the error page print_object - // put out is already complete. + // WALK_ERROR_SHOWN is left alone, since the error page the walk put + // out is already complete. } -- cgit 2.12.1