2007-04-27 15:41:15 +08:00
|
|
|
#include "cache.h"
|
2008-07-22 02:03:49 +08:00
|
|
|
#include "string-list.h"
|
2007-05-01 06:31:52 +08:00
|
|
|
#include "mailmap.h"
|
2007-04-27 15:41:15 +08:00
|
|
|
|
2009-02-08 22:34:29 +08:00
|
|
|
#define DEBUG_MAILMAP 0
|
|
|
|
#if DEBUG_MAILMAP
|
|
|
|
#define debug_mm(...) fprintf(stderr, __VA_ARGS__)
|
|
|
|
#else
|
|
|
|
static inline void debug_mm(const char *format, ...) {}
|
|
|
|
#endif
|
|
|
|
|
2009-02-08 22:34:27 +08:00
|
|
|
const char *git_mailmap_file;
|
2012-12-12 19:04:04 +08:00
|
|
|
const char *git_mailmap_blob;
|
2009-02-08 22:34:29 +08:00
|
|
|
|
|
|
|
struct mailmap_info {
|
|
|
|
char *name;
|
|
|
|
char *email;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct mailmap_entry {
|
|
|
|
/* name and email for the simple mail-only case */
|
|
|
|
char *name;
|
|
|
|
char *email;
|
|
|
|
|
|
|
|
/* name and email for the complex mail and name matching case */
|
|
|
|
struct string_list namemap;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void free_mailmap_info(void *p, const char *s)
|
|
|
|
{
|
|
|
|
struct mailmap_info *mi = (struct mailmap_info *)p;
|
|
|
|
debug_mm("mailmap: -- complex: '%s' -> '%s' <%s>\n", s, mi->name, mi->email);
|
|
|
|
free(mi->name);
|
|
|
|
free(mi->email);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_mailmap_entry(void *p, const char *s)
|
|
|
|
{
|
|
|
|
struct mailmap_entry *me = (struct mailmap_entry *)p;
|
|
|
|
debug_mm("mailmap: removing entries for <%s>, with %d sub-entries\n", s, me->namemap.nr);
|
|
|
|
debug_mm("mailmap: - simple: '%s' <%s>\n", me->name, me->email);
|
|
|
|
free(me->name);
|
|
|
|
free(me->email);
|
|
|
|
|
|
|
|
me->namemap.strdup_strings = 1;
|
|
|
|
string_list_clear_func(&me->namemap, free_mailmap_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_mapping(struct string_list *map,
|
|
|
|
char *new_name, char *new_email, char *old_name, char *old_email)
|
|
|
|
{
|
|
|
|
struct mailmap_entry *me;
|
|
|
|
int index;
|
2009-03-31 08:18:36 +08:00
|
|
|
char *p;
|
|
|
|
|
|
|
|
if (old_email)
|
|
|
|
for (p = old_email; *p; p++)
|
|
|
|
*p = tolower(*p);
|
|
|
|
if (new_email)
|
|
|
|
for (p = new_email; *p; p++)
|
|
|
|
*p = tolower(*p);
|
|
|
|
|
2009-02-08 22:34:29 +08:00
|
|
|
if (old_email == NULL) {
|
|
|
|
old_email = new_email;
|
|
|
|
new_email = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((index = string_list_find_insert_index(map, old_email, 1)) < 0) {
|
|
|
|
/* mailmap entry exists, invert index value */
|
|
|
|
index = -1 - index;
|
|
|
|
} else {
|
|
|
|
/* create mailmap entry */
|
2010-06-26 07:41:36 +08:00
|
|
|
struct string_list_item *item = string_list_insert_at_index(map, index, old_email);
|
2011-11-17 09:25:06 +08:00
|
|
|
item->util = xcalloc(1, sizeof(struct mailmap_entry));
|
2009-02-08 22:34:29 +08:00
|
|
|
((struct mailmap_entry *)item->util)->namemap.strdup_strings = 1;
|
|
|
|
}
|
|
|
|
me = (struct mailmap_entry *)map->items[index].util;
|
|
|
|
|
|
|
|
if (old_name == NULL) {
|
|
|
|
debug_mm("mailmap: adding (simple) entry for %s at index %d\n", old_email, index);
|
|
|
|
/* Replace current name and new email for simple entry */
|
2010-10-11 23:41:16 +08:00
|
|
|
if (new_name) {
|
|
|
|
free(me->name);
|
2009-02-08 22:34:29 +08:00
|
|
|
me->name = xstrdup(new_name);
|
2010-10-11 23:41:16 +08:00
|
|
|
}
|
|
|
|
if (new_email) {
|
|
|
|
free(me->email);
|
2009-02-08 22:34:29 +08:00
|
|
|
me->email = xstrdup(new_email);
|
2010-10-11 23:41:16 +08:00
|
|
|
}
|
2009-02-08 22:34:29 +08:00
|
|
|
} else {
|
2011-11-17 09:25:06 +08:00
|
|
|
struct mailmap_info *mi = xcalloc(1, sizeof(struct mailmap_info));
|
2009-02-08 22:34:29 +08:00
|
|
|
debug_mm("mailmap: adding (complex) entry for %s at index %d\n", old_email, index);
|
|
|
|
if (new_name)
|
|
|
|
mi->name = xstrdup(new_name);
|
|
|
|
if (new_email)
|
|
|
|
mi->email = xstrdup(new_email);
|
2010-06-26 07:41:35 +08:00
|
|
|
string_list_insert(&me->namemap, old_name)->util = mi;
|
2009-02-08 22:34:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
debug_mm("mailmap: '%s' <%s> -> '%s' <%s>\n",
|
|
|
|
old_name, old_email, new_name, new_email);
|
|
|
|
}
|
|
|
|
|
2009-03-31 23:30:39 +08:00
|
|
|
static char *parse_name_and_email(char *buffer, char **name,
|
|
|
|
char **email, int allow_empty_email)
|
2009-02-08 22:34:29 +08:00
|
|
|
{
|
|
|
|
char *left, *right, *nstart, *nend;
|
2009-06-19 01:28:43 +08:00
|
|
|
*name = *email = NULL;
|
2009-02-08 22:34:29 +08:00
|
|
|
|
|
|
|
if ((left = strchr(buffer, '<')) == NULL)
|
|
|
|
return NULL;
|
|
|
|
if ((right = strchr(left+1, '>')) == NULL)
|
|
|
|
return NULL;
|
2009-03-31 23:30:39 +08:00
|
|
|
if (!allow_empty_email && (left+1 == right))
|
2009-02-08 22:34:29 +08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* remove whitespace from beginning and end of name */
|
|
|
|
nstart = buffer;
|
|
|
|
while (isspace(*nstart) && nstart < left)
|
|
|
|
++nstart;
|
|
|
|
nend = left-1;
|
2012-10-28 06:49:55 +08:00
|
|
|
while (nend > nstart && isspace(*nend))
|
2009-02-08 22:34:29 +08:00
|
|
|
--nend;
|
|
|
|
|
|
|
|
*name = (nstart < nend ? nstart : NULL);
|
|
|
|
*email = left+1;
|
|
|
|
*(nend+1) = '\0';
|
|
|
|
*right++ = '\0';
|
|
|
|
|
|
|
|
return (*right == '\0' ? NULL : right);
|
|
|
|
}
|
|
|
|
|
2012-12-12 18:59:45 +08:00
|
|
|
static void read_mailmap_line(struct string_list *map, char *buffer,
|
|
|
|
char **repo_abbrev)
|
|
|
|
{
|
|
|
|
char *name1 = NULL, *email1 = NULL, *name2 = NULL, *email2 = NULL;
|
|
|
|
if (buffer[0] == '#') {
|
|
|
|
static const char abbrev[] = "# repo-abbrev:";
|
|
|
|
int abblen = sizeof(abbrev) - 1;
|
|
|
|
int len = strlen(buffer);
|
|
|
|
|
|
|
|
if (!repo_abbrev)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (len && buffer[len - 1] == '\n')
|
|
|
|
buffer[--len] = 0;
|
|
|
|
if (!strncmp(buffer, abbrev, abblen)) {
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
if (repo_abbrev)
|
|
|
|
free(*repo_abbrev);
|
|
|
|
*repo_abbrev = xmalloc(len);
|
|
|
|
|
|
|
|
for (cp = buffer + abblen; isspace(*cp); cp++)
|
|
|
|
; /* nothing */
|
|
|
|
strcpy(*repo_abbrev, cp);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL)
|
|
|
|
parse_name_and_email(name2, &name2, &email2, 1);
|
|
|
|
|
|
|
|
if (email1)
|
|
|
|
add_mapping(map, name1, email1, name2, email2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int read_mailmap_file(struct string_list *map, const char *filename,
|
|
|
|
char **repo_abbrev)
|
2007-04-27 15:41:15 +08:00
|
|
|
{
|
|
|
|
char buffer[1024];
|
mailmap: clean up read_mailmap error handling
The error handling for the read_mailmap function is odd. It
returns 1 on error, rather than -1. And it treats a
non-existent mailmap as an error, even though there is no
reason that one needs to exist. Unless some other mailmap
source loads successfully, in which case the original error
is completely masked.
This does not cause any bugs, however, because no caller
bothers to check the return value, anyway. Let's make this a
little more robust to real errors and less surprising for
future callers that do check the error code:
1. Return -1 on errors.
2. Treat a missing entry (e.g., no mailmap.file given),
ENOENT, or a non-existent blob (for mailmap.blob) as
"no error".
3. Complain loudly when a real error (e.g., a transient
I/O error, no permission to open the mailmap file,
missing or corrupted blob object, etc) occurs.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-12 19:18:02 +08:00
|
|
|
FILE *f;
|
|
|
|
|
|
|
|
if (!filename)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
f = fopen(filename, "r");
|
|
|
|
if (!f) {
|
|
|
|
if (errno == ENOENT)
|
|
|
|
return 0;
|
|
|
|
return error("unable to open mailmap at %s: %s",
|
|
|
|
filename, strerror(errno));
|
|
|
|
}
|
2007-04-27 15:41:15 +08:00
|
|
|
|
2012-12-12 18:59:45 +08:00
|
|
|
while (fgets(buffer, sizeof(buffer), f) != NULL)
|
|
|
|
read_mailmap_line(map, buffer, repo_abbrev);
|
2007-04-27 15:41:15 +08:00
|
|
|
fclose(f);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-12-12 19:04:04 +08:00
|
|
|
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)
|
mailmap: clean up read_mailmap error handling
The error handling for the read_mailmap function is odd. It
returns 1 on error, rather than -1. And it treats a
non-existent mailmap as an error, even though there is no
reason that one needs to exist. Unless some other mailmap
source loads successfully, in which case the original error
is completely masked.
This does not cause any bugs, however, because no caller
bothers to check the return value, anyway. Let's make this a
little more robust to real errors and less surprising for
future callers that do check the error code:
1. Return -1 on errors.
2. Treat a missing entry (e.g., no mailmap.file given),
ENOENT, or a non-existent blob (for mailmap.blob) as
"no error".
3. Complain loudly when a real error (e.g., a transient
I/O error, no permission to open the mailmap file,
missing or corrupted blob object, etc) occurs.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-12 19:18:02 +08:00
|
|
|
return 0;
|
2012-12-12 19:04:04 +08:00
|
|
|
if (get_sha1(name, sha1) < 0)
|
mailmap: clean up read_mailmap error handling
The error handling for the read_mailmap function is odd. It
returns 1 on error, rather than -1. And it treats a
non-existent mailmap as an error, even though there is no
reason that one needs to exist. Unless some other mailmap
source loads successfully, in which case the original error
is completely masked.
This does not cause any bugs, however, because no caller
bothers to check the return value, anyway. Let's make this a
little more robust to real errors and less surprising for
future callers that do check the error code:
1. Return -1 on errors.
2. Treat a missing entry (e.g., no mailmap.file given),
ENOENT, or a non-existent blob (for mailmap.blob) as
"no error".
3. Complain loudly when a real error (e.g., a transient
I/O error, no permission to open the mailmap file,
missing or corrupted blob object, etc) occurs.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-12 19:18:02 +08:00
|
|
|
return 0;
|
2012-12-12 19:04:04 +08:00
|
|
|
|
|
|
|
buf = read_sha1_file(sha1, &type, &size);
|
|
|
|
if (!buf)
|
mailmap: clean up read_mailmap error handling
The error handling for the read_mailmap function is odd. It
returns 1 on error, rather than -1. And it treats a
non-existent mailmap as an error, even though there is no
reason that one needs to exist. Unless some other mailmap
source loads successfully, in which case the original error
is completely masked.
This does not cause any bugs, however, because no caller
bothers to check the return value, anyway. Let's make this a
little more robust to real errors and less surprising for
future callers that do check the error code:
1. Return -1 on errors.
2. Treat a missing entry (e.g., no mailmap.file given),
ENOENT, or a non-existent blob (for mailmap.blob) as
"no error".
3. Complain loudly when a real error (e.g., a transient
I/O error, no permission to open the mailmap file,
missing or corrupted blob object, etc) occurs.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-12 19:18:02 +08:00
|
|
|
return error("unable to read mailmap object at %s", name);
|
2012-12-12 19:04:04 +08:00
|
|
|
if (type != OBJ_BLOB)
|
mailmap: clean up read_mailmap error handling
The error handling for the read_mailmap function is odd. It
returns 1 on error, rather than -1. And it treats a
non-existent mailmap as an error, even though there is no
reason that one needs to exist. Unless some other mailmap
source loads successfully, in which case the original error
is completely masked.
This does not cause any bugs, however, because no caller
bothers to check the return value, anyway. Let's make this a
little more robust to real errors and less surprising for
future callers that do check the error code:
1. Return -1 on errors.
2. Treat a missing entry (e.g., no mailmap.file given),
ENOENT, or a non-existent blob (for mailmap.blob) as
"no error".
3. Complain loudly when a real error (e.g., a transient
I/O error, no permission to open the mailmap file,
missing or corrupted blob object, etc) occurs.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-12 19:18:02 +08:00
|
|
|
return error("mailmap is not a blob: %s", name);
|
2012-12-12 19:04:04 +08:00
|
|
|
|
|
|
|
read_mailmap_buf(map, buf, size, repo_abbrev);
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-08 22:34:27 +08:00
|
|
|
int read_mailmap(struct string_list *map, char **repo_abbrev)
|
|
|
|
{
|
mailmap: clean up read_mailmap error handling
The error handling for the read_mailmap function is odd. It
returns 1 on error, rather than -1. And it treats a
non-existent mailmap as an error, even though there is no
reason that one needs to exist. Unless some other mailmap
source loads successfully, in which case the original error
is completely masked.
This does not cause any bugs, however, because no caller
bothers to check the return value, anyway. Let's make this a
little more robust to real errors and less surprising for
future callers that do check the error code:
1. Return -1 on errors.
2. Treat a missing entry (e.g., no mailmap.file given),
ENOENT, or a non-existent blob (for mailmap.blob) as
"no error".
3. Complain loudly when a real error (e.g., a transient
I/O error, no permission to open the mailmap file,
missing or corrupted blob object, etc) occurs.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-12 19:18:02 +08:00
|
|
|
int err = 0;
|
mailmap: default mailmap.blob in bare repositories
The motivation for mailmap.blob is to let users of bare
repositories use the mailmap feature, as they would not have
a checkout containing the .mailmap file. We can make it even
easier for them by just looking in HEAD:.mailmap by default.
We can't know for sure that this is where they would keep a
mailmap, of course, but it is the best guess (and it matches
the non-bare behavior, which reads from HEAD:.mailmap in the
working tree). If it's missing, git will silently ignore the
setting.
We do not do the same magic in the non-bare case, because:
1. In the common case, HEAD:.mailmap will be the same as
the .mailmap in the working tree, which is a no-op.
2. In the uncommon case, the user has modified .mailmap
but not yet committed it, and would expect the working
tree version to take precedence.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-13 21:04:47 +08:00
|
|
|
|
2009-02-08 22:34:29 +08:00
|
|
|
map->strdup_strings = 1;
|
mailmap: default mailmap.blob in bare repositories
The motivation for mailmap.blob is to let users of bare
repositories use the mailmap feature, as they would not have
a checkout containing the .mailmap file. We can make it even
easier for them by just looking in HEAD:.mailmap by default.
We can't know for sure that this is where they would keep a
mailmap, of course, but it is the best guess (and it matches
the non-bare behavior, which reads from HEAD:.mailmap in the
working tree). If it's missing, git will silently ignore the
setting.
We do not do the same magic in the non-bare case, because:
1. In the common case, HEAD:.mailmap will be the same as
the .mailmap in the working tree, which is a no-op.
2. In the uncommon case, the user has modified .mailmap
but not yet committed it, and would expect the working
tree version to take precedence.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-13 21:04:47 +08:00
|
|
|
|
|
|
|
if (!git_mailmap_blob && is_bare_repository())
|
|
|
|
git_mailmap_blob = "HEAD:.mailmap";
|
|
|
|
|
mailmap: clean up read_mailmap error handling
The error handling for the read_mailmap function is odd. It
returns 1 on error, rather than -1. And it treats a
non-existent mailmap as an error, even though there is no
reason that one needs to exist. Unless some other mailmap
source loads successfully, in which case the original error
is completely masked.
This does not cause any bugs, however, because no caller
bothers to check the return value, anyway. Let's make this a
little more robust to real errors and less surprising for
future callers that do check the error code:
1. Return -1 on errors.
2. Treat a missing entry (e.g., no mailmap.file given),
ENOENT, or a non-existent blob (for mailmap.blob) as
"no error".
3. Complain loudly when a real error (e.g., a transient
I/O error, no permission to open the mailmap file,
missing or corrupted blob object, etc) occurs.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-12 19:18:02 +08:00
|
|
|
err |= read_mailmap_file(map, ".mailmap", repo_abbrev);
|
|
|
|
err |= read_mailmap_blob(map, git_mailmap_blob, repo_abbrev);
|
|
|
|
err |= read_mailmap_file(map, git_mailmap_file, repo_abbrev);
|
|
|
|
return err;
|
2009-02-08 22:34:27 +08:00
|
|
|
}
|
|
|
|
|
2009-02-08 22:34:29 +08:00
|
|
|
void clear_mailmap(struct string_list *map)
|
|
|
|
{
|
|
|
|
debug_mm("mailmap: clearing %d entries...\n", map->nr);
|
|
|
|
map->strdup_strings = 1;
|
|
|
|
string_list_clear_func(map, free_mailmap_entry);
|
|
|
|
debug_mm("mailmap: cleared\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
int map_user(struct string_list *map,
|
|
|
|
char *email, int maxlen_email, char *name, int maxlen_name)
|
2007-04-27 15:41:15 +08:00
|
|
|
{
|
mailmap: always return a plain mail address from map_user()
The callers of map_user() give email and name to it, and expect to get the
up-to-date email and/or name to be used in their output. The function
rewrites the given buffers in place. To optimize the majority of cases,
the function returns 0 when it did not do anything, and it returns 1 when
the caller should use the updated contents.
The 'email' input to the function is terminated by '>' or a NUL (whichever
comes first) for historical reasons, but when a rewrite happens, the value
is replaced with the mailbox inside the <> pair. However, it failed to
meet this expectation when it only rewrote the name part without rewriting
the email part, and the email in the input was terminated by '>'.
This causes an extra '>' to appear in the output of "blame -e", because the
caller does send in '>'-terminated email, and when the function returned 1
to tell it that rewriting happened, it appends '>' that is necessary when
the email part was rewritten.
The patch looks bigger than it actually is, because this change makes a
variable that points at the end of the email part in the input 'p' live
much longer than it used to, deserving a more descriptive name.
Noticed and diagnosed by Felipe Contreras and Jeff King.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 09:31:51 +08:00
|
|
|
char *end_of_email;
|
2008-07-22 02:03:49 +08:00
|
|
|
struct string_list_item *item;
|
2009-02-08 22:34:29 +08:00
|
|
|
struct mailmap_entry *me;
|
2007-04-27 15:41:15 +08:00
|
|
|
char buf[1024], *mailbuf;
|
|
|
|
int i;
|
|
|
|
|
2009-02-08 22:34:29 +08:00
|
|
|
/* figure out space requirement for email */
|
mailmap: always return a plain mail address from map_user()
The callers of map_user() give email and name to it, and expect to get the
up-to-date email and/or name to be used in their output. The function
rewrites the given buffers in place. To optimize the majority of cases,
the function returns 0 when it did not do anything, and it returns 1 when
the caller should use the updated contents.
The 'email' input to the function is terminated by '>' or a NUL (whichever
comes first) for historical reasons, but when a rewrite happens, the value
is replaced with the mailbox inside the <> pair. However, it failed to
meet this expectation when it only rewrote the name part without rewriting
the email part, and the email in the input was terminated by '>'.
This causes an extra '>' to appear in the output of "blame -e", because the
caller does send in '>'-terminated email, and when the function returned 1
to tell it that rewriting happened, it appends '>' that is necessary when
the email part was rewritten.
The patch looks bigger than it actually is, because this change makes a
variable that points at the end of the email part in the input 'p' live
much longer than it used to, deserving a more descriptive name.
Noticed and diagnosed by Felipe Contreras and Jeff King.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 09:31:51 +08:00
|
|
|
end_of_email = strchr(email, '>');
|
|
|
|
if (!end_of_email) {
|
2009-02-08 22:34:29 +08:00
|
|
|
/* email passed in might not be wrapped in <>, but end with a \0 */
|
mailmap: always return a plain mail address from map_user()
The callers of map_user() give email and name to it, and expect to get the
up-to-date email and/or name to be used in their output. The function
rewrites the given buffers in place. To optimize the majority of cases,
the function returns 0 when it did not do anything, and it returns 1 when
the caller should use the updated contents.
The 'email' input to the function is terminated by '>' or a NUL (whichever
comes first) for historical reasons, but when a rewrite happens, the value
is replaced with the mailbox inside the <> pair. However, it failed to
meet this expectation when it only rewrote the name part without rewriting
the email part, and the email in the input was terminated by '>'.
This causes an extra '>' to appear in the output of "blame -e", because the
caller does send in '>'-terminated email, and when the function returned 1
to tell it that rewriting happened, it appends '>' that is necessary when
the email part was rewritten.
The patch looks bigger than it actually is, because this change makes a
variable that points at the end of the email part in the input 'p' live
much longer than it used to, deserving a more descriptive name.
Noticed and diagnosed by Felipe Contreras and Jeff King.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 09:31:51 +08:00
|
|
|
end_of_email = memchr(email, '\0', maxlen_email);
|
|
|
|
if (!end_of_email)
|
2009-02-08 22:34:29 +08:00
|
|
|
return 0;
|
|
|
|
}
|
mailmap: always return a plain mail address from map_user()
The callers of map_user() give email and name to it, and expect to get the
up-to-date email and/or name to be used in their output. The function
rewrites the given buffers in place. To optimize the majority of cases,
the function returns 0 when it did not do anything, and it returns 1 when
the caller should use the updated contents.
The 'email' input to the function is terminated by '>' or a NUL (whichever
comes first) for historical reasons, but when a rewrite happens, the value
is replaced with the mailbox inside the <> pair. However, it failed to
meet this expectation when it only rewrote the name part without rewriting
the email part, and the email in the input was terminated by '>'.
This causes an extra '>' to appear in the output of "blame -e", because the
caller does send in '>'-terminated email, and when the function returned 1
to tell it that rewriting happened, it appends '>' that is necessary when
the email part was rewritten.
The patch looks bigger than it actually is, because this change makes a
variable that points at the end of the email part in the input 'p' live
much longer than it used to, deserving a more descriptive name.
Noticed and diagnosed by Felipe Contreras and Jeff King.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 09:31:51 +08:00
|
|
|
if (end_of_email - email + 1 < sizeof(buf))
|
2007-04-27 15:41:15 +08:00
|
|
|
mailbuf = buf;
|
|
|
|
else
|
mailmap: always return a plain mail address from map_user()
The callers of map_user() give email and name to it, and expect to get the
up-to-date email and/or name to be used in their output. The function
rewrites the given buffers in place. To optimize the majority of cases,
the function returns 0 when it did not do anything, and it returns 1 when
the caller should use the updated contents.
The 'email' input to the function is terminated by '>' or a NUL (whichever
comes first) for historical reasons, but when a rewrite happens, the value
is replaced with the mailbox inside the <> pair. However, it failed to
meet this expectation when it only rewrote the name part without rewriting
the email part, and the email in the input was terminated by '>'.
This causes an extra '>' to appear in the output of "blame -e", because the
caller does send in '>'-terminated email, and when the function returned 1
to tell it that rewriting happened, it appends '>' that is necessary when
the email part was rewritten.
The patch looks bigger than it actually is, because this change makes a
variable that points at the end of the email part in the input 'p' live
much longer than it used to, deserving a more descriptive name.
Noticed and diagnosed by Felipe Contreras and Jeff King.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 09:31:51 +08:00
|
|
|
mailbuf = xmalloc(end_of_email - email + 1);
|
2007-04-27 15:41:15 +08:00
|
|
|
|
|
|
|
/* downcase the email address */
|
mailmap: always return a plain mail address from map_user()
The callers of map_user() give email and name to it, and expect to get the
up-to-date email and/or name to be used in their output. The function
rewrites the given buffers in place. To optimize the majority of cases,
the function returns 0 when it did not do anything, and it returns 1 when
the caller should use the updated contents.
The 'email' input to the function is terminated by '>' or a NUL (whichever
comes first) for historical reasons, but when a rewrite happens, the value
is replaced with the mailbox inside the <> pair. However, it failed to
meet this expectation when it only rewrote the name part without rewriting
the email part, and the email in the input was terminated by '>'.
This causes an extra '>' to appear in the output of "blame -e", because the
caller does send in '>'-terminated email, and when the function returned 1
to tell it that rewriting happened, it appends '>' that is necessary when
the email part was rewritten.
The patch looks bigger than it actually is, because this change makes a
variable that points at the end of the email part in the input 'p' live
much longer than it used to, deserving a more descriptive name.
Noticed and diagnosed by Felipe Contreras and Jeff King.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 09:31:51 +08:00
|
|
|
for (i = 0; i < end_of_email - email; i++)
|
2007-04-27 15:41:15 +08:00
|
|
|
mailbuf[i] = tolower(email[i]);
|
|
|
|
mailbuf[i] = 0;
|
2009-02-08 22:34:29 +08:00
|
|
|
|
|
|
|
debug_mm("map_user: map '%s' <%s>\n", name, mailbuf);
|
2010-06-26 07:41:37 +08:00
|
|
|
item = string_list_lookup(map, mailbuf);
|
2009-02-08 22:34:29 +08:00
|
|
|
if (item != NULL) {
|
|
|
|
me = (struct mailmap_entry *)item->util;
|
|
|
|
if (me->namemap.nr) {
|
|
|
|
/* The item has multiple items, so we'll look up on name too */
|
|
|
|
/* If the name is not found, we choose the simple entry */
|
2010-06-26 07:41:37 +08:00
|
|
|
struct string_list_item *subitem = string_list_lookup(&me->namemap, name);
|
2009-02-08 22:34:29 +08:00
|
|
|
if (subitem)
|
|
|
|
item = subitem;
|
|
|
|
}
|
|
|
|
}
|
2007-04-27 15:41:15 +08:00
|
|
|
if (mailbuf != buf)
|
|
|
|
free(mailbuf);
|
|
|
|
if (item != NULL) {
|
2009-02-08 22:34:29 +08:00
|
|
|
struct mailmap_info *mi = (struct mailmap_info *)item->util;
|
|
|
|
if (mi->name == NULL && (mi->email == NULL || maxlen_email == 0)) {
|
|
|
|
debug_mm("map_user: -- (no simple mapping)\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (maxlen_email && mi->email)
|
|
|
|
strlcpy(email, mi->email, maxlen_email);
|
mailmap: always return a plain mail address from map_user()
The callers of map_user() give email and name to it, and expect to get the
up-to-date email and/or name to be used in their output. The function
rewrites the given buffers in place. To optimize the majority of cases,
the function returns 0 when it did not do anything, and it returns 1 when
the caller should use the updated contents.
The 'email' input to the function is terminated by '>' or a NUL (whichever
comes first) for historical reasons, but when a rewrite happens, the value
is replaced with the mailbox inside the <> pair. However, it failed to
meet this expectation when it only rewrote the name part without rewriting
the email part, and the email in the input was terminated by '>'.
This causes an extra '>' to appear in the output of "blame -e", because the
caller does send in '>'-terminated email, and when the function returned 1
to tell it that rewriting happened, it appends '>' that is necessary when
the email part was rewritten.
The patch looks bigger than it actually is, because this change makes a
variable that points at the end of the email part in the input 'p' live
much longer than it used to, deserving a more descriptive name.
Noticed and diagnosed by Felipe Contreras and Jeff King.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-02-06 09:31:51 +08:00
|
|
|
else
|
|
|
|
*end_of_email = '\0';
|
2009-02-08 22:34:29 +08:00
|
|
|
if (maxlen_name && mi->name)
|
|
|
|
strlcpy(name, mi->name, maxlen_name);
|
|
|
|
debug_mm("map_user: to '%s' <%s>\n", name, mi->email ? mi->email : "");
|
2007-04-27 15:41:15 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2009-02-08 22:34:29 +08:00
|
|
|
debug_mm("map_user: --\n");
|
2007-04-27 15:41:15 +08:00
|
|
|
return 0;
|
|
|
|
}
|