| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | README.md | 12 | ||||
| -rw-r--r-- | cgit.c | 14 | ||||
| -rw-r--r-- | cgit.css | 24 | ||||
| -rw-r--r-- | cgit.h | 4 | ||||
| -rw-r--r-- | cgit.svg | 5 | ||||
| -rw-r--r-- | cgitrc.5.txt | 18 | ||||
| -rw-r--r-- | favicon.svg | 5 | ||||
| -rw-r--r-- | solarized.css | 140 | ||||
| -rwxr-xr-x | tests/t0106-diff.sh | 129 | ||||
| -rw-r--r-- | ui-diff.c | 157 | ||||
| -rw-r--r-- | ui-shared.c | 98 |
12 files changed, 21 insertions, 591 deletions
@@ -87,12 +87,9 @@ install: all $(INSTALL) -m 0755 cgit $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) $(INSTALL) -m 0755 -d $(DESTDIR)$(CGIT_DATA_PATH) $(INSTALL) -m 0644 cgit.css $(DESTDIR)$(CGIT_DATA_PATH)/cgit.css - $(INSTALL) -m 0644 solarized.css $(DESTDIR)$(CGIT_DATA_PATH)/solarized.css $(INSTALL) -m 0644 cgit.js $(DESTDIR)$(CGIT_DATA_PATH)/cgit.js $(INSTALL) -m 0644 cgit.png $(DESTDIR)$(CGIT_DATA_PATH)/cgit.png - $(INSTALL) -m 0644 cgit.svg $(DESTDIR)$(CGIT_DATA_PATH)/cgit.svg $(INSTALL) -m 0644 favicon.ico $(DESTDIR)$(CGIT_DATA_PATH)/favicon.ico - $(INSTALL) -m 0644 favicon.svg $(DESTDIR)$(CGIT_DATA_PATH)/favicon.svg $(INSTALL) -m 0644 robots.txt $(DESTDIR)$(CGIT_DATA_PATH)/robots.txt $(INSTALL) -m 0755 -d $(DESTDIR)$(filterdir) $(COPYTREE) filters/* $(DESTDIR)$(filterdir) @@ -119,12 +116,9 @@ endef uninstall: rm -f $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.css - rm -f $(DESTDIR)$(CGIT_DATA_PATH)/solarized.css rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.js rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.png - rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.svg rm -f $(DESTDIR)$(CGIT_DATA_PATH)/favicon.ico - rm -f $(DESTDIR)$(CGIT_DATA_PATH)/favicon.svg rm -f $(DESTDIR)$(CGIT_DATA_PATH)/robots.txt $(foreach file,$(patsubst filters/%,%,$(shell find filters/ ! -type d)), \ $(call rm_f,$(DESTDIR)$(filterdir)/$(file))) @@ -1,4 +1,4 @@ -## cgitext – CGI for Git extension by Saya Andy +## cgitext - CGI for Git extension by Saya Andy This is a custom expansion to cgit. Its most prominent changes by now are: @@ -6,17 +6,9 @@ This is a custom expansion to cgit. Its most prominent changes by now are: * Theming now relies on CSS variables set in cgit.css, to allow easier custom additions and implicit filter theming. -* Allow to use multiple favicons and of MIME type different from x-icon (f.ex. svg/png/webp). - -* Use vector-based format for favicon and cgit logo and make it default. - -* Include optional solarized.css addon theme. - -* Allow user to pick variable refs for diff in web ui. - The original cgit project is hosted at [git.zx2c4.com](https://git.zx2c4.com/cgit/about/) -## cgit – CGI for Git +## cgit - CGI for Git This is an attempt to create a fast web interface for the Git SCM, using a built-in cache to decrease server I/O pressure. @@ -5,7 +5,6 @@ * * Modified 2026 by Saya Andy: * Always check there is git repo on repo.path - * Allow to include multiple favicons * * Licensed under GNU General Public License v2 * (see COPYING for full license text) @@ -171,7 +170,7 @@ static void config_cb(const char *name, const char *value) else if (!strcmp(name, "js")) string_list_append(&ctx.cfg.js, strdup_first_line(value)); else if (!strcmp(name, "favicon")) - string_list_append(&ctx.cfg.favicon, strdup_first_line(value)); + ctx.cfg.favicon = strdup_first_line(value); else if (!strcmp(name, "footer")) ctx.cfg.footer = strdup_first_line(value); else if (!strcmp(name, "head-include")) @@ -393,14 +392,6 @@ static void querystring_cb(const char *name, const char *value) ctx.qry.ignorews = atoi(value); } else if (!strcmp(name, "follow")) { ctx.qry.follow = atoi(value); - } else if (!strcmp(name, "idoff")) { - ctx.qry.idoff = atoi(value); - if (ctx.qry.idoff < 0) - ctx.qry.idoff = 0; - } else if (!strcmp(name, "id2off")) { - ctx.qry.id2off = atoi(value); - if (ctx.qry.id2off < 0) - ctx.qry.id2off = 0; } } @@ -421,7 +412,8 @@ static void prepare_context(void) ctx.cfg.case_sensitive_sort = 1; ctx.cfg.branch_sort = 0; ctx.cfg.commit_sort = 0; - ctx.cfg.logo = "/cgit.svg"; + ctx.cfg.logo = "/cgit.png"; + ctx.cfg.favicon = "/favicon.ico"; ctx.cfg.local_time = 0; ctx.cfg.enable_http_clone = 1; ctx.cfg.enable_index_owner = 1; @@ -478,14 +478,6 @@ div#cgit div.cgit-panel { margin-top: 1.5em; } -div#cgit form.diff-ctrls div.cgit-panel { - float: none; -} - -div#cgit form.diff-ctrls { - float: right; -} - div#cgit div.cgit-panel table { border-collapse: collapse; border: solid 1px var(--border-mid); @@ -674,22 +666,6 @@ div#cgit a.button { padding: 0em 0.5em; } -div#cgit form.diff-ctrls div.cgit-panel a.button, -div#cgit form.diff-ctrls div.cgit-panel input[type=submit] { - border: solid 1px var(--border-mid); - background-color: var(--bg-hl); -} - -div#cgit form.diff-ctrls div.cgit-panel input[type=submit] { - font-size: 80%; - padding: 0em 0.5em; -} - -div#cgit span.hint { - color: var(--fg-mute); - font-size: 80%; -} - div#cgit a.primary { font-size: 100%; } @@ -181,8 +181,6 @@ struct cgit_query { char *head; char *oid; char *oid2; - int idoff; - int id2off; char *path; char *name; char *url; @@ -207,7 +205,7 @@ struct cgit_config { char *ci_tag_url; char *clone_prefix; char *clone_url; - struct string_list favicon; + char *favicon; char *footer; char *head_include; char *header; diff --git a/cgit.svg b/cgit.svg deleted file mode 100644 index 43fee2c..0000000 --- a/cgit.svg +++ /dev/null @@ -1,5 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="96" height="64" viewBox="0 0 96 64" fill="none" stroke="#a00" stroke-width="5"> - <title>cgit</title> - <path d="M31.5 27.5A9 9 0 0 0 22.5 18.5h-5A9 9 0 0 0 8.5 27.5V38a9 9 0 0 0 9 9h5a9 9 0 0 0 9-9M31.5 38v12.5a8 8 0 0 1-8 8H17a8 8 0 0 1-8-8M46.5 3v5m0 8v33M62.5 9v29.75a7.75 7.75 0 0 0 15.5 0V37"/> - <path stroke-width="4" d="M56 18h25"/> -</svg> diff --git a/cgitrc.5.txt b/cgitrc.5.txt index 527233d..76b2085 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@ -240,14 +240,9 @@ enable-tree-linenumbers:: for plaintext blobs printed in the tree view. Default value: "1". favicon:: - Url used as link to a shortcut icon for cgit. It is suggested to - always include the value "/favicon.ico" since certain browsers will - ignore other values. May be given multiple times, each favicon URL - path is added in the head section of the document in turn, letting - the browser pick the icon it prefers. The mimetype of each icon is - deduced from the extension of its url ("ico", "png", "svg", "gif", - "jpg", "jpeg", "webp" and "avif" are recognized) and emitted as a - "type" attribute. Default value: "/favicon.svg", "/favicon.ico". + Url used as link to a shortcut icon for cgit. It is suggested to use + the value "/favicon.ico" since certain browsers will ignore other + values. Default value: "/favicon.ico". footer:: The content of the file specified with this option will be included @@ -277,7 +272,7 @@ local-time:: logo:: Url which specifies the source of an image which will be used as a logo - on all cgit pages. Default value: "/cgit.svg". + on all cgit pages. Default value: "/cgit.png". logo-link:: Url loaded when clicking on the cgit logo image. If unspecified the @@ -921,10 +916,8 @@ cache-size=1000 # Specify some default clone urls using macro expansion clone-url=git://foo.org/$CGIT_REPO_URL git@foo.org:$CGIT_REPO_URL - # Specify the css url css=/css/cgit.css -css=/css/solarized.css # Add a "ci" tab pointing at a Jenkins multibranch pipeline @@ -964,8 +957,7 @@ enable-log-linecount=1 branch-sort=age -# Add cgit favicons -favicon=/favicon.svg +# Add a cgit favicon favicon=/favicon.ico diff --git a/favicon.svg b/favicon.svg deleted file mode 100644 index 6be3df4..0000000 --- a/favicon.svg +++ /dev/null @@ -1,5 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 52 52" fill="none" stroke-width="6"> - <title>cgit</title> - <g stroke="#f33"><path id="g" d="M37.5 15A9 9 0 0 0 28.5 6h-5A9 9 0 0 0 14.5 15v10.5a9 9 0 0 0 9 9h5a9 9 0 0 0 9-9M37.5 25.5V38a8 8 0 0 1-8 8H23a8 8 0 0 1-8-8"/></g> - <use href="#g" stroke="#a00" stroke-width="4"/> -</svg> diff --git a/solarized.css b/solarized.css deleted file mode 100644 index 2e6e3d4..0000000 --- a/solarized.css +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Solarized theme (Ethan Schoonover) with automatic light/dark selection - * based on the prefers-color-scheme media query. - * - * Must be listed after cgit.css, e.g. - * - * css=/cgit.css - * css=/solarized.css - */ - -:root { - --sol-base03: #002b36; - --sol-base02: #073642; - --sol-base01: #586e75; - --sol-base00: #657b83; - --sol-base0: #839496; - --sol-base1: #93a1a1; - --sol-base2: #eee8d5; - --sol-base3: #fdf6e3; - - --sol-yellow: #b58900; - --sol-orange: #cb4b16; - --sol-red: #dc322f; - --sol-magenta: #d33682; - --sol-violet: #6c71c4; - --sol-blue: #268bd2; - --sol-cyan: #2aa198; - --sol-green: #859900; - - --sol-canvas: var(--sol-base3); - --sol-panel: var(--sol-base2); - --sol-body: var(--sol-base00); - --sol-emph: var(--sol-base01); - --sol-muted: var(--sol-base0); - --sol-secondary: var(--sol-base1); - --sol-shade: var(--sol-base03); - --sol-page: var(--sol-panel); - - --sol-tint-soft: 18%; - --sol-tint: 25%; - --sol-tint-strong: 45%; - - color-scheme: light dark; -} - -@media (prefers-color-scheme: dark) { - :root { - --sol-canvas: var(--sol-base03); - --sol-panel: var(--sol-base02); - --sol-body: var(--sol-base0); - --sol-emph: var(--sol-base1); - --sol-muted: var(--sol-base00); - --sol-secondary: var(--sol-base01); - --sol-shade: var(--sol-base3); - - --sol-tint-soft: 30%; - --sol-tint: 35%; - --sol-tint-strong: 55%; - } -} - -body:has(> div#cgit) { - margin: 0; - background-color: var(--sol-page); -} - -div#cgit { - --bg: var(--sol-canvas); - --bg-zebra: color-mix(in srgb, var(--sol-panel) 40%, var(--sol-canvas)); - --bg-hl: var(--sol-panel); - --bg-hl2: color-mix(in srgb, var(--sol-panel) 85%, var(--sol-shade)); - --fg: var(--sol-body); - --fg-strong: var(--sol-emph); - --fg-mid: var(--sol-body); - --fg-mute: var(--sol-muted); - --fg-dim: var(--sol-secondary); - --fg-faint: color-mix(in srgb, var(--sol-secondary) 65%, var(--sol-canvas)); - --fg-faintest: color-mix(in srgb, var(--sol-secondary) 45%, var(--sol-canvas)); - --fg-on-tint: var(--sol-emph); - --fg-linenum: var(--sol-secondary); - --border: var(--sol-panel); - --border-mid: var(--sol-secondary); - --border-dark: var(--sol-muted); - --border-strong: var(--sol-emph); - - --red: var(--sol-red); - --red-mid: color-mix(in srgb, var(--sol-red) 75%, var(--sol-shade)); - --red-dark: color-mix(in srgb, var(--sol-red) 55%, var(--sol-shade)); - --green: var(--sol-green); - --green-mid: color-mix(in srgb, var(--sol-green) 70%, var(--sol-shade)); - --green-dark: color-mix(in srgb, var(--sol-green) 50%, var(--sol-shade)); - --blue: var(--sol-blue); - --blue-dark: color-mix(in srgb, var(--sol-blue) 70%, var(--sol-shade)); - - --graph-col1: var(--sol-red); - --graph-col2: var(--sol-green); - --graph-col3: var(--sol-yellow); - --graph-col4: var(--sol-blue); - --graph-col5: var(--sol-magenta); - --graph-col6: var(--sol-cyan); - - --graph-add-bg: var(--sol-green); - --graph-rem-bg: var(--sol-red); - - --notes-bg: color-mix(in srgb, var(--sol-yellow) var(--sol-tint-soft), var(--sol-canvas)); - --notes-border: var(--sol-yellow); - --add-bg: color-mix(in srgb, var(--sol-green) var(--sol-tint), var(--sol-canvas)); - --add-bg-dark: color-mix(in srgb, var(--sol-green) var(--sol-tint-strong), var(--sol-canvas)); - --del-bg: color-mix(in srgb, var(--sol-red) var(--sol-tint), var(--sol-canvas)); - --del-bg-dark: color-mix(in srgb, var(--sol-red) var(--sol-tint-strong), var(--sol-canvas)); - --changed-bg: color-mix(in srgb, var(--sol-yellow) var(--sol-tint), var(--sol-canvas)); - --changed-bg-dark: color-mix(in srgb, var(--sol-yellow) var(--sol-tint-strong), var(--sol-canvas)); - --hunk-bg: color-mix(in srgb, var(--sol-blue) var(--sol-tint), var(--sol-canvas)); - - --deco-branch-bg: color-mix(in srgb, var(--sol-green) var(--sol-tint-soft), var(--sol-canvas)); - --deco-branch-border: var(--sol-green); - --deco-tag-bg: color-mix(in srgb, var(--sol-yellow) var(--sol-tint-soft), var(--sol-canvas)); - --deco-tag-border: var(--sol-yellow); - --deco-tag-annotated-bg: color-mix(in srgb, var(--sol-orange) var(--sol-tint-soft), var(--sol-canvas)); - --deco-tag-annotated-border: var(--sol-yellow); - --deco-remote-bg: color-mix(in srgb, var(--sol-violet) var(--sol-tint-soft), var(--sol-canvas)); - --deco-remote-border: var(--sol-violet); - --deco-other-bg: color-mix(in srgb, var(--sol-red) var(--sol-tint-soft), var(--sol-canvas)); - --deco-other-border: var(--sol-red); - - --syn-keyword: var(--sol-emph); - --syn-keyword-alt: var(--sol-blue); - --syn-type: var(--blue-dark); - --syn-string: var(--sol-red); - --syn-string-alt: var(--sol-green); - --syn-escape: var(--sol-magenta); - --syn-comment: var(--sol-secondary); - --syn-number: var(--sol-yellow); - --syn-preproc: var(--green-mid); - --syn-operator: var(--sol-emph); - --syn-interpolation: var(--sol-blue); - --syn-linenum: var(--sol-secondary); - --syn-error: var(--sol-red); - --syn-mark-bg: color-mix(in srgb, var(--sol-yellow) var(--sol-tint), var(--sol-canvas)); -} diff --git a/tests/t0106-diff.sh b/tests/t0106-diff.sh index 0e45087..82b645e 100755 --- a/tests/t0106-diff.sh +++ b/tests/t0106-diff.sh @@ -16,133 +16,4 @@ test_expect_success 'find added line' ' grep "<div class=.add.>+5</div>" tmp ' -test_expect_success 'ref picker: from: select present' ' - grep "<select name=.id2." tmp -' - -test_expect_success 'ref picker: to: select present' ' - grep "<select name=.id." tmp -' - -test_expect_success 'ref picker: from: label present' ' - grep "from:" tmp -' - -test_expect_success 'ref picker: to: label present' ' - grep "to:" tmp -' - -test_expect_success 'ref pickers live in a separate refs panel' ' - grep "<b>diff refs</b>" tmp && - grep "<b>diff options</b>" tmp -' - -test_expect_success 'ref picker: master branch listed' ' - grep "master" tmp -' - -test_expect_success 'ref picker: auto-submit on change' ' - grep "onchange=.this.form.submit()." tmp -' - -test_expect_success 'flip link present' ' - grep "<a title=.swap from and to. class=.button. href=./foo/diff/?" tmp -' - -test_expect_success 'flip link swaps the default refs' ' - grep "/foo/diff/?id2=master&idoff=1" tmp -' - -test_expect_success 'compare two refs: foo/diff?id=master&id2=HEAD' ' - cgit_query "url=foo/diff&id=master&id2=HEAD" >tmp -' - -test_expect_success 'diff with explicit refs shows diffstat' ' - grep "diffstat" tmp -' - -test_expect_success 'diff with oid2 parameter uses it for old ref' ' - cgit_query "url=foo/diff&id=master&id2=HEAD" >tmp && - grep "from:" tmp -' - -test_expect_success 'ref picker: to: shows master when id=master' ' - cgit_query "url=foo/diff&id=master" >tmp && - grep "master" tmp -' - -test_expect_success 'ref picker: from: empty when no id2' ' - cgit_query "url=foo/diff" >tmp && - grep "<select name=.id2." tmp -' - -test_expect_success 'compare initial commit with HEAD' ' - root=$(git --git-dir="$PWD/repos/foo/.git" rev-list --max-parents=0 HEAD) && - cgit_query "url=foo/diff&id=HEAD&id2=$root" >tmp -' - -test_expect_success 'diff with HEAD and root shows content' ' - grep "diffstat" tmp -' - -test_expect_success 'flip link swaps explicit refs' ' - cgit_query "url=foo/diff&id=master&id2=HEAD" >tmp && - grep "/foo/diff/?id=HEAD&id2=master" tmp -' - -test_expect_success 'flip link omits id for a diff against a root commit' ' - root=$(git --git-dir="$PWD/repos/foo/.git" rev-list --max-parents=0 HEAD) && - cgit_query "url=foo/diff&id=$root" >tmp && - grep "href=./foo/diff/?id2=$root." tmp -' - -test_expect_success 'offset input: to: present' ' - grep "name=.idoff." tmp -' - -test_expect_success 'offset input: from: present' ' - grep "name=.id2off." tmp -' - -test_expect_success 'apply button present' ' - grep "value=.apply." tmp -' - -test_expect_success 'offset: idoff steps back the to ref' ' - cgit_query "url=foo/diff&id=master&idoff=1" >tmp && - grep "a/file-4 b/file-4" tmp -' - -test_expect_success 'offset: id2off steps back the from ref' ' - cgit_query "url=foo/diff&id=master&id2=master&id2off=2" >tmp && - grep "a/file-5 b/file-5" tmp -' - -test_expect_success 'offset: filled input and hidden field' ' - cgit_query "url=foo/diff&id=master&idoff=1" >tmp && - grep "title=.N commits back from the selected ref. value=.1.>" tmp && - grep "type=.hidden. name=.idoff. value=.1./>" tmp -' - -test_expect_success 'offset: too large 404s with the stepped rev' ' - cgit_query "url=foo/diff&id=master&id2=master&id2off=9" >tmp && - grep "Bad object name: master~9" tmp -' - -test_expect_success 'empty id2 does not 404' ' - cgit_query "url=foo/diff&id=master&id2=" >tmp && - grep "diffstat" tmp && - ! grep "Bad object name" tmp -' - -test_expect_success 'file link carries the offsets' ' - cgit_query "url=foo/diff&id=master&id2=master&id2off=2" >tmp && - grep "/foo/diff/file-5?id2=master&id2off=2" tmp -' - -test_expect_success 'flip link carries the offsets' ' - cgit_query "url=foo/diff&id=master&id2=master&idoff=1&id2off=2" >tmp && - grep "/foo/diff/?id2=master&idoff=2&id2off=1" tmp -' - test_done @@ -1,10 +1,6 @@ /* ui-diff.c: show diff between two blobs * * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com> - * Copyright (C) 2026 Saya Andy <saya.andy@posteo.com> - * - * Modified 2026 by Saya Andy: - * Select variable refs from web ui for diff * * Licensed under GNU General Public License v2 * (see COPYING for full license text) @@ -340,145 +336,16 @@ static void filepair_cb(struct diff_filepair *pair) cgit_ssdiff_footer(); } -static int print_ref_option(const struct reference *ref, void *cb_data) -{ - const char **sel = (const char **)cb_data; - - html_option(ref->name, ref->name, sel[0]); - return 0; -} - -static void cgit_print_ref_select(const char *name, const char *selected) -{ - /* - * Offer every branch and tag so that any two refs can be compared. - */ - html("<select name='"); - html_attr(name); - html("' onchange='this.form.submit();'>"); - refs_for_each_branch_ref(get_main_ref_store(the_repository), - print_ref_option, (void *)&selected); - if (ctx.repo->enable_remote_branches) - refs_for_each_remote_ref(get_main_ref_store(the_repository), - print_ref_option, (void *)&selected); - refs_for_each_tag_ref(get_main_ref_store(the_repository), - print_ref_option, (void *)&selected); - html("</select>"); -} - -/* - * The number of commits to step back from the selected ref, so that any - * ancestor of a branch or tag can be picked without typing a rev into - * the url by hand. - */ -static void cgit_print_ref_offset(const char *name, int value) -{ - html(" <input type='text' size='2' name='"); - html_attr(name); - html("' title='N commits back from the selected ref'"); - if (value) - htmlf(" value='%d'", value); - html("> <span class='hint'>back</span>"); -} - void cgit_print_diff_ctrls(void) { int i, curr; - html("<form class='diff-ctrls' method='get'>"); - /* - * Emit the same hidden fields as cgit_add_hidden_formfields(), except - * id/id2, which are carried by the ref-picker selects below. One - * form wraps both panels so any submission carries all controls. - */ - if (!ctx.cfg.virtual_root) { - struct strbuf url = STRBUF_INIT; - strbuf_addf(&url, "%s/%s", ctx.qry.repo, ctx.qry.page); - if (ctx.qry.vpath) - strbuf_addf(&url, "/%s", ctx.qry.vpath); - html_hidden("url", url.buf); - strbuf_release(&url); - } - if (ctx.qry.head && ctx.repo->defbranch && - strcmp(ctx.qry.head, ctx.repo->defbranch)) - html_hidden("h", ctx.qry.head); - if (ctx.qry.showmsg) - html_hidden("showmsg", "1"); - - html("<div class='cgit-panel'>"); - html("<b>diff refs</b>"); - html("<table>"); - html("<tr><td colspan='2'/></tr>"); - - /* ref pickers: compare any two refs (branches/tags) */ - { - const char *new_ref = ctx.qry.oid && *ctx.qry.oid ? - ctx.qry.oid : ctx.qry.head; - const char *old_ref = ctx.qry.oid2; - - html("<tr>"); - html("<td class='label'>from:</td>"); - html("<td class='ctrl'>"); - cgit_print_ref_select("id2", old_ref); - cgit_print_ref_offset("id2off", ctx.qry.id2off); - html("</td></tr><tr>"); - html("<td class='label'>to:</td>"); - html("<td class='ctrl'>"); - cgit_print_ref_select("id", new_ref); - cgit_print_ref_offset("idoff", ctx.qry.idoff); - html("</td></tr>"); - - html("<tr><td/><td class='ctrl'>"); - html("<input type='submit' value='apply'>"); - html(" | "); - { - const char *flip_new_ref; - int flip_idoff; - int idoff = ctx.qry.idoff; - int id2off = ctx.qry.id2off; - - if (old_ref && *old_ref) { - /* explicit from ref */ - flip_new_ref = old_ref; - flip_idoff = id2off; - } else if (!is_null_oid(old_rev_oid)) { - /* - * The from rev is the parent of the (stepped) - * to rev, i.e. new_ref~(idoff+1); keep the - * ref name in the url instead of a materialized - * parent sha. - */ - flip_new_ref = new_ref; - flip_idoff = idoff + 1; - } else { - /* root: no from rev to flip to */ - flip_new_ref = NULL; - flip_idoff = 0; - } - - /* - * cgit_diff_link() emits the offsets from ctx.qry; - * swap them around the call so they follow the refs. - */ - ctx.qry.idoff = flip_idoff; - ctx.qry.id2off = idoff; - cgit_diff_link("flip", "swap from and to", "button", - ctx.qry.head, - flip_new_ref, new_ref, - ctx.qry.path); - ctx.qry.idoff = idoff; - ctx.qry.id2off = id2off; - } - html("</td></tr>"); - } - html("</table>"); - html("</div>"); - html("<div class='cgit-panel'>"); html("<b>diff options</b>"); + html("<form method='get'>"); + cgit_add_hidden_formfields(1, 0, ctx.qry.page); html("<table>"); html("<tr><td colspan='2'/></tr>"); - html("<tr>"); html("<td class='label'>context:</td>"); html("<td class='ctrl'>"); @@ -512,8 +379,8 @@ void cgit_print_diff_ctrls(void) html("<tr><td/><td class='ctrl'>"); html("<noscript><input type='submit' value='reload'/></noscript>"); html("</td></tr></table>"); - html("</div>"); html("</form>"); + html("</div>"); } void cgit_print_diff(const char *new_rev, const char *old_rev, @@ -521,7 +388,6 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, { struct commit *commit, *commit2; const struct object_id *old_tree_oid, *new_tree_oid; - struct strbuf new_refbuf = STRBUF_INIT, old_refbuf = STRBUF_INIT; diff_type difftype; /* @@ -536,16 +402,8 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, current_prefix = NULL; } - /* - * An empty rev is the same as no rev; a zero offset means the ref - * itself. - */ - if (!new_rev || !*new_rev) + if (!new_rev) new_rev = ctx.qry.head; - if (ctx.qry.idoff) { - strbuf_addf(&new_refbuf, "%s~%d", new_rev, ctx.qry.idoff); - new_rev = new_refbuf.buf; - } if (repo_get_oid(the_repository, new_rev, new_rev_oid)) { cgit_print_error_page(404, "Not found", "Bad object name: %s", new_rev); @@ -559,12 +417,7 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, } new_tree_oid = get_commit_tree_oid(commit); - if (old_rev && *old_rev) { - if (ctx.qry.id2off) { - strbuf_addf(&old_refbuf, "%s~%d", old_rev, - ctx.qry.id2off); - old_rev = old_refbuf.buf; - } + if (old_rev) { if (repo_get_oid(the_repository, old_rev, old_rev_oid)) { cgit_print_error_page(404, "Not found", "Bad object name: %s", old_rev); diff --git a/ui-shared.c b/ui-shared.c index 9eb48a9..97d1839 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -7,8 +7,6 @@ * Implement ci link tab * Check repo existence * Replace memrchr() for macOS compatibility - * Allow multiple favicons of different mime types to be used - * Include favicon.svg as default * * Licensed under GNU General Public License v2 * (see COPYING for full license text) @@ -494,21 +492,6 @@ void cgit_diff_link(const char *name, const char *title, const char *class, html_url_arg(old_rev); delim = "&"; } - /* - * Emit the ref offsets after the refs so that they follow the - * refs through file-level links; a zero offset means the ref - * itself. - */ - if (ctx.qry.idoff) { - html(delim); - htmlf("idoff=%d", ctx.qry.idoff); - delim = "&"; - } - if (ctx.qry.id2off) { - html(delim); - htmlf("id2off=%d", ctx.qry.id2off); - delim = "&"; - } if (ctx.qry.difftype) { html(delim); htmlf("dt=%d", ctx.qry.difftype); @@ -791,51 +774,6 @@ void cgit_redirect(const char *url, bool permanent) html("\n\n"); } -static const struct { - const char *ext; - const char *mimetype; -} favicon_mimetypes[] = { - { "ico", "image/x-icon" }, - { "png", "image/png" }, - { "svg", "image/svg+xml" }, - { "gif", "image/gif" }, - { "jpg", "image/jpeg" }, - { "jpeg", "image/jpeg" }, - { "webp", "image/webp" }, - { "avif", "image/avif" }, -}; - -/* Deduce the mimetype of a favicon from the extension of its url, ignoring - * any query string or fragment. Returns NULL for unknown extensions. - */ -static const char *favicon_mimetype(const char *url) -{ - const char *p, *end, *ext = NULL; - size_t len; - int i; - - end = strpbrk(url, "?#"); - if (!end) - end = url + strlen(url); - - for (p = url; p < end; p++) { - if (*p == '/') - ext = NULL; - else if (*p == '.') - ext = p + 1; - } - if (!ext) - return NULL; - len = end - ext; - - for (i = 0; i < ARRAY_SIZE(favicon_mimetypes); i++) { - if (strlen(favicon_mimetypes[i].ext) == len && - !strncasecmp(favicon_mimetypes[i].ext, ext, len)) - return favicon_mimetypes[i].mimetype; - } - return NULL; -} - static void print_rel_vcs_link(const char *url) { html("<link rel='vcs-git' href='"); @@ -877,27 +815,6 @@ static int emit_js_link(struct string_list_item *s, void *arg) return 0; } -static int emit_favicon_link(struct string_list_item *s, void *arg) -{ - const char *url = s ? s->string : (const char *)arg; - const char *mimetype; - - /* Do not emit anything if favicon= is specified. */ - if (!*url) - return 0; - - html("<link rel='shortcut icon' href='"); - html_attr(url); - mimetype = favicon_mimetype(url); - if (mimetype) { - html("' type='"); - html_attr(mimetype); - } - html("'/>\n"); - - return 0; -} - void cgit_print_docstart(void) { char *host = cgit_hosturl(); @@ -928,12 +845,11 @@ void cgit_print_docstart(void) else emit_js_link(NULL, "/cgit.js"); - if (ctx.cfg.favicon.items) - for_each_string_list(&ctx.cfg.favicon, emit_favicon_link, NULL); - else - emit_favicon_link(NULL, "/favicon.svg"); - emit_favicon_link(NULL, "/favicon.ico"); - + if (ctx.cfg.favicon && *ctx.cfg.favicon) { + html("<link rel='shortcut icon' href='"); + html_attr(ctx.cfg.favicon); + html("'/>\n"); + } if (host && ctx.repo && ctx.qry.head) { char *fileurl; struct strbuf sb = STRBUF_INIT; @@ -1066,10 +982,6 @@ void cgit_add_hidden_formfields(int incl_head, int incl_search, html_hidden("id", ctx.qry.oid); if (ctx.qry.oid2) html_hidden("id2", ctx.qry.oid2); - if (ctx.qry.idoff) - html_hidden("idoff", fmt("%d", ctx.qry.idoff)); - if (ctx.qry.id2off) - html_hidden("id2off", fmt("%d", ctx.qry.id2off)); if (ctx.qry.showmsg) html_hidden("showmsg", "1"); |