From 086109006f695166daf2934417a20681b0c94ab8 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 12 Dec 2012 06:04:04 -0500 Subject: [PATCH] mailmap: support reading mailmap from blobs In a bare repository, there isn't a simple way to respect an in-tree mailmap without extracting it to a temporary file. This patch provides a config variable, similar to mailmap.file, which reads the mailmap from a blob in the repository. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- Documentation/config.txt | 6 ++++ cache.h | 1 + config.c | 2 ++ mailmap.c | 49 +++++++++++++++++++++++++-- t/t4203-mailmap.sh | 73 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 129 insertions(+), 2 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index bf8f911e1..376007797 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1517,6 +1517,12 @@ mailmap.file:: subdirectory, or somewhere outside of the repository itself. See linkgit:git-shortlog[1] and linkgit:git-blame[1]. +mailmap.blob:: + Like `mailmap.file`, but consider the value as a reference to a + blob in the repository (e.g., `HEAD:.mailmap`). If both + `mailmap.file` and `mailmap.blob` are given, both are parsed, + with entries from `mailmap.file` taking precedence. + man.viewer:: Specify the programs that may be used to display help in the 'man' format. See linkgit:git-help[1]. diff --git a/cache.h b/cache.h index 18fdd18f3..a65f6d141 100644 --- a/cache.h +++ b/cache.h @@ -1155,6 +1155,7 @@ extern int author_ident_sufficiently_given(void); extern const char *git_commit_encoding; extern const char *git_log_output_encoding; extern const char *git_mailmap_file; +extern const char *git_mailmap_blob; /* IO helper functions */ extern void maybe_flush_or_die(FILE *, const char *); diff --git a/config.c b/config.c index fb3f8681e..97364c03f 100644 --- a/config.c +++ b/config.c @@ -839,6 +839,8 @@ static int git_default_mailmap_config(const char *var, const char *value) { if (!strcmp(var, "mailmap.file")) return git_config_string(&git_mailmap_file, var, value); + if (!strcmp(var, "mailmap.blob")) + return git_config_string(&git_mailmap_blob, var, value); /* Add other config variables here and to Documentation/config.txt. */ return 0; diff --git a/mailmap.c b/mailmap.c index 89bc318de..2f9c69157 100644 --- a/mailmap.c +++ b/mailmap.c @@ -10,6 +10,7 @@ static inline void debug_mm(const char *format, ...) {} #endif const char *git_mailmap_file; +const char *git_mailmap_blob; struct mailmap_info { char *name; @@ -177,12 +178,56 @@ static int read_mailmap_file(struct string_list *map, const char *filename, return 0; } +static void read_mailmap_buf(struct string_list *map, + const char *buf, unsigned long len, + char **repo_abbrev) +{ + while (len) { + const char *end = strchrnul(buf, '\n'); + unsigned long linelen = end - buf + 1; + char *line = xmemdupz(buf, linelen); + + read_mailmap_line(map, line, repo_abbrev); + + free(line); + buf += linelen; + len -= linelen; + } +} + +static int read_mailmap_blob(struct string_list *map, + const char *name, + char **repo_abbrev) +{ + unsigned char sha1[20]; + char *buf; + unsigned long size; + enum object_type type; + + if (!name) + return 1; + if (get_sha1(name, sha1) < 0) + return 1; + + buf = read_sha1_file(sha1, &type, &size); + if (!buf) + return 1; + if (type != OBJ_BLOB) + return 1; + + read_mailmap_buf(map, buf, size, repo_abbrev); + + free(buf); + return 0; +} + int read_mailmap(struct string_list *map, char **repo_abbrev) { map->strdup_strings = 1; - /* each failure returns 1, so >1 means both calls failed */ + /* each failure returns 1, so >2 means all calls failed */ return read_mailmap_file(map, ".mailmap", repo_abbrev) + - read_mailmap_file(map, git_mailmap_file, repo_abbrev) > 1; + read_mailmap_blob(map, git_mailmap_blob, repo_abbrev) + + read_mailmap_file(map, git_mailmap_file, repo_abbrev) > 2; } void clear_mailmap(struct string_list *map) diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 1f182f612..e7ea40ceb 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -149,6 +149,79 @@ test_expect_success 'No mailmap files, but configured' ' test_cmp expect actual ' +test_expect_success 'setup mailmap blob tests' ' + git checkout -b map && + test_when_finished "git checkout master" && + cat >just-bugs <<-\EOF && + Blob Guy + EOF + cat >both <<-\EOF && + Blob Guy + Blob Guy + EOF + git add just-bugs both && + git commit -m "my mailmaps" && + echo "Repo Guy " >.mailmap && + echo "Internal Guy " >internal.map +' + +test_expect_success 'mailmap.blob set' ' + cat >expect <<-\EOF && + Blob Guy (1): + second + + Repo Guy (1): + initial + + EOF + git -c mailmap.blob=map:just-bugs shortlog HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'mailmap.blob overrides .mailmap' ' + cat >expect <<-\EOF && + Blob Guy (2): + initial + second + + EOF + git -c mailmap.blob=map:both shortlog HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'mailmap.file overrides mailmap.blob' ' + cat >expect <<-\EOF && + Blob Guy (1): + second + + Internal Guy (1): + initial + + EOF + git \ + -c mailmap.blob=map:both \ + -c mailmap.file=internal.map \ + shortlog HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'mailmap.blob can be missing' ' + cat >expect <<-\EOF && + Repo Guy (1): + initial + + nick1 (1): + second + + EOF + git -c mailmap.blob=map:nonexistent shortlog HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'cleanup after mailmap.blob tests' ' + rm -f .mailmap +' + # Extended mailmap configurations should give us the following output for shortlog cat >expect <<\EOF A U Thor (1): -- 2.26.2