aboutsummaryrefslogtreecommitdiff
path: root/ui-ci.c
diff refs
from:
to:
flip
diff options
context:
space:
mode:
Diffstat (limited to 'ui-ci.c')
-rw-r--r--ui-ci.c152
1 files changed, 0 insertions, 152 deletions
diff --git a/ui-ci.c b/ui-ci.c
deleted file mode 100644
index f2561a2..0000000
--- a/ui-ci.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/* ui-ci.c: redirect to an external CI system
- *
- * Copyright (C) 2026 Saya Andy <saya.andy@posteo.com>
- *
- * Licensed under GNU General Public License v2
- * (see COPYING for full license text)
- */
-
-#define USE_THE_REPOSITORY_VARIABLE
-
-#include "cgit.h"
-#include "ui-ci.h"
-#include "html.h"
-#include "ui-shared.h"
-
-/* Memoized outcome of resolving the ci url for this request: -1 while
- * unresolved, 0 when there is no ci url for the current ref, and 1 when
- * ci_url holds the url to redirect to.
- */
-static int ci_resolved = -1;
-static char *ci_url;
-
-static int ref_is_tag(const char *ref)
-{
- struct strbuf fullref = STRBUF_INIT;
- struct object_id oid;
- int is_tag;
-
- strbuf_addf(&fullref, "refs/tags/%s", ref);
- is_tag = !repo_get_oid(the_repository, fullref.buf, &oid);
- strbuf_release(&fullref);
- return is_tag;
-}
-
-/* Append the repository url with any ".git" suffix removed and all
- * slashes replaced by dashes, e.g. "sayauz/web.git" becomes
- * "sayauz-web".
- */
-static void add_repo_slug(struct strbuf *buf, const char *url)
-{
- size_t len, i;
-
- if (!strip_suffix(url, ".git", &len))
- len = strlen(url);
- for (i = 0; i < len; i++)
- strbuf_addch(buf, url[i] == '/' ? '-' : url[i]);
-}
-
-static char *expand_ci_url(const char *template)
-{
- const char *p, *rest;
- struct strbuf buf = STRBUF_INIT;
-
- for (p = template; *p; p++) {
- if (*p != '$') {
- strbuf_addch(&buf, *p);
- continue;
- }
- if (skip_prefix(p, "$ref", &rest))
- strbuf_addstr(&buf, ctx.qry.head);
- else if (skip_prefix(p, "$repo", &rest))
- strbuf_addstr(&buf, ctx.repo->url);
- else if (skip_prefix(p, "$slug", &rest))
- add_repo_slug(&buf, ctx.repo->url);
- else if (skip_prefix(p, "$$", &rest))
- strbuf_addch(&buf, '$');
- else {
- strbuf_addch(&buf, '$');
- continue;
- }
- p = rest - 1;
- }
- return strbuf_detach(&buf, NULL);
-}
-
-/* Ask the ci filter whether the pipeline denoted by url actually exists.
- * The filter must not write to stdout, and signals "yes" by exiting with
- * a zero status.
- */
-static int ci_filter_accepts(const char *refkind, const char *url)
-{
- struct cgit_filter *filter = ctx.repo->ci_filter;
-
- if (!filter)
- return 1;
- if (cgit_open_filter(filter, ctx.qry.head, refkind, url))
- return 0;
- return !cgit_close_filter(filter);
-}
-
-static void resolve_ci_url(void)
-{
- const char *template, *refkind;
-
- if (ci_resolved != -1)
- return;
- ci_resolved = 0;
-
- if (!ctx.repo || !ctx.qry.head || !cgit_have_repository())
- return;
-
- if (ref_is_tag(ctx.qry.head)) {
- refkind = "tag";
- template = ctx.repo->ci_tag_url;
- } else {
- refkind = "branch";
- template = ctx.repo->ci_branch_url;
- }
- if (!template)
- template = ctx.repo->ci_url;
- if (!template)
- return;
-
- ci_url = expand_ci_url(template);
- if (!ci_filter_accepts(refkind, ci_url)) {
- free(ci_url);
- ci_url = NULL;
- return;
- }
- ci_resolved = 1;
-}
-
-int cgit_ci_available(void)
-{
- resolve_ci_url();
- return ci_resolved == 1;
-}
-
-void cgit_print_ci(void)
-{
- resolve_ci_url();
-
- if (ci_resolved != 1) {
- cgit_print_error_page(404, "Not found",
- "No ci url available for %s",
- ctx.qry.head);
- return;
- }
-
- /* The expanded template is emitted verbatim rather than through
- * cgit_redirect(), which percent-encodes characters such as '?',
- * '=' and '%' that are meaningful in a ci url. Refuse anything
- * which could be used to smuggle in extra response headers.
- */
- if (strpbrk(ci_url, "\r\n")) {
- cgit_print_error_page(500, "Internal server error",
- "Malformed ci url");
- return;
- }
-
- htmlf("Status: 302 Found\nLocation: %s\n\n", ci_url);
-}