mailmap: support reading mailmap from blobs
authorJeff King <peff@peff.net>
Wed, 12 Dec 2012 11:04:04 +0000 (06:04 -0500)
committerJunio C Hamano <gitster@pobox.com>
Wed, 12 Dec 2012 19:12:35 +0000 (11:12 -0800)
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 <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/config.txt
cache.h
config.c
mailmap.c
t/t4203-mailmap.sh

index bf8f911e1ffe7820a8e903ec669c690d39612150..376007797c3a3d977991b50814eb6c29a03d14e9 100644 (file)
@@ -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 18fdd18f3674b1d7c62de65509bdb7bc57743395..a65f6d141f311477e17177d6007f8a4131973c3a 100644 (file)
--- 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 *);
index fb3f8681eed21ee81cfe36296c438ed135b98485..97364c03fc1ee0e0200b5977e7eea48f384cdaf7 100644 (file)
--- 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;
index 89bc318de4a537e228f3e00a173b46b16b7c4f73..2f9c69157d7fbdd5f2b578fe72c2422712d36800 100644 (file)
--- 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)
index 1f182f612c7e2376b503cf0b9cf7389e37903239..e7ea40ceb6c68a69fefae30ef5cee09acd02a6b2 100755 (executable)
@@ -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 <bugs@company.xx>
+       EOF
+       cat >both <<-\EOF &&
+       Blob Guy <author@example.com>
+       Blob Guy <bugs@company.xx>
+       EOF
+       git add just-bugs both &&
+       git commit -m "my mailmaps" &&
+       echo "Repo Guy <author@example.com>" >.mailmap &&
+       echo "Internal Guy <author@example.com>" >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 <author@example.com> (1):