aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2012-12-12 06:04:04 -0500
committerJunio C Hamano <gitster@pobox.com>2012-12-12 11:12:35 -0800
commit086109006f695166daf2934417a20681b0c94ab8 (patch)
treed249ca71b8fa4caf806790de5853bf2dd3df2138
parent7c8ce308d383ce6888f69e39f0d32322600c2cc2 (diff)
downloadgit-086109006f695166daf2934417a20681b0c94ab8.tar.gz
git-086109006f695166daf2934417a20681b0c94ab8.tar.xz
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 <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--Documentation/config.txt6
-rw-r--r--cache.h1
-rw-r--r--config.c2
-rw-r--r--mailmap.c49
-rwxr-xr-xt/t4203-mailmap.sh73
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 <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):