diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--source/ui-commit.c57
-rwxr-xr-xtests/t0206-trailers.sh22
2 files changed, 57 insertions, 22 deletions
diff --git a/source/ui-commit.c b/source/ui-commit.c
index b67f5db..ba079a0 100644
--- a/source/ui-commit.c
+++ b/source/ui-commit.c
@@ -1,9 +1,10 @@
/*
* The commit page, which shows one commit on its own and is where the log and
- * the ref listings link. It renders the idents, the object ids, the message
- * and any note, then hands off to ui-diff.c for the diff against the first
- * parent. Free text and addresses are written through the repository's commit
- * and email filters, so a site can rewrite either on the way out.
+ * the ref listings link. It renders the idents, the object ids, the message,
+ * the trailer table when the repository asks for one and any note, then hands
+ * off to ui-diff.c for the diff against the first parent. Free text and
+ * addresses are written through the repository's commit, trailer and email
+ * filters, so a site can rewrite any of them on the way out.
*/
#define USE_THE_REPOSITORY_VARIABLE
@@ -19,6 +20,7 @@
#include "ui-shared.h"
#include <list.h>
+#include <mailmap.h>
#include <trailer.h>
// The diff below the message is always taken against the first parent alone,
@@ -81,30 +83,46 @@ static void print_filtered_text(const char *text)
/*
* A value shaped like an ident is written the way the author row is, through
- * the email filter. Anything else goes through the trailer filter when one is
- * set, and otherwise through the commit filter, so the links a site already
- * draws in message text keep appearing on trailer lines.
+ * the mailmap and the email filter, and anything after the address, such as a
+ * role in parentheses, follows as text. Anything else goes through the trailer
+ * filter when one is set, and otherwise through the commit filter, so the
+ * links a site already draws in message text keep appearing on trailer lines.
*/
static void print_trailer_value(const char *key, const char *value)
{
struct ident_split ident;
- struct strbuf name = STRBUF_INIT, email = STRBUF_INIT;
+ struct string_list *map;
+ struct strbuf email = STRBUF_INIT;
+ const char *name, *mail, *rest;
+ size_t name_len, mail_len;
if (!split_ident_line(&ident, value, strlen(value)) &&
memchr(ident.mail_begin, '@', ident.mail_end - ident.mail_begin)) {
- strbuf_add(&name, ident.name_begin, ident.name_end - ident.name_begin);
+ name = ident.name_begin;
+ name_len = ident.name_end - ident.name_begin;
+ mail = ident.mail_begin;
+ mail_len = ident.mail_end - ident.mail_begin;
+ map = cgit_mailmap();
+ if (map)
+ map_user(map, &mail, &mail_len, &name, &name_len);
strbuf_addch(&email, '<');
- strbuf_add(&email, ident.mail_begin, ident.mail_end - ident.mail_begin);
+ strbuf_add(&email, mail, mail_len);
strbuf_addch(&email, '>');
cgit_open_filter(ctx.repo->email_filter, email.buf, "commit");
- html_txt(name.buf);
+ html_ntxt(name, name_len);
if (ctx.cfg.enable_plain_email) {
html(" ");
html_txt(email.buf);
}
cgit_close_filter(ctx.repo->email_filter);
- strbuf_release(&name);
strbuf_release(&email);
+ rest = ident.mail_end + 1;
+ while (isspace((unsigned char)*rest))
+ rest++;
+ if (*rest) {
+ html(" ");
+ html_txt(rest);
+ }
} else if (ctx.repo->trailer_filter) {
cgit_open_filter(ctx.repo->trailer_filter, key, "commit");
html_txt(value);
@@ -114,14 +132,15 @@ static void print_trailer_value(const char *key, const char *value)
}
/*
- * One row per trailer, except that a run of trailers sharing a key becomes a
- * single row listing every value. A line git kept in the block without being
- * able to split it, such as a cherry-pick note, gets a row of its own.
+ * One row per trailer, except that a run of trailers sharing a key, compared
+ * without regard to case, becomes a single row listing every value. A line git
+ * kept in the block without a value, such as a cherry-pick note or a key with
+ * nothing after its colon, gets a row of its own as written.
*/
static void print_trailers(const char *msg)
{
struct trailer_iterator iter;
- struct strbuf key = STRBUF_INIT;
+ struct strbuf key = STRBUF_INIT, line = STRBUF_INIT;
int open = 0;
html("<table class='commit-trailers'>\n");
@@ -131,8 +150,11 @@ static void print_trailers(const char *msg)
if (open)
html("</td></tr>\n");
open = 0;
+ strbuf_reset(&line);
+ strbuf_addstr(&line, iter.raw);
+ strbuf_rtrim(&line);
html("<tr><td colspan='2'>");
- print_filtered_text(iter.key.buf);
+ print_filtered_text(line.buf);
html("</td></tr>\n");
continue;
}
@@ -155,6 +177,7 @@ static void print_trailers(const char *msg)
html("</table>\n");
trailer_iterator_release(&iter);
strbuf_release(&key);
+ strbuf_release(&line);
}
/*
diff --git a/tests/t0206-trailers.sh b/tests/t0206-trailers.sh
index fe96c5a..75c59a1 100755
--- a/tests/t0206-trailers.sh
+++ b/tests/t0206-trailers.sh
@@ -4,7 +4,8 @@
# trailer block is rendered with enable-trailers on, through the exec dump
# filter as both trailer filter and email filter so the arguments each one
# receives show in the page, then with the flag off globally and off for the
-# one repository. A commit with no block is checked to get no table.
+# one repository. The repository carries a mailmap, so the sign-off idents are
+# checked to follow it. A commit with no block is checked to get no table.
test_description='Check the commit trailers table'
CGIT_TEST_NO_CREATE_REPOS=YesPlease
@@ -15,7 +16,8 @@ test_expect_success 'create a repository with a trailer-shaped message' '
(
cd repos/trailers &&
echo content >file &&
- git add file &&
+ echo "Mapped Name <mapped@example.com> <author@example.com>" >.mailmap &&
+ git add file .mailmap &&
git commit -m "plain commit" &&
echo more >>file &&
git add file &&
@@ -26,7 +28,9 @@ test_expect_success 'create a repository with a trailer-shaped message' '
Fixes: 1234567 ("plain commit")
Signed-off-by: A U Thor <author@example.com>
- Signed-off-by: C O Mitter <committer@example.com>
+ signed-off-by: C O Mitter <committer@example.com>
+ Acked-by: Some One <some@example.com> (maintainer)
+ Reported-by:
(cherry picked from commit deadbeefcafe1234)
Link: https://example.com/?a=1&b=2
EOF
@@ -55,8 +59,16 @@ test_expect_success 'a value reaches the trailer filter with its key and page' '
grep "<tr><th>Fixes</th><td>Fixes commit 1234567 (.PLAIN COMMIT.)</td></tr>" tmp
'
-test_expect_success 'a run of one key collapses into one row through the email filter' '
- grep "<tr><th>Signed-off-by</th><td><author@example.com> commit A U THOR &LT;AUTHOR@EXAMPLE.COM&GT;<br><committer@example.com> commit C O MITTER &LT;COMMITTER@EXAMPLE.COM&GT;</td></tr>" tmp
+test_expect_success 'a run of one key, whatever its case, collapses into one row' '
+ grep "<tr><th>Signed-off-by</th><td><mapped@example.com> commit MAPPED NAME &LT;MAPPED@EXAMPLE.COM&GT;<br><committer@example.com> commit C O MITTER &LT;COMMITTER@EXAMPLE.COM&GT;</td></tr>" tmp
+'
+
+test_expect_success 'an ident follows the mailmap and keeps what trails the address' '
+ grep "<tr><th>Acked-by</th><td><some@example.com> commit SOME ONE &LT;SOME@EXAMPLE.COM&GT; (maintainer)</td></tr>" tmp
+'
+
+test_expect_success 'a key with no value is printed as written' '
+ grep "<tr><td colspan=.2.>Reported-by:</td></tr>" tmp
'
test_expect_success 'a line git could not split gets a row of its own' '