diff options
Diffstat (limited to '')
-rw-r--r--README.txt2
-rw-r--r--assets/cgit.css15
-rw-r--r--source/ui-tag.c29
-rwxr-xr-xtests/t0005-markup.sh21
-rwxr-xr-xtests/t0113-tag.sh31
5 files changed, 94 insertions, 4 deletions
diff --git a/README.txt b/README.txt
index db55ec9..e160af5 100644
--- a/README.txt
+++ b/README.txt
@@ -101,6 +101,8 @@ script added through the css and js options has stable hooks to work with.
A character in a file that a browser would start a new line at, though git
does not, such as a carriage return with no line feed after it, is shown as
an escape sequence in span.escape.
+* A signed tag's signature, of whatever kind git reads, is folded away in
+ details.signature after the tag's message.
* The bundled auth filters write their login form as form.login, with
p.login-error above it after a failed login.
* Colours, fonts and metrics are custom properties on div#cgit, so a theme can
diff --git a/assets/cgit.css b/assets/cgit.css
index 7a4472a..49b00ab 100644
--- a/assets/cgit.css
+++ b/assets/cgit.css
@@ -875,6 +875,21 @@ div#cgit table.commit-trailers {
margin-top: 1em;
}
+div#cgit details.signature {
+ margin-top: 1em;
+}
+
+div#cgit details.signature summary {
+ color: var(--muted);
+ cursor: pointer;
+}
+
+div#cgit details.signature pre {
+ margin: 0.5em 0 0;
+ font-family: var(--font-mono);
+ overflow-x: auto;
+}
+
div#cgit table.commit-trailers th {
text-align: left;
font-weight: normal;
diff --git a/source/ui-tag.c b/source/ui-tag.c
index 5fa8a17..246ff12 100644
--- a/source/ui-tag.c
+++ b/source/ui-tag.c
@@ -11,6 +11,7 @@
#include "cgit.h"
#include "filter.h"
+#include "gpg-interface.h"
#include "html.h"
#include "parsing.h"
#include "shared.h"
@@ -71,17 +72,31 @@ static void print_download_row(const char *revname, const struct object *obj)
}
/*
- * Cutting the subject out terminates the message in place, which is safe only
- * because the caller frees it straight after. The blank lines between the
- * subject and the body are skipped, as the commit page skips them.
+ * Cutting the subject and the signature out terminates the message in place,
+ * which is safe only because the caller frees it straight after. The blank
+ * lines between the subject and the body are skipped, as the commit page skips
+ * them.
*/
static void print_message(char *msg)
{
- char *newline, *body;
+ char *newline, *body, *signature = NULL;
+ size_t len, start;
if (!msg)
return;
+ // git finds the signature of any kind it can sign with, PGP, SSH or
+ // X.509, and it goes in a fold after the message, since its armour
+ // would otherwise run on for more lines than the message itself.
+ len = strlen(msg);
+ start = parse_signed_buffer(msg, len);
+ if (start < len) {
+ signature = xstrdup(msg + start);
+ while (start > 0 && msg[start - 1] == '\n')
+ start--;
+ msg[start] = '\0';
+ }
+
html("<div class='commit-subject'>");
newline = strchr(msg, '\n');
if (newline)
@@ -96,6 +111,12 @@ static void print_message(char *msg)
html_txt(body);
html("</div>");
}
+ if (signature) {
+ html("<details class='signature'><summary>Signature</summary><pre>");
+ html_txt(signature);
+ html("</pre></details>");
+ free(signature);
+ }
}
static void print_annotated_tag(const char *revname, const struct object_id *oid)
diff --git a/tests/t0005-markup.sh b/tests/t0005-markup.sh
index 5d802a7..0ba8ded 100755
--- a/tests/t0005-markup.sh
+++ b/tests/t0005-markup.sh
@@ -194,4 +194,25 @@ test_expect_success 'embedded mode marks the root' '
grep "<div id=.cgit. class=.cgit-embedded. data-page=.summary." tmp
'
+test_expect_success 'a signed tag folds its signature away' '
+ (
+ cd repos/hooks &&
+ {
+ echo "object $(git rev-parse HEAD)" &&
+ echo "type commit" &&
+ echo "tag signed" &&
+ echo "tagger C O Mitter <committer@example.com> 1700000000 +0000" &&
+ echo &&
+ echo "Signed" &&
+ echo &&
+ echo "-----BEGIN SSH SIGNATURE-----" &&
+ echo "U1NIU0lH" &&
+ echo "-----END SSH SIGNATURE-----"
+ } >signed-tag &&
+ git update-ref refs/tags/signed $(git mktag <signed-tag)
+ ) &&
+ hooks "hooks/tag/&h=signed" >tmp &&
+ grep "<details class=.signature.><summary>Signature</summary>" tmp
+'
+
test_done
diff --git a/tests/t0113-tag.sh b/tests/t0113-tag.sh
index ff50f90..ec6f3c3 100755
--- a/tests/t0113-tag.sh
+++ b/tests/t0113-tag.sh
@@ -59,4 +59,35 @@ test_expect_success 'a tag of anything but a commit offers no download' '
grep ">download<" tmp
'
+# git reads the signature off the end of a tag's message, so a block shaped
+# like one is enough to show it is folded away, with nothing to verify.
+test_expect_success 'a signed tag folds its signature after the message' '
+ (
+ cd repos/foo &&
+ {
+ echo "object $(git rev-parse HEAD)" &&
+ echo "type commit" &&
+ echo "tag signed" &&
+ echo "tagger C O Mitter <committer@example.com> 1700000000 +0000" &&
+ echo &&
+ echo "Signed release" &&
+ echo &&
+ echo "Notes." &&
+ echo &&
+ echo "-----BEGIN PGP SIGNATURE-----" &&
+ echo "iQEzBAABCAAdFiEE" &&
+ echo "-----END PGP SIGNATURE-----"
+ } >signed-tag &&
+ git update-ref refs/tags/signed $(git mktag <signed-tag)
+ ) &&
+ cgit_url "foo/tag/&h=signed" >tmp &&
+ tr -d "\n" <tmp >flat &&
+ grep "<div class=.commit-msg.>Notes.</div><details class=.signature.><summary>Signature</summary><pre>-----BEGIN PGP SIGNATURE-----iQEzBAABCAAdFiEE-----END PGP SIGNATURE-----</pre></details>" flat
+'
+
+test_expect_success 'an unsigned tag has no fold' '
+ cgit_url "foo/tag/&h=v1.0" >tmp &&
+ ! grep "details class=.signature." tmp
+'
+
test_done