aboutsummaryrefslogtreecommitdiff
diff options
from:
to:
context:
space:
mode:
-rw-r--r--README.md2
-rwxr-xr-xtests/t0106-diff.sh56
-rw-r--r--ui-diff.c66
3 files changed, 123 insertions, 1 deletions
diff --git a/README.md b/README.md
index 68db236..1e13a37 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,8 @@ This is a custom expansion to cgit. Its most prominent changes by now are:
* 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
diff --git a/tests/t0106-diff.sh b/tests/t0106-diff.sh
index 82b645e..0c167d4 100755
--- a/tests/t0106-diff.sh
+++ b/tests/t0106-diff.sh
@@ -16,4 +16,60 @@ 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 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 '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_done
diff --git a/ui-diff.c b/ui-diff.c
index 6cfa697..ae4c9de 100644
--- a/ui-diff.c
+++ b/ui-diff.c
@@ -1,6 +1,10 @@
/* 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)
@@ -336,6 +340,32 @@ 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>");
+}
+
void cgit_print_diff_ctrls(void)
{
int i, curr;
@@ -343,9 +373,43 @@ void cgit_print_diff_ctrls(void)
html("<div class='cgit-panel'>");
html("<b>diff options</b>");
html("<form method='get'>");
- cgit_add_hidden_formfields(1, 0, ctx.qry.page);
+ /*
+ * Emit the same hidden fields as cgit_add_hidden_formfields(), except
+ * id/id2, which are carried by the ref-picker selects below.
+ */
+ 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("<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.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);
+ html("</td></tr><tr>");
+ html("<td class='label'>to:</td>");
+ html("<td class='ctrl'>");
+ cgit_print_ref_select("id", new_ref);
+ html("</td></tr>");
+ }
+
html("<tr>");
html("<td class='label'>context:</td>");
html("<td class='ctrl'>");