[PATCH 3/3] Add support for git's mailmap.
Jason A. Smith
smithj4 at bnl.gov
Sat Feb 25 17:12:36 CET 2017
If a mailmap file is present in the repo, it will be used to coalesce
commits by the same person, just like git does. When no mailmap file is
found then it functions as before.
Signed-off-by: Jason A. Smith <smithj4 at bnl.gov>
---
cgit.h | 3 +++
parsing.c | 21 +++++++++++++++++++++
ui-atom.c | 20 ++++++++++++++------
ui-commit.c | 22 ++++++++++++++++------
ui-log.c | 11 +++++++++--
ui-refs.c | 32 ++++++++++++++++++++++++++------
ui-stats.c | 13 ++++++++++---
ui-tag.c | 14 ++++++++++----
8 files changed, 109 insertions(+), 27 deletions(-)
diff --git a/cgit.h b/cgit.h
index 204e59e..e4e070f 100644
--- a/cgit.h
+++ b/cgit.h
@@ -24,6 +24,7 @@
#include <utf8.h>
#include <notes.h>
#include <graph.h>
+#include <mailmap.h>
/* Add isgraph(x) to Git's sane ctype support (see git-compat-util.h) */
#undef isgraph
@@ -369,6 +370,8 @@ extern char *fmtalloc(const char *format,...);
extern struct commitinfo *cgit_parse_commit(struct commit *commit);
extern struct taginfo *cgit_parse_tag(struct tag *tag);
extern void cgit_parse_url(const char *url);
+extern int cgit_read_mailmap(struct string_list *map);
+extern int cgit_map_user(struct string_list *map, const char **email, const char **name);
extern const char *cgit_repobasename(const char *reponame);
diff --git a/parsing.c b/parsing.c
index 352338d..c9619a0 100644
--- a/parsing.c
+++ b/parsing.c
@@ -84,6 +84,27 @@ static void parse_user(const char *t, char **name, char **email, unsigned long *
}
}
+int cgit_read_mailmap(struct string_list *map)
+{
+ int ret;
+
+ ret = read_mailmap(map, NULL);
+ if (ret)
+ fprintf(stderr, "Error reading mailmap: read_mailmap() returned: %d\n", ret);
+ return ret;
+}
+
+int cgit_map_user(struct string_list *map, const char **email, const char **name)
+{
+ size_t emaillen, namelen;
+ int ret;
+
+ emaillen = strlen(*email);
+ namelen = strlen(*name);
+ ret = map_user(map, email, &emaillen, name, &namelen);
+ return ret;
+}
+
#ifdef NO_ICONV
#define reencode(a, b, c)
#else
diff --git a/ui-atom.c b/ui-atom.c
index 7c17d6a..9d541ba 100644
--- a/ui-atom.c
+++ b/ui-atom.c
@@ -11,13 +11,18 @@
#include "html.h"
#include "ui-shared.h"
-static void add_entry(struct commit *commit, const char *host)
+static void add_entry(struct commit *commit, const char *host,
+ struct string_list *mailmap)
{
char delim = '&';
char *hex;
struct commitinfo *info;
+ const char *author, *author_email;
info = cgit_parse_commit(commit);
+ author = info->author;
+ author_email = info->author_email;
+ cgit_map_user(mailmap, &author_email, &author);
hex = oid_to_hex(&commit->object.oid);
html("<entry>\n");
html("<title>");
@@ -28,14 +33,14 @@ static void add_entry(struct commit *commit, const char *host)
date_mode_from_type(DATE_ISO8601_STRICT)));
html("</updated>\n");
html("<author>\n");
- if (info->author) {
+ if (author) {
html("<name>");
- html_txt(info->author);
+ html_txt(author);
html("</name>\n");
}
- if (info->author_email && !ctx.cfg.noplainemail) {
+ if (author_email && !ctx.cfg.noplainemail) {
html("<email>");
- html_txt(info->author_email);
+ html_txt(author_email);
html("</email>\n");
}
html("</author>\n");
@@ -78,6 +83,7 @@ void cgit_print_atom(char *tip, char *path, int max_count)
const char *argv[] = {NULL, tip, NULL, NULL, NULL};
struct commit *commit;
struct rev_info rev;
+ struct string_list mailmap = STRING_LIST_INIT_NODUP;
int argc = 2;
if (ctx.qry.show_all)
@@ -97,6 +103,8 @@ void cgit_print_atom(char *tip, char *path, int max_count)
rev.show_root_diff = 0;
rev.max_count = max_count;
setup_revisions(argc, argv, &rev, NULL);
+ cgit_read_mailmap(&mailmap);
+ rev.mailmap = &mailmap;
prepare_revision_walk(&rev);
host = cgit_hosturl();
@@ -128,7 +136,7 @@ void cgit_print_atom(char *tip, char *path, int max_count)
free(repourl);
}
while ((commit = get_revision(&rev)) != NULL) {
- add_entry(commit, host);
+ add_entry(commit, host, &mailmap);
free_commit_buffer(commit);
free_commit_list(commit->parents);
commit->parents = NULL;
diff --git a/ui-commit.c b/ui-commit.c
index dccb5f3..491d800 100644
--- a/ui-commit.c
+++ b/ui-commit.c
@@ -18,8 +18,11 @@ void cgit_print_commit(char *hex, const char *prefix)
struct commit *commit, *parent;
struct commitinfo *info, *parent_info;
struct commit_list *p;
+ struct string_list mailmap = STRING_LIST_INIT_NODUP;
struct strbuf notes = STRBUF_INIT;
struct object_id oid;
+ const char *author, *author_email;
+ const char *committer, *committer_email;
char *tmp, *tmp2;
int parents = 0;
@@ -38,6 +41,13 @@ void cgit_print_commit(char *hex, const char *prefix)
return;
}
info = cgit_parse_commit(commit);
+ cgit_read_mailmap(&mailmap);
+ author = info->author;
+ author_email = info->author_email;
+ cgit_map_user(&mailmap, &author_email, &author);
+ committer = info->committer;
+ committer_email = info->committer_email;
+ cgit_map_user(&mailmap, &committer_email, &committer);
format_display_notes(oid.hash, ¬es, PAGE_ENCODING, 0);
@@ -47,11 +57,11 @@ void cgit_print_commit(char *hex, const char *prefix)
cgit_print_diff_ctrls();
html("<table summary='commit info' class='commit-info'>\n");
html("<tr><th>author</th><td>");
- cgit_open_email_filter(info->author_email, "commit");
- html_txt(info->author);
+ cgit_open_email_filter(author_email, "commit");
+ html_txt(author);
if (!ctx.cfg.noplainemail) {
html(" <");
- html_txt(info->author_email);
+ html_txt(author_email);
html(">");
}
cgit_close_filter(ctx.repo->email_filter);
@@ -60,11 +70,11 @@ void cgit_print_commit(char *hex, const char *prefix)
cgit_date_mode(DATE_ISO8601)));
html("</td></tr>\n");
html("<tr><th>committer</th><td>");
- cgit_open_email_filter(info->committer_email, "commit");
- html_txt(info->committer);
+ cgit_open_email_filter(committer_email, "commit");
+ html_txt(committer);
if (!ctx.cfg.noplainemail) {
html(" <");
- html_txt(info->committer_email);
+ html_txt(committer_email);
html(">");
}
cgit_close_filter(ctx.repo->email_filter);
diff --git a/ui-log.c b/ui-log.c
index b78f56f..21a3497 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -171,6 +171,7 @@ static int show_commit(struct commit *commit, struct rev_info *revs)
static void print_commit(struct commit *commit, struct rev_info *revs)
{
struct commitinfo *info;
+ const char *author, *author_email;
int columns = revs->graph ? 4 : 3;
struct strbuf graphbuf = STRBUF_INIT;
struct strbuf msgbuf = STRBUF_INIT;
@@ -238,8 +239,11 @@ static void print_commit(struct commit *commit, struct rev_info *revs)
oid_to_hex(&commit->object.oid), ctx.qry.vpath);
show_commit_decorations(commit);
html("</td><td>");
- cgit_open_email_filter(info->author_email, "log");
- html_txt(info->author);
+ author = info->author;
+ author_email = info->author_email;
+ cgit_map_user(revs->mailmap, &author_email, &author);
+ cgit_open_email_filter(author_email, "log");
+ html_txt(author);
cgit_close_filter(ctx.repo->email_filter);
if (revs->graph) {
@@ -361,6 +365,7 @@ static char *next_token(char **src)
void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern,
char *path, int pager, int commit_graph, int commit_sort)
{
+ struct string_list mailmap = STRING_LIST_INIT_NODUP;
struct rev_info rev;
struct commit *commit;
struct argv_array rev_argv = ARGV_ARRAY_INIT;
@@ -444,6 +449,8 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern
DIFF_XDL_SET(&rev.diffopt, IGNORE_WHITESPACE);
compile_grep_patterns(&rev.grep_filter);
+ cgit_read_mailmap(&mailmap);
+ rev.mailmap = &mailmap;
prepare_revision_walk(&rev);
if (pager) {
diff --git a/ui-refs.c b/ui-refs.c
index 0c4eef9..f645d7d 100644
--- a/ui-refs.c
+++ b/ui-refs.c
@@ -11,6 +11,8 @@
#include "html.h"
#include "ui-shared.h"
+static struct string_list mailmap = STRING_LIST_INIT_DUP;
+
static inline int cmp_age(int age1, int age2)
{
/* age1 and age2 are assumed to be non-negative */
@@ -57,6 +59,7 @@ static int cmp_tag_age(const void *a, const void *b)
static int print_branch(struct refinfo *ref)
{
struct commitinfo *info = ref->commit;
+ const char *author, *author_email;
char *name = (char *)ref->refname;
if (!info)
@@ -67,10 +70,13 @@ static int print_branch(struct refinfo *ref)
html("</td><td>");
if (ref->object->type == OBJ_COMMIT) {
+ author = info->author;
+ author_email = info->author_email;
+ cgit_map_user(&mailmap, &author_email, &author);
cgit_commit_link(info->subject, NULL, NULL, name, NULL, NULL);
html("</td><td>");
- cgit_open_email_filter(info->author_email, "refs");
- html_txt(info->author);
+ cgit_open_email_filter(author_email, "refs");
+ html_txt(author);
cgit_close_filter(ctx.repo->email_filter);
html("</td><td colspan='2'>");
cgit_print_age(info->committer_date, info->committer_tz, -1);
@@ -122,6 +128,8 @@ static int print_tag(struct refinfo *ref)
{
struct tag *tag = NULL;
struct taginfo *info = NULL;
+ const char *tagger, *tagger_email;
+ const char *author, *author_email;
char *name = (char *)ref->refname;
struct object *obj = ref->object;
@@ -143,13 +151,19 @@ static int print_tag(struct refinfo *ref)
html("</td><td>");
if (info) {
if (info->tagger) {
- cgit_open_email_filter(info->tagger_email, "refs");
- html_txt(info->tagger);
+ tagger = info->tagger;
+ tagger_email = info->tagger_email;
+ cgit_map_user(&mailmap, &tagger_email, &tagger);
+ cgit_open_email_filter(tagger_email, "refs");
+ html_txt(tagger);
cgit_close_filter(ctx.repo->email_filter);
}
} else if (ref->object->type == OBJ_COMMIT) {
- cgit_open_email_filter(ref->commit->author_email, "refs");
- html_txt(ref->commit->author);
+ author = ref->commit->author;
+ author_email = ref->commit->author_email;
+ cgit_map_user(&mailmap, &author_email, &author);
+ cgit_open_email_filter(author_email, "refs");
+ html_txt(author);
cgit_close_filter(ctx.repo->email_filter);
}
html("</td><td colspan='2'>");
@@ -194,6 +208,9 @@ void cgit_print_branches(int maxcount)
if (ctx.repo->branch_sort == 0)
qsort(list.refs, maxcount, sizeof(*list.refs), cmp_ref_name);
+ if (!mailmap.items) {
+ cgit_read_mailmap(&mailmap);
+ }
for (i = 0; i < maxcount; i++)
print_branch(list.refs[i]);
@@ -219,6 +236,9 @@ void cgit_print_tags(int maxcount)
else if (maxcount > list.count)
maxcount = list.count;
print_tag_header();
+ if (!mailmap.items) {
+ cgit_read_mailmap(&mailmap);
+ }
for (i = 0; i < maxcount; i++)
print_tag(list.refs[i]);
diff --git a/ui-stats.c b/ui-stats.c
index 7acd358..12eedee 100644
--- a/ui-stats.c
+++ b/ui-stats.c
@@ -159,9 +159,10 @@ const char *cgit_find_stats_periodname(int idx)
}
static void add_commit(struct string_list *authors, struct commit *commit,
- const struct cgit_period *period)
+ const struct cgit_period *period, struct string_list *mailmap)
{
struct commitinfo *info;
+ const char *author_name, *author_email;
struct string_list_item *author, *item;
struct authorstat *authorstat;
struct string_list *items;
@@ -171,7 +172,10 @@ static void add_commit(struct string_list *authors, struct commit *commit,
uintptr_t *counter;
info = cgit_parse_commit(commit);
- tmp = xstrdup(info->author);
+ author_name = info->author;
+ author_email = info->author_email;
+ cgit_map_user(mailmap, &author_email, &author_name);
+ tmp = xstrdup(author_name);
author = string_list_insert(authors, tmp);
if (!author->util)
author->util = xcalloc(1, sizeof(struct authorstat));
@@ -209,6 +213,7 @@ static int cmp_total_commits(const void *a1, const void *a2)
static struct string_list collect_stats(const struct cgit_period *period)
{
struct string_list authors;
+ struct string_list mailmap = STRING_LIST_INIT_NODUP;
struct rev_info rev;
struct commit *commit;
const char *argv[] = {NULL, ctx.qry.head, NULL, NULL, NULL, NULL};
@@ -237,10 +242,12 @@ static struct string_list collect_stats(const struct cgit_period *period)
rev.verbose_header = 1;
rev.show_root_diff = 0;
setup_revisions(argc, argv, &rev, NULL);
+ cgit_read_mailmap(&mailmap);
+ rev.mailmap = &mailmap;
prepare_revision_walk(&rev);
memset(&authors, 0, sizeof(authors));
while ((commit = get_revision(&rev)) != NULL) {
- add_commit(&authors, commit, period);
+ add_commit(&authors, commit, period, &mailmap);
free_commit_buffer(commit);
free_commit_list(commit->parents);
commit->parents = NULL;
diff --git a/ui-tag.c b/ui-tag.c
index ad7854e..cccfc53 100644
--- a/ui-tag.c
+++ b/ui-tag.c
@@ -44,6 +44,8 @@ void cgit_print_tag(char *revname)
struct strbuf fullref = STRBUF_INIT;
struct object_id oid;
struct object *obj;
+ struct string_list mailmap = STRING_LIST_INIT_NODUP;
+ const char *tagger, *tagger_email;
if (!revname)
revname = ctx.qry.head;
@@ -82,12 +84,16 @@ void cgit_print_tag(char *revname)
html("</td></tr>\n");
}
if (info->tagger) {
+ cgit_read_mailmap(&mailmap);
+ tagger = info->tagger;
+ tagger_email = info->tagger_email;
+ cgit_map_user(&mailmap, &tagger_email, &tagger);
html("<tr><td>tagged by</td><td>");
- cgit_open_email_filter(info->tagger_email, "tag");
- html_txt(info->tagger);
- if (info->tagger_email && !ctx.cfg.noplainemail) {
+ cgit_open_email_filter(tagger_email, "tag");
+ html_txt(tagger);
+ if (tagger_email && !ctx.cfg.noplainemail) {
html(" <");
- html_txt(info->tagger_email);
+ html_txt(tagger_email);
html(">");
}
cgit_close_filter(ctx.repo->email_filter);
--
2.9.3
More information about the CGit
mailing list