diff options
| -rw-r--r-- | source/ui-empty.c | 8 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-shared.c | 69 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-shared.h | 1 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rw-r--r-- | source/ui-summary.c | 8 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rwxr-xr-x | tests/t0102-summary.sh | 21 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
5 files changed, 93 insertions, 14 deletions
diff --git a/source/ui-empty.c b/source/ui-empty.c index a65f49b..dd8dc64 100644 --- a/source/ui-empty.c +++ b/source/ui-empty.c @@ -13,13 +13,7 @@ static void print_clone_url(const char *url) { - html("<tr><td class='clone-url'><a rel='vcs-git' href='"); - html_url_path(url); - html("' title='"); - html_attr(ctx.repo->name); - html(" Git repository'>"); - html_txt(url); - html("</a></td></tr>\n"); + cgit_print_clone_row(url, 0); } /* diff --git a/source/ui-shared.c b/source/ui-shared.c index 85712bf..5cf9428 100644 --- a/source/ui-shared.c +++ b/source/ui-shared.c @@ -317,8 +317,26 @@ static void print_rel_date(time_t t, int tz, double count, const char *class, htmlf("'>%.0f %s</time>", count, suffix); } +/* + * Whether a clone url opens with a URI scheme. The scp form git@host:path + * has none, and a link element's href must hold a URI, so that form stays + * out of the document head. + */ +static int has_uri_scheme(const char *url) +{ + const char *p = url; + + if (!isalpha((unsigned char)*p)) + return 0; + while (isalnum((unsigned char)*p) || *p == '+' || *p == '-' || *p == '.') + p++; + return *p == ':'; +} + static void print_rel_vcs_link(const char *url) { + if (!has_uri_scheme(url)) + return; html("<link rel='vcs-git' href='"); html_attr(url); html("' title='"); @@ -1620,6 +1638,57 @@ void cgit_add_clone_urls(void (*fn)(const char *)) add_clone_urls(fn, ctx.cfg.clone_prefix, ctx.repo->url); } +static char *http_clone_url; +static int http_clone_url_scanned; + +// Scheme names compare case-insensitively. +static int is_http_url(const char *url) +{ + return istarts_with(url, "http://") || istarts_with(url, "https://"); +} + +static void capture_http_clone_url(const char *url) +{ + if (!http_clone_url && is_http_url(url)) + http_clone_url = xstrdup(url); +} + +/* + * One row of the clone table. The url is shown as written, and every row is + * a link, but a browser cannot follow the ssh, scp or git forms, so those + * rows point at the first http url in the clone list, or at the repository's + * own page when the list has none, which with http clone enabled is itself a + * working clone url. A colspan of zero leaves the attribute out. + */ +void cgit_print_clone_row(const char *url, int colspan) +{ + const char *href = url; + char *fallback = NULL; + + if (!is_http_url(url)) { + if (!http_clone_url_scanned) { + http_clone_url_scanned = 1; + cgit_add_clone_urls(capture_http_clone_url); + } + href = http_clone_url; + if (!href) + href = fallback = cgit_repourl(ctx.repo->url); + } + + if (colspan) + htmlf("<tr><td colspan='%d' class='clone-url'>", colspan); + else + html("<tr><td class='clone-url'>"); + html("<a rel='vcs-git' title='"); + html_attr(ctx.repo->name); + html(" Git repository' href='"); + html_attr(href); + html("'>"); + html_txt(url); + html("</a></td></tr>\n"); + free(fallback); +} + void cgit_add_hidden_formfields(int incl_head, int incl_search, const char *page) { diff --git a/source/ui-shared.h b/source/ui-shared.h index c266951..c421178 100644 --- a/source/ui-shared.h +++ b/source/ui-shared.h @@ -24,6 +24,7 @@ extern char *cgit_currenturl(void); extern char *cgit_currentfullurl(void); extern const char *cgit_loginurl(void); extern char *cgit_repourl(const char *reponame); +extern void cgit_print_clone_row(const char *url, int colspan); extern char *cgit_fileurl(const char *reponame, const char *pagename, const char *filename, const char *query); extern char *cgit_pageurl(const char *reponame, const char *pagename, diff --git a/source/ui-summary.c b/source/ui-summary.c index 3658bc5..dacf0f7 100644 --- a/source/ui-summary.c +++ b/source/ui-summary.c @@ -48,13 +48,7 @@ static void print_clone_url(const char *url) htmlf("<tr class='nohover'><th colspan='%d' class='left'>Clone</th></tr>\n", columns); } - htmlf("<tr><td colspan='%d' class='clone-url'><a rel='vcs-git' href='", columns); - html_url_path(url); - html("' title='"); - html_attr(ctx.repo->name); - html(" Git repository'>"); - html_txt(url); - html("</a></td></tr>\n"); + cgit_print_clone_row(url, columns); } /* diff --git a/tests/t0102-summary.sh b/tests/t0102-summary.sh index 79f2b11..5ce1fab 100755 --- a/tests/t0102-summary.sh +++ b/tests/t0102-summary.sh @@ -32,4 +32,25 @@ test_expect_success 'clone-url expanded correctly' ' grep "git://example.org/bar.git" tmp ' +# A clone url is shown as written, but a browser cannot follow the ssh, scp +# or git forms, so those rows link to the first http url in the list, or to +# the repository's own page when the list has none. +test_expect_success 'a git clone url row falls back to the page url' ' + grep "clone-url.><a rel=.vcs-git. title=.bar Git repository. href=./bar/.>git://example.org/bar.git</a>" tmp +' + +test_expect_success 'an scp clone url row links to the http url' ' + { + echo "virtual-root=/" && + echo "cache-size=0" && + echo "repo.url=foo" && + echo "repo.path=$PWD/repos/foo/.git" && + echo "repo.clone-url=git@example.org:foo https://example.org/foo" + } >clonerc && + CGIT_CONFIG="$PWD/clonerc" QUERY_STRING="url=foo" cgit >tmp && + grep "title=.foo Git repository. href=.https://example.org/foo.>git@example.org:foo</a>" tmp && + grep "vcs-git. href=.https://example.org/foo." tmp && + ! grep "vcs-git. href=.git@" tmp +' + test_done |
