diff options
Diffstat (limited to '')
| -rw-r--r-- | README.txt | 2 | |
| -rw-r--r-- | assets/cgit.css | 15 | |
| -rw-r--r-- | source/ui-tag.c | 29 | |
| -rwxr-xr-x | tests/t0005-markup.sh | 21 | |
| -rwxr-xr-x | tests/t0113-tag.sh | 31 |
5 files changed, 94 insertions, 4 deletions
@@ -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 |
