Merge branch 'ab/mailmap'

Clean-up docs, codepaths and tests around mailmap.

* ab/mailmap: (22 commits)
  shortlog: remove unused(?) "repo-abbrev" feature
  mailmap doc + tests: document and test for case-insensitivity
  mailmap tests: add tests for empty "<>" syntax
  mailmap tests: add tests for whitespace syntax
  mailmap tests: add a test for comment syntax
  mailmap doc + tests: add better examples & test them
  tests: refactor a few tests to use "test_commit --append"
  test-lib functions: add an --append option to test_commit
  test-lib functions: add --author support to test_commit
  test-lib functions: document arguments to test_commit
  test-lib functions: expand "test_commit" comment template
  mailmap: test for silent exiting on missing file/blob
  mailmap tests: get rid of overly complex blame fuzzing
  mailmap tests: add a test for "not a blob" error
  mailmap tests: remove redundant entry in test
  mailmap tests: improve --stdin tests
  mailmap tests: modernize syntax & test idioms
  mailmap tests: use our preferred whitespace syntax
  mailmap doc: start by mentioning the comment syntax
  check-mailmap doc: note config options
  ...
This commit is contained in:
Junio C Hamano 2021-01-25 14:19:19 -08:00
commit 42342b3ee6
22 changed files with 789 additions and 447 deletions

View file

@ -21,6 +21,7 @@ MAN1_TXT += gitweb.txt
MAN5_TXT += gitattributes.txt MAN5_TXT += gitattributes.txt
MAN5_TXT += githooks.txt MAN5_TXT += githooks.txt
MAN5_TXT += gitignore.txt MAN5_TXT += gitignore.txt
MAN5_TXT += gitmailmap.txt
MAN5_TXT += gitmodules.txt MAN5_TXT += gitmodules.txt
MAN5_TXT += gitrepository-layout.txt MAN5_TXT += gitrepository-layout.txt
MAN5_TXT += gitweb.conf.txt MAN5_TXT += gitweb.conf.txt

View file

@ -226,7 +226,7 @@ commit commentary), a blame viewer will not care.
MAPPING AUTHORS MAPPING AUTHORS
--------------- ---------------
include::mailmap.txt[] See linkgit:gitmailmap[5].
SEE ALSO SEE ALSO

View file

@ -36,10 +36,17 @@ name is provided or known to the 'mailmap', ``Name $$<user@host>$$'' is
printed; otherwise only ``$$<user@host>$$'' is printed. printed; otherwise only ``$$<user@host>$$'' is printed.
CONFIGURATION
-------------
See `mailmap.file` and `mailmap.blob` in linkgit:git-config[1] for how
to specify a custom `.mailmap` target file or object.
MAPPING AUTHORS MAPPING AUTHORS
--------------- ---------------
include::mailmap.txt[] See linkgit:gitmailmap[5].
GIT GIT

View file

@ -111,11 +111,7 @@ include::rev-list-options.txt[]
MAPPING AUTHORS MAPPING AUTHORS
--------------- ---------------
The `.mailmap` feature is used to coalesce together commits by the same See linkgit:gitmailmap[5].
person in the shortlog, where their name and/or email address was
spelled differently.
include::mailmap.txt[]
GIT GIT
--- ---

View file

@ -0,0 +1,123 @@
gitmailmap(5)
=============
NAME
----
gitmailmap - Map author/committer names and/or E-Mail addresses
SYNOPSIS
--------
$GIT_WORK_DIR/.mailmap
DESCRIPTION
-----------
If the file `.mailmap` exists at the toplevel of the repository, or at
the location pointed to by the `mailmap.file` or `mailmap.blob`
configuration options (see linkgit:git-config[1]), it
is used to map author and committer names and email addresses to
canonical real names and email addresses.
SYNTAX
------
The '#' character begins a comment to the end of line, blank lines
are ignored.
In the simple form, each line in the file consists of the canonical
real name of an author, whitespace, and an email address used in the
commit (enclosed by '<' and '>') to map to the name. For example:
--
Proper Name <commit@email.xx>
--
The more complex forms are:
--
<proper@email.xx> <commit@email.xx>
--
which allows mailmap to replace only the email part of a commit, and:
--
Proper Name <proper@email.xx> <commit@email.xx>
--
which allows mailmap to replace both the name and the email of a
commit matching the specified commit email address, and:
--
Proper Name <proper@email.xx> Commit Name <commit@email.xx>
--
which allows mailmap to replace both the name and the email of a
commit matching both the specified commit name and email address.
Both E-Mails and names are matched case-insensitively. For example
this would also match the 'Commit Name <commit@email.xx>' above:
--
Proper Name <proper@email.xx> CoMmIt NaMe <CoMmIt@EmAiL.xX>
--
EXAMPLES
--------
Your history contains commits by two authors, Jane
and Joe, whose names appear in the repository under several forms:
------------
Joe Developer <joe@example.com>
Joe R. Developer <joe@example.com>
Jane Doe <jane@example.com>
Jane Doe <jane@laptop.(none)>
Jane D. <jane@desktop.(none)>
------------
Now suppose that Joe wants his middle name initial used, and Jane
prefers her family name fully spelled out. A `.mailmap` file to
correct the names would look like:
------------
Joe R. Developer <joe@example.com>
Jane Doe <jane@example.com>
Jane Doe <jane@desktop.(none)>
------------
Note that there's no need to map the name for 'jane@laptop.(none)' to
only correct the names. However, leaving the obviously broken
`<jane@laptop.(none)>' and '<jane@desktop.(none)>' E-Mails as-is is
usually not what you want. A `.mailmap` file which also corrects those
is:
------------
Joe R. Developer <joe@example.com>
Jane Doe <jane@example.com> <jane@laptop.(none)>
Jane Doe <jane@example.com> <jane@desktop.(none)>
------------
Finally, let's say that Joe and Jane shared an E-Mail address, but not
a name, e.g. by having these two commits in the history generated by a
bug reporting system. I.e. names appearing in history as:
------------
Joe <bugs@example.com>
Jane <bugs@example.com>
------------
A full `.mailmap` file which also handles those cases (an addition of
two lines to the above example) would be:
------------
Joe R. Developer <joe@example.com>
Jane Doe <jane@example.com> <jane@laptop.(none)>
Jane Doe <jane@example.com> <jane@desktop.(none)>
Joe R. Developer <joe@example.com> Joe <bugs@example.com>
Jane Doe <jane@example.com> Jane <bugs@example.com>
------------
SEE ALSO
--------
linkgit:git-check-mailmap[1]
GIT
---
Part of the linkgit:git[1] suite

View file

@ -1,75 +0,0 @@
If the file `.mailmap` exists at the toplevel of the repository, or at
the location pointed to by the mailmap.file or mailmap.blob
configuration options, it
is used to map author and committer names and email addresses to
canonical real names and email addresses.
In the simple form, each line in the file consists of the canonical
real name of an author, whitespace, and an email address used in the
commit (enclosed by '<' and '>') to map to the name. For example:
--
Proper Name <commit@email.xx>
--
The more complex forms are:
--
<proper@email.xx> <commit@email.xx>
--
which allows mailmap to replace only the email part of a commit, and:
--
Proper Name <proper@email.xx> <commit@email.xx>
--
which allows mailmap to replace both the name and the email of a
commit matching the specified commit email address, and:
--
Proper Name <proper@email.xx> Commit Name <commit@email.xx>
--
which allows mailmap to replace both the name and the email of a
commit matching both the specified commit name and email address.
Example 1: Your history contains commits by two authors, Jane
and Joe, whose names appear in the repository under several forms:
------------
Joe Developer <joe@example.com>
Joe R. Developer <joe@example.com>
Jane Doe <jane@example.com>
Jane Doe <jane@laptop.(none)>
Jane D. <jane@desktop.(none)>
------------
Now suppose that Joe wants his middle name initial used, and Jane
prefers her family name fully spelled out. A proper `.mailmap` file
would look like:
------------
Jane Doe <jane@desktop.(none)>
Joe R. Developer <joe@example.com>
------------
Note how there is no need for an entry for `<jane@laptop.(none)>`, because the
real name of that author is already correct.
Example 2: Your repository contains commits from the following
authors:
------------
nick1 <bugs@company.xx>
nick2 <bugs@company.xx>
nick2 <nick2@company.xx>
santa <me@company.xx>
claus <me@company.xx>
CTO <cto@coompany.xx>
------------
Then you might want a `.mailmap` file that looks like:
------------
<cto@company.xx> <cto@coompany.xx>
Some Dude <some@dude.xx> nick1 <bugs@company.xx>
Other Author <other@author.xx> nick2 <bugs@company.xx>
Other Author <other@author.xx> <nick2@company.xx>
Santa Claus <santa.claus@northpole.xx> <me@company.xx>
------------
Use hash '#' for comments that are either on their own line, or after
the email address.

View file

@ -1151,7 +1151,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
sb.xdl_opts = xdl_opts; sb.xdl_opts = xdl_opts;
sb.no_whole_file_rename = no_whole_file_rename; sb.no_whole_file_rename = no_whole_file_rename;
read_mailmap(&mailmap, NULL); read_mailmap(&mailmap);
sb.found_guilty_entry = &found_guilty_entry; sb.found_guilty_entry = &found_guilty_entry;
sb.found_guilty_entry_data = &pi; sb.found_guilty_entry_data = &pi;

View file

@ -47,7 +47,7 @@ int cmd_check_mailmap(int argc, const char **argv, const char *prefix)
if (argc == 0 && !use_stdin) if (argc == 0 && !use_stdin)
die(_("no contacts specified")); die(_("no contacts specified"));
read_mailmap(&mailmap, NULL); read_mailmap(&mailmap);
for (i = 0; i < argc; ++i) for (i = 0; i < argc; ++i)
check_mailmap(&mailmap, argv[i]); check_mailmap(&mailmap, argv[i]);

View file

@ -1039,7 +1039,7 @@ static const char *find_author_by_nickname(const char *name)
av[++ac] = NULL; av[++ac] = NULL;
setup_revisions(ac, av, &revs, NULL); setup_revisions(ac, av, &revs, NULL);
revs.mailmap = &mailmap; revs.mailmap = &mailmap;
read_mailmap(revs.mailmap, NULL); read_mailmap(revs.mailmap);
if (prepare_revision_walk(&revs)) if (prepare_revision_walk(&revs))
die(_("revision walk setup failed")); die(_("revision walk setup failed"));

View file

@ -230,7 +230,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
if (mailmap) { if (mailmap) {
rev->mailmap = xcalloc(1, sizeof(struct string_list)); rev->mailmap = xcalloc(1, sizeof(struct string_list));
read_mailmap(rev->mailmap, NULL); read_mailmap(rev->mailmap);
} }
if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) { if (rev->pretty_given && rev->commit_format == CMIT_FMT_RAW) {

View file

@ -61,8 +61,7 @@ static void insert_one_record(struct shortlog *log,
if (log->summary) if (log->summary)
item->util = (void *)(UTIL_TO_INT(item) + 1); item->util = (void *)(UTIL_TO_INT(item) + 1);
else { else {
const char *dot3 = log->common_repo_prefix; char *buffer;
char *buffer, *p;
struct strbuf subject = STRBUF_INIT; struct strbuf subject = STRBUF_INIT;
const char *eol; const char *eol;
@ -82,17 +81,6 @@ static void insert_one_record(struct shortlog *log,
format_subject(&subject, oneline, " "); format_subject(&subject, oneline, " ");
buffer = strbuf_detach(&subject, NULL); buffer = strbuf_detach(&subject, NULL);
if (dot3) {
int dot3len = strlen(dot3);
if (dot3len > 5) {
while ((p = strstr(buffer, dot3)) != NULL) {
int taillen = strlen(p) - dot3len;
memcpy(p, "/.../", 5);
memmove(p + 5, p + dot3len, taillen + 1);
}
}
}
if (item->util == NULL) if (item->util == NULL)
item->util = xcalloc(1, sizeof(struct string_list)); item->util = xcalloc(1, sizeof(struct string_list));
string_list_append(item->util, buffer); string_list_append(item->util, buffer);
@ -342,7 +330,7 @@ void shortlog_init(struct shortlog *log)
{ {
memset(log, 0, sizeof(*log)); memset(log, 0, sizeof(*log));
read_mailmap(&log->mailmap, &log->common_repo_prefix); read_mailmap(&log->mailmap);
log->list.strdup_strings = 1; log->list.strdup_strings = 1;
log->wrap = DEFAULT_WRAPLEN; log->wrap = DEFAULT_WRAPLEN;

View file

@ -204,6 +204,7 @@ gitfaq guide
gitglossary guide gitglossary guide
githooks guide githooks guide
gitignore guide gitignore guide
gitmailmap guide
gitmodules guide gitmodules guide
gitnamespaces guide gitnamespaces guide
gitremote-helpers guide gitremote-helpers guide

View file

@ -143,31 +143,13 @@ static char *parse_name_and_email(char *buffer, char **name,
return (*right == '\0' ? NULL : right); return (*right == '\0' ? NULL : right);
} }
static void read_mailmap_line(struct string_list *map, char *buffer, static void read_mailmap_line(struct string_list *map, char *buffer)
char **repo_abbrev)
{ {
char *name1 = NULL, *email1 = NULL, *name2 = NULL, *email2 = NULL; 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) if (buffer[0] == '#')
return; return;
if (len && buffer[len - 1] == '\n')
buffer[--len] = 0;
if (!strncmp(buffer, abbrev, abblen)) {
char *cp;
free(*repo_abbrev);
for (cp = buffer + abblen; isspace(*cp); cp++)
; /* nothing */
*repo_abbrev = xstrdup(cp);
}
return;
}
if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL) if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL)
parse_name_and_email(name2, &name2, &email2, 1); parse_name_and_email(name2, &name2, &email2, 1);
@ -175,8 +157,7 @@ static void read_mailmap_line(struct string_list *map, char *buffer,
add_mapping(map, name1, email1, name2, email2); add_mapping(map, name1, email1, name2, email2);
} }
static int read_mailmap_file(struct string_list *map, const char *filename, static int read_mailmap_file(struct string_list *map, const char *filename)
char **repo_abbrev)
{ {
char buffer[1024]; char buffer[1024];
FILE *f; FILE *f;
@ -192,13 +173,12 @@ static int read_mailmap_file(struct string_list *map, const char *filename,
} }
while (fgets(buffer, sizeof(buffer), f) != NULL) while (fgets(buffer, sizeof(buffer), f) != NULL)
read_mailmap_line(map, buffer, repo_abbrev); read_mailmap_line(map, buffer);
fclose(f); fclose(f);
return 0; return 0;
} }
static void read_mailmap_string(struct string_list *map, char *buf, static void read_mailmap_string(struct string_list *map, char *buf)
char **repo_abbrev)
{ {
while (*buf) { while (*buf) {
char *end = strchrnul(buf, '\n'); char *end = strchrnul(buf, '\n');
@ -206,14 +186,12 @@ static void read_mailmap_string(struct string_list *map, char *buf,
if (*end) if (*end)
*end++ = '\0'; *end++ = '\0';
read_mailmap_line(map, buf, repo_abbrev); read_mailmap_line(map, buf);
buf = end; buf = end;
} }
} }
static int read_mailmap_blob(struct string_list *map, static int read_mailmap_blob(struct string_list *map, const char *name)
const char *name,
char **repo_abbrev)
{ {
struct object_id oid; struct object_id oid;
char *buf; char *buf;
@ -231,13 +209,13 @@ static int read_mailmap_blob(struct string_list *map,
if (type != OBJ_BLOB) if (type != OBJ_BLOB)
return error("mailmap is not a blob: %s", name); return error("mailmap is not a blob: %s", name);
read_mailmap_string(map, buf, repo_abbrev); read_mailmap_string(map, buf);
free(buf); free(buf);
return 0; return 0;
} }
int read_mailmap(struct string_list *map, char **repo_abbrev) int read_mailmap(struct string_list *map)
{ {
int err = 0; int err = 0;
@ -247,10 +225,10 @@ int read_mailmap(struct string_list *map, char **repo_abbrev)
if (!git_mailmap_blob && is_bare_repository()) if (!git_mailmap_blob && is_bare_repository())
git_mailmap_blob = "HEAD:.mailmap"; git_mailmap_blob = "HEAD:.mailmap";
err |= read_mailmap_file(map, ".mailmap", repo_abbrev); err |= read_mailmap_file(map, ".mailmap");
if (startup_info->have_repository) if (startup_info->have_repository)
err |= read_mailmap_blob(map, git_mailmap_blob, repo_abbrev); err |= read_mailmap_blob(map, git_mailmap_blob);
err |= read_mailmap_file(map, git_mailmap_file, repo_abbrev); err |= read_mailmap_file(map, git_mailmap_file);
return err; return err;
} }

View file

@ -3,7 +3,7 @@
struct string_list; struct string_list;
int read_mailmap(struct string_list *map, char **repo_abbrev); int read_mailmap(struct string_list *map);
void clear_mailmap(struct string_list *map); void clear_mailmap(struct string_list *map);
int map_user(struct string_list *map, int map_user(struct string_list *map,

View file

@ -679,7 +679,7 @@ static int mailmap_name(const char **email, size_t *email_len,
static struct string_list *mail_map; static struct string_list *mail_map;
if (!mail_map) { if (!mail_map) {
mail_map = xcalloc(1, sizeof(*mail_map)); mail_map = xcalloc(1, sizeof(*mail_map));
read_mailmap(mail_map, NULL); read_mailmap(mail_map);
} }
return mail_map->nr && map_user(mail_map, email, email_len, name, name_len); return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
} }

View file

@ -23,7 +23,6 @@ struct shortlog {
} groups; } groups;
struct string_list trailers; struct string_list trailers;
char *common_repo_prefix;
int email; int email;
struct string_list mailmap; struct string_list mailmap;
FILE *file; FILE *file;

View file

@ -4,11 +4,8 @@ test_description='reflog walk shows repeated commits again'
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'setup commits' ' test_expect_success 'setup commits' '
test_tick && test_commit one file content &&
echo content >file && git add file && git commit -m one && test_commit --append two file content
git tag one &&
echo content >>file && git add file && git commit -m two &&
git tag two
' '
test_expect_success 'setup reflog with alternating commits' ' test_expect_success 'setup reflog with alternating commits' '

View file

@ -8,13 +8,9 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'setup' ' test_expect_success 'setup' '
echo hello >world && test_commit initial world hello &&
git add world &&
git commit -m initial &&
git branch other && git branch other &&
echo "hello again" >>world && test_commit --append second world "hello again"
git add world &&
git commit -m second
' '
test_expect_success '"checkout -" does not work initially' ' test_expect_success '"checkout -" does not work initially' '
@ -96,9 +92,7 @@ test_expect_success 'switch to twelfth from the last' '
test_expect_success 'merge base test setup' ' test_expect_success 'merge base test setup' '
git checkout -b another other && git checkout -b another other &&
echo "hello again" >>world && test_commit --append third world "hello again"
git add world &&
git commit -m third
' '
test_expect_success 'another...main' ' test_expect_success 'another...main' '

View file

@ -7,28 +7,9 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh . ./test-lib.sh
fuzz_blame () { test_expect_success 'setup commits and contacts file' '
sed " test_commit initial one one &&
s/$_x05[0-9a-f][0-9a-f][0-9a-f]/OBJID/g test_commit --author "nick1 <bugs@company.xx>" --append second one two
s/$_x05[0-9a-f][0-9a-f]/OBJI/g
s/[-0-9]\{10\} [:0-9]\{8\} [-+][0-9]\{4\}/DATE/g
" "$@"
}
test_expect_success setup '
cat >contacts <<- EOF &&
$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
nick1 <bugs@company.xx>
EOF
echo one >one &&
git add one &&
test_tick &&
git commit -m initial &&
echo two >>one &&
git add one &&
test_tick &&
git commit --author "nick1 <bugs@company.xx>" -m second
' '
test_expect_success 'check-mailmap no arguments' ' test_expect_success 'check-mailmap no arguments' '
@ -51,25 +32,55 @@ test_expect_success 'check-mailmap --stdin' '
$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
nick1 <bugs@company.xx> nick1 <bugs@company.xx>
EOF EOF
git check-mailmap --stdin <contacts >actual && git check-mailmap --stdin <expect >actual &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'check-mailmap --stdin arguments' ' test_expect_success 'check-mailmap --stdin arguments: no mapping' '
test_when_finished "rm contacts" &&
cat >contacts <<-EOF &&
$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
nick1 <bugs@company.xx>
EOF
cat >expect <<-\EOF && cat >expect <<-\EOF &&
Internal Guy <bugs@company.xy> Internal Guy <bugs@company.xy>
EOF EOF
cat <contacts >>expect && cat contacts >>expect &&
git check-mailmap --stdin "Internal Guy <bugs@company.xy>" \ git check-mailmap --stdin "Internal Guy <bugs@company.xy>" \
<contacts >actual && <contacts >actual &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'check-mailmap --stdin arguments: mapping' '
test_when_finished "rm .mailmap" &&
cat >.mailmap <<-EOF &&
New Name <$GIT_AUTHOR_EMAIL>
EOF
cat >stdin <<-EOF &&
Old Name <$GIT_AUTHOR_EMAIL>
EOF
cp .mailmap expect &&
git check-mailmap --stdin <stdin >actual &&
test_cmp expect actual &&
cat .mailmap >>expect &&
git check-mailmap --stdin "Another Old Name <$GIT_AUTHOR_EMAIL>" \
<stdin >actual &&
test_cmp expect actual
'
test_expect_success 'check-mailmap bogus contact' ' test_expect_success 'check-mailmap bogus contact' '
test_must_fail git check-mailmap bogus test_must_fail git check-mailmap bogus
' '
cat >expect << EOF test_expect_success 'check-mailmap bogus contact --stdin' '
test_must_fail git check-mailmap --stdin bogus </dev/null
'
test_expect_success 'No mailmap' '
cat >expect <<-EOF &&
$GIT_AUTHOR_NAME (1): $GIT_AUTHOR_NAME (1):
initial initial
@ -77,13 +88,21 @@ nick1 (1):
second second
EOF EOF
test_expect_success 'No mailmap' '
git shortlog HEAD >actual && git shortlog HEAD >actual &&
test_cmp expect actual test_cmp expect actual
' '
cat >expect <<\EOF test_expect_success 'setup default .mailmap' '
cat >default.map <<-EOF
Repo Guy <$GIT_AUTHOR_EMAIL>
EOF
'
test_expect_success 'test default .mailmap' '
test_when_finished "rm .mailmap" &&
cp default.map .mailmap &&
cat >expect <<-\EOF &&
Repo Guy (1): Repo Guy (1):
initial initial
@ -91,16 +110,20 @@ nick1 (1):
second second
EOF EOF
test_expect_success 'default .mailmap' '
echo "Repo Guy <$GIT_AUTHOR_EMAIL>" > .mailmap &&
git shortlog HEAD >actual && git shortlog HEAD >actual &&
test_cmp expect actual test_cmp expect actual
' '
# Using a mailmap file in a subdirectory of the repo here, but test_expect_success 'mailmap.file set' '
# could just as well have been a file outside of the repository test_when_finished "rm .mailmap" &&
cat >expect <<\EOF cp default.map .mailmap &&
test_config mailmap.file internal.map &&
cat >internal.map <<-\EOF &&
Internal Guy <bugs@company.xx>
EOF
cat >expect <<-\EOF &&
Internal Guy (1): Internal Guy (1):
second second
@ -108,15 +131,30 @@ Repo Guy (1):
initial initial
EOF EOF
test_expect_success 'mailmap.file set' '
mkdir -p internal_mailmap &&
echo "Internal Guy <bugs@company.xx>" > internal_mailmap/.mailmap &&
git config mailmap.file internal_mailmap/.mailmap &&
git shortlog HEAD >actual && git shortlog HEAD >actual &&
test_cmp expect actual test_cmp expect actual &&
# The internal_mailmap/.mailmap file is an a subdirectory, but
# as shown here it can also be outside the repository
test_when_finished "rm -rf sub-repo" &&
git clone . sub-repo &&
(
cd sub-repo &&
cp ../.mailmap . &&
git config mailmap.file ../internal.map &&
git shortlog HEAD >actual &&
test_cmp ../expect actual
)
' '
cat >expect <<\EOF test_expect_success 'mailmap.file override' '
test_config mailmap.file internal.map &&
cat >internal.map <<-EOF &&
Internal Guy <bugs@company.xx>
External Guy <$GIT_AUTHOR_EMAIL>
EOF
cat >expect <<-\EOF &&
External Guy (1): External Guy (1):
initial initial
@ -124,14 +162,15 @@ Internal Guy (1):
second second
EOF EOF
test_expect_success 'mailmap.file override' '
echo "External Guy <$GIT_AUTHOR_EMAIL>" >> internal_mailmap/.mailmap &&
git config mailmap.file internal_mailmap/.mailmap &&
git shortlog HEAD >actual && git shortlog HEAD >actual &&
test_cmp expect actual test_cmp expect actual
' '
cat >expect <<\EOF test_expect_success 'mailmap.file non-existent' '
test_when_finished "rm .mailmap" &&
cp default.map .mailmap &&
cat >expect <<-\EOF &&
Repo Guy (1): Repo Guy (1):
initial initial
@ -139,32 +178,21 @@ nick1 (1):
second second
EOF EOF
test_expect_success 'mailmap.file non-existent' '
rm internal_mailmap/.mailmap &&
rmdir internal_mailmap &&
git shortlog HEAD >actual && git shortlog HEAD >actual &&
test_cmp expect actual test_cmp expect actual
' '
cat >expect <<\EOF
Internal Guy (1):
second
Repo Guy (1):
initial
EOF
test_expect_success 'name entry after email entry' ' test_expect_success 'name entry after email entry' '
mkdir -p internal_mailmap && test_when_finished "rm .mailmap" &&
echo "<bugs@company.xy> <bugs@company.xx>" >internal_mailmap/.mailmap && cp default.map .mailmap &&
echo "Internal Guy <bugs@company.xx>" >>internal_mailmap/.mailmap &&
git shortlog HEAD >actual &&
test_cmp expect actual
'
cat >expect <<\EOF test_config mailmap.file internal.map &&
cat >internal.map <<-\EOF &&
<bugs@company.xy> <bugs@company.xx>
Internal Guy <bugs@company.xx>
EOF
cat >expect <<-\EOF &&
Internal Guy (1): Internal Guy (1):
second second
@ -173,15 +201,49 @@ Repo Guy (1):
EOF EOF
test_expect_success 'name entry after email entry, case-insensitive' '
mkdir -p internal_mailmap &&
echo "<bugs@company.xy> <bugs@company.xx>" >internal_mailmap/.mailmap &&
echo "Internal Guy <BUGS@Company.xx>" >>internal_mailmap/.mailmap &&
git shortlog HEAD >actual && git shortlog HEAD >actual &&
test_cmp expect actual test_cmp expect actual
' '
cat >expect << EOF test_expect_success 'name entry after email entry, case-insensitive' '
test_when_finished "rm .mailmap" &&
cp default.map .mailmap &&
test_config mailmap.file internal.map &&
cat >internal.map <<-\EOF &&
<bugs@company.xy> <bugs@company.xx>
Internal Guy <BUGS@Company.xx>
EOF
cat >expect <<-\EOF &&
Internal Guy (1):
second
Repo Guy (1):
initial
EOF
git shortlog HEAD >actual &&
test_cmp expect actual &&
cat >internal.map <<-\EOF &&
NiCk <BuGs@CoMpAnY.Xy> NICK1 <BUGS@COMPANY.XX>
EOF
cat >expect <<-\EOF &&
NiCk (1):
second
Repo Guy (1):
initial
EOF
git shortlog HEAD >actual &&
test_cmp expect actual
'
test_expect_success 'No mailmap files, but configured' '
cat >expect <<-EOF &&
$GIT_AUTHOR_NAME (1): $GIT_AUTHOR_NAME (1):
initial initial
@ -189,8 +251,6 @@ nick1 (1):
second second
EOF EOF
test_expect_success 'No mailmap files, but configured' '
rm -f .mailmap internal_mailmap/.mailmap &&
git shortlog HEAD >actual && git shortlog HEAD >actual &&
test_cmp expect actual test_cmp expect actual
' '
@ -198,7 +258,7 @@ test_expect_success 'No mailmap files, but configured' '
test_expect_success 'setup mailmap blob tests' ' test_expect_success 'setup mailmap blob tests' '
git checkout -b map && git checkout -b map &&
test_when_finished "git checkout main" && test_when_finished "git checkout main" &&
cat >just-bugs <<- EOF && cat >just-bugs <<-\EOF &&
Blob Guy <bugs@company.xx> Blob Guy <bugs@company.xx>
EOF EOF
cat >both <<-EOF && cat >both <<-EOF &&
@ -208,11 +268,16 @@ test_expect_success 'setup mailmap blob tests' '
printf "Tricky Guy <$GIT_AUTHOR_EMAIL>" >no-newline && printf "Tricky Guy <$GIT_AUTHOR_EMAIL>" >no-newline &&
git add just-bugs both no-newline && git add just-bugs both no-newline &&
git commit -m "my mailmaps" && git commit -m "my mailmaps" &&
echo "Repo Guy <$GIT_AUTHOR_EMAIL>" >.mailmap &&
echo "Internal Guy <$GIT_AUTHOR_EMAIL>" >internal.map cat >internal.map <<-EOF
Internal Guy <$GIT_AUTHOR_EMAIL>
EOF
' '
test_expect_success 'mailmap.blob set' ' test_expect_success 'mailmap.blob set' '
test_when_finished "rm .mailmap" &&
cp default.map .mailmap &&
cat >expect <<-\EOF && cat >expect <<-\EOF &&
Blob Guy (1): Blob Guy (1):
second second
@ -226,6 +291,9 @@ test_expect_success 'mailmap.blob set' '
' '
test_expect_success 'mailmap.blob overrides .mailmap' ' test_expect_success 'mailmap.blob overrides .mailmap' '
test_when_finished "rm .mailmap" &&
cp default.map .mailmap &&
cat >expect <<-\EOF && cat >expect <<-\EOF &&
Blob Guy (2): Blob Guy (2):
initial initial
@ -252,7 +320,11 @@ test_expect_success 'mailmap.file overrides mailmap.blob' '
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'mailmap.blob can be missing' ' test_expect_success 'mailmap.file can be missing' '
test_when_finished "rm .mailmap" &&
cp default.map .mailmap &&
test_config mailmap.file nonexistent &&
cat >expect <<-\EOF && cat >expect <<-\EOF &&
Repo Guy (1): Repo Guy (1):
initial initial
@ -261,7 +333,34 @@ test_expect_success 'mailmap.blob can be missing' '
second second
EOF EOF
git -c mailmap.blob=map:nonexistent shortlog HEAD >actual && git shortlog HEAD >actual 2>err &&
test_must_be_empty err &&
test_cmp expect actual
'
test_expect_success 'mailmap.blob can be missing' '
test_when_finished "rm .mailmap" &&
cp default.map .mailmap &&
cat >expect <<-\EOF &&
Repo Guy (1):
initial
nick1 (1):
second
EOF
git -c mailmap.blob=map:nonexistent shortlog HEAD >actual 2>err &&
test_must_be_empty err &&
test_cmp expect actual
'
test_expect_success 'mailmap.blob might be the wrong type' '
test_when_finished "rm .mailmap" &&
cp default.map .mailmap &&
git -c mailmap.blob=HEAD: shortlog HEAD >actual 2>err &&
test_i18ngrep "mailmap is not a blob" err &&
test_cmp expect actual test_cmp expect actual
' '
@ -270,11 +369,15 @@ test_expect_success 'mailmap.blob defaults to off in non-bare repo' '
( (
cd non-bare && cd non-bare &&
test_commit one .mailmap "Fake Name <$GIT_AUTHOR_EMAIL>" && test_commit one .mailmap "Fake Name <$GIT_AUTHOR_EMAIL>" &&
echo " 1 Fake Name" >expect && cat >expect <<-\EOF &&
1 Fake Name
EOF
git shortlog -ns HEAD >actual && git shortlog -ns HEAD >actual &&
test_cmp expect actual && test_cmp expect actual &&
rm .mailmap && rm .mailmap &&
echo " 1 $GIT_AUTHOR_NAME" >expect && cat >expect <<-EOF &&
1 $GIT_AUTHOR_NAME
EOF
git shortlog -ns HEAD >actual && git shortlog -ns HEAD >actual &&
test_cmp expect actual test_cmp expect actual
) )
@ -284,7 +387,9 @@ test_expect_success 'mailmap.blob defaults to HEAD:.mailmap in bare repo' '
git clone --bare non-bare bare && git clone --bare non-bare bare &&
( (
cd bare && cd bare &&
echo " 1 Fake Name" >expect && cat >expect <<-\EOF &&
1 Fake Name
EOF
git shortlog -ns HEAD >actual && git shortlog -ns HEAD >actual &&
test_cmp expect actual test_cmp expect actual
) )
@ -303,30 +408,140 @@ test_expect_success 'mailmap.blob can handle blobs without trailing newline' '
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'cleanup after mailmap.blob tests' '
rm -f .mailmap
'
test_expect_success 'single-character name' ' test_expect_success 'single-character name' '
echo " 1 A <$GIT_AUTHOR_EMAIL>" >expect &&
echo " 1 nick1 <bugs@company.xx>" >>expect &&
echo "A <$GIT_AUTHOR_EMAIL>" >.mailmap &&
test_when_finished "rm .mailmap" && test_when_finished "rm .mailmap" &&
cat >.mailmap <<-EOF &&
A <$GIT_AUTHOR_EMAIL>
EOF
cat >expect <<-EOF &&
1 A <$GIT_AUTHOR_EMAIL>
1 nick1 <bugs@company.xx>
EOF
git shortlog -es HEAD >actual && git shortlog -es HEAD >actual &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'preserve canonical email case' ' test_expect_success 'preserve canonical email case' '
echo " 1 $GIT_AUTHOR_NAME <AUTHOR@example.com>" >expect &&
echo " 1 nick1 <bugs@company.xx>" >>expect &&
echo "<AUTHOR@example.com> <$GIT_AUTHOR_EMAIL>" >.mailmap &&
test_when_finished "rm .mailmap" && test_when_finished "rm .mailmap" &&
cat >.mailmap <<-EOF &&
<AUTHOR@example.com> <$GIT_AUTHOR_EMAIL>
EOF
cat >expect <<-EOF &&
1 $GIT_AUTHOR_NAME <AUTHOR@example.com>
1 nick1 <bugs@company.xx>
EOF
git shortlog -es HEAD >actual && git shortlog -es HEAD >actual &&
test_cmp expect actual test_cmp expect actual
' '
# Extended mailmap configurations should give us the following output for shortlog test_expect_success 'gitmailmap(5) example output: setup' '
cat >expect << EOF test_create_repo doc &&
test_commit -C doc --author "Joe Developer <joe@example.com>" A &&
test_commit -C doc --author "Joe R. Developer <joe@example.com>" B &&
test_commit -C doc --author "Jane Doe <jane@example.com>" C &&
test_commit -C doc --author "Jane Doe <jane@laptop.(none)>" D &&
test_commit -C doc --author "Jane D. <jane@desktop.(none)>" E
'
test_expect_success 'gitmailmap(5) example output: example #1' '
test_config -C doc mailmap.file ../doc.map &&
cat >doc.map <<-\EOF &&
Joe R. Developer <joe@example.com>
Jane Doe <jane@example.com>
Jane Doe <jane@desktop.(none)>
EOF
cat >expect <<-\EOF &&
Author Joe Developer <joe@example.com> maps to Joe R. Developer <joe@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author Joe R. Developer <joe@example.com> maps to Joe R. Developer <joe@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author Jane Doe <jane@example.com> maps to Jane Doe <jane@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author Jane Doe <jane@laptop.(none)> maps to Jane Doe <jane@laptop.(none)>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author Jane D <jane@desktop.(none)> maps to Jane Doe <jane@desktop.(none)>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
EOF
git -C doc log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual &&
test_cmp expect actual
'
test_expect_success 'gitmailmap(5) example output: example #2' '
test_config -C doc mailmap.file ../doc.map &&
cat >doc.map <<-\EOF &&
Joe R. Developer <joe@example.com>
Jane Doe <jane@example.com> <jane@laptop.(none)>
Jane Doe <jane@example.com> <jane@desktop.(none)>
EOF
cat >expect <<-\EOF &&
Author Joe Developer <joe@example.com> maps to Joe R. Developer <joe@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author Joe R. Developer <joe@example.com> maps to Joe R. Developer <joe@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author Jane Doe <jane@example.com> maps to Jane Doe <jane@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author Jane Doe <jane@laptop.(none)> maps to Jane Doe <jane@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author Jane D <jane@desktop.(none)> maps to Jane Doe <jane@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
EOF
git -C doc log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual &&
test_cmp expect actual
'
test_expect_success 'gitmailmap(5) example output: example #3' '
test_config -C doc mailmap.file ../doc.map &&
cat >>doc.map <<-\EOF &&
Joe R. Developer <joe@example.com> Joe <bugs@example.com>
Jane Doe <jane@example.com> Jane <bugs@example.com>
EOF
test_commit -C doc --author "Joe <bugs@example.com>" F &&
test_commit -C doc --author "Jane <bugs@example.com>" G &&
cat >>expect <<-\EOF &&
Author Joe <bugs@example.com> maps to Joe R. Developer <joe@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author Jane <bugs@example.com> maps to Jane Doe <jane@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
EOF
git -C doc log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual &&
test_cmp expect actual
'
test_expect_success 'Shortlog output (complex mapping)' '
test_config mailmap.file complex.map &&
cat >complex.map <<-EOF &&
Committed <$GIT_COMMITTER_EMAIL>
<cto@company.xx> <cto@coompany.xx>
Some Dude <some@dude.xx> nick1 <bugs@company.xx>
Other Author <other@author.xx> nick2 <bugs@company.xx>
Other Author <other@author.xx> <nick2@company.xx>
Santa Claus <santa.claus@northpole.xx> <me@company.xx>
EOF
test_commit --author "nick2 <bugs@company.xx>" --append third one three &&
test_commit --author "nick2 <nick2@company.xx>" --append fourth one four &&
test_commit --author "santa <me@company.xx>" --append fifth one five &&
test_commit --author "claus <me@company.xx>" --append sixth one six &&
test_commit --author "CTO <cto@coompany.xx>" --append seventh one seven &&
cat >expect <<-EOF &&
$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> (1): $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> (1):
initial initial
@ -346,48 +561,15 @@ Some Dude <some@dude.xx> (1):
EOF EOF
test_expect_success 'Shortlog output (complex mapping)' '
echo three >>one &&
git add one &&
test_tick &&
git commit --author "nick2 <bugs@company.xx>" -m third &&
echo four >>one &&
git add one &&
test_tick &&
git commit --author "nick2 <nick2@company.xx>" -m fourth &&
echo five >>one &&
git add one &&
test_tick &&
git commit --author "santa <me@company.xx>" -m fifth &&
echo six >>one &&
git add one &&
test_tick &&
git commit --author "claus <me@company.xx>" -m sixth &&
echo seven >>one &&
git add one &&
test_tick &&
git commit --author "CTO <cto@coompany.xx>" -m seventh &&
mkdir -p internal_mailmap &&
echo "Committed <$GIT_COMMITTER_EMAIL>" > internal_mailmap/.mailmap &&
echo "<cto@company.xx> <cto@coompany.xx>" >> internal_mailmap/.mailmap &&
echo "Some Dude <some@dude.xx> nick1 <bugs@company.xx>" >> internal_mailmap/.mailmap &&
echo "Other Author <other@author.xx> nick2 <bugs@company.xx>" >> internal_mailmap/.mailmap &&
echo "Other Author <other@author.xx> <nick2@company.xx>" >> internal_mailmap/.mailmap &&
echo "Santa Claus <santa.claus@northpole.xx> <me@company.xx>" >> internal_mailmap/.mailmap &&
echo "Santa Claus <santa.claus@northpole.xx> <me@company.xx>" >> internal_mailmap/.mailmap &&
git shortlog -e HEAD >actual && git shortlog -e HEAD >actual &&
test_cmp expect actual test_cmp expect actual
' '
# git log with --pretty format which uses the name and email mailmap placemarkers test_expect_success 'Log output (complex mapping)' '
cat >expect << EOF test_config mailmap.file complex.map &&
cat >expect <<-EOF &&
Author CTO <cto@coompany.xx> maps to CTO <cto@company.xx> Author CTO <cto@coompany.xx> maps to CTO <cto@company.xx>
Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL>
@ -410,12 +592,12 @@ Author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> maps to $GIT_AUTHOR_NAME <$GIT_AUTHO
Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL>
EOF EOF
test_expect_success 'Log output (complex mapping)' '
git log --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual && git log --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual &&
test_cmp expect actual test_cmp expect actual
' '
cat >expect << EOF test_expect_success 'Log output (local-part email address)' '
cat >expect <<-EOF &&
Author email cto@coompany.xx has local-part cto Author email cto@coompany.xx has local-part cto
Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME
@ -438,12 +620,14 @@ Author email author@example.com has local-part author
Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME
EOF EOF
test_expect_success 'Log output (local-part email address)' '
git log --pretty=format:"Author email %ae has local-part %al%nCommitter email %ce has local-part %cl%n" >actual && git log --pretty=format:"Author email %ae has local-part %al%nCommitter email %ce has local-part %cl%n" >actual &&
test_cmp expect actual test_cmp expect actual
' '
cat >expect << EOF test_expect_success 'Log output with --use-mailmap' '
test_config mailmap.file complex.map &&
cat >expect <<-EOF &&
Author: CTO <cto@company.xx> Author: CTO <cto@company.xx>
Author: Santa Claus <santa.claus@northpole.xx> Author: Santa Claus <santa.claus@northpole.xx>
Author: Santa Claus <santa.claus@northpole.xx> Author: Santa Claus <santa.claus@northpole.xx>
@ -453,12 +637,14 @@ Author: Some Dude <some@dude.xx>
Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
EOF EOF
test_expect_success 'Log output with --use-mailmap' '
git log --use-mailmap | grep Author >actual && git log --use-mailmap | grep Author >actual &&
test_cmp expect actual test_cmp expect actual
' '
cat >expect << EOF test_expect_success 'Log output with log.mailmap' '
test_config mailmap.file complex.map &&
cat >expect <<-EOF &&
Author: CTO <cto@company.xx> Author: CTO <cto@company.xx>
Author: Santa Claus <santa.claus@northpole.xx> Author: Santa Claus <santa.claus@northpole.xx>
Author: Santa Claus <santa.claus@northpole.xx> Author: Santa Claus <santa.claus@northpole.xx>
@ -468,7 +654,6 @@ Author: Some Dude <some@dude.xx>
Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
EOF EOF
test_expect_success 'Log output with log.mailmap' '
git -c log.mailmap=True log | grep Author >actual && git -c log.mailmap=True log | grep Author >actual &&
test_cmp expect actual test_cmp expect actual
' '
@ -483,7 +668,7 @@ test_expect_success 'log.mailmap=false disables mailmap' '
Author: nick1 <bugs@company.xx> Author: nick1 <bugs@company.xx>
Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
EOF EOF
git -c log.mailmap=False log | grep Author > actual && git -c log.mailmap=false log | grep Author >actual &&
test_cmp expect actual test_cmp expect actual
' '
@ -501,60 +686,200 @@ test_expect_success '--no-use-mailmap disables mailmap' '
test_cmp expect actual test_cmp expect actual
' '
cat >expect <<\EOF test_expect_success 'Grep author with --use-mailmap' '
test_config mailmap.file complex.map &&
cat >expect <<-\EOF &&
Author: Santa Claus <santa.claus@northpole.xx> Author: Santa Claus <santa.claus@northpole.xx>
Author: Santa Claus <santa.claus@northpole.xx> Author: Santa Claus <santa.claus@northpole.xx>
EOF EOF
test_expect_success 'Grep author with --use-mailmap' '
git log --use-mailmap --author Santa | grep Author >actual && git log --use-mailmap --author Santa | grep Author >actual &&
test_cmp expect actual test_cmp expect actual
' '
cat >expect <<\EOF
test_expect_success 'Grep author with log.mailmap' '
test_config mailmap.file complex.map &&
cat >expect <<-\EOF &&
Author: Santa Claus <santa.claus@northpole.xx> Author: Santa Claus <santa.claus@northpole.xx>
Author: Santa Claus <santa.claus@northpole.xx> Author: Santa Claus <santa.claus@northpole.xx>
EOF EOF
test_expect_success 'Grep author with log.mailmap' '
git -c log.mailmap=True log --author Santa | grep Author >actual && git -c log.mailmap=True log --author Santa | grep Author >actual &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'log.mailmap is true by default these days' ' test_expect_success 'log.mailmap is true by default these days' '
test_config mailmap.file complex.map &&
git log --author Santa | grep Author >actual && git log --author Santa | grep Author >actual &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'Only grep replaced author with --use-mailmap' ' test_expect_success 'Only grep replaced author with --use-mailmap' '
test_config mailmap.file complex.map &&
git log --use-mailmap --author "<cto@coompany.xx>" >actual && git log --use-mailmap --author "<cto@coompany.xx>" >actual &&
test_must_be_empty actual test_must_be_empty actual
' '
# git blame test_expect_success 'Blame --porcelain output (complex mapping)' '
cat >expect <<EOF test_config mailmap.file complex.map &&
^OBJI ($GIT_AUTHOR_NAME DATE 1) one
OBJID (Some Dude DATE 2) two cat >expect <<-EOF &&
OBJID (Other Author DATE 3) three 1 1 1
OBJID (Other Author DATE 4) four A U Thor
OBJID (Santa Claus DATE 5) five 2 2 1
OBJID (Santa Claus DATE 6) six Some Dude
OBJID (CTO DATE 7) seven 3 3 1
Other Author
4 4 1
Other Author
5 5 1
Santa Claus
6 6 1
Santa Claus
7 7 1
CTO
EOF EOF
test_expect_success 'Blame output (complex mapping)' '
git blame one >actual && git blame --porcelain one >actual.blame &&
fuzz_blame actual >actual.fuzz && grep -E \
-e "[0-9]+ [0-9]+ [0-9]+$" \
-e "^author .*$" \
actual.blame >actual.grep &&
cut -d " " -f2-4 <actual.grep >actual.fuzz &&
test_cmp expect actual.fuzz test_cmp expect actual.fuzz
' '
cat >expect <<\EOF test_expect_success 'Blame output (complex mapping)' '
git -c mailmap.file=complex.map blame one >a &&
git blame one >b &&
test_file_not_empty a &&
! cmp a b
'
test_expect_success 'commit --author honors mailmap' '
test_config mailmap.file complex.map &&
cat >expect <<-\EOF &&
Some Dude <some@dude.xx> Some Dude <some@dude.xx>
EOF EOF
test_expect_success 'commit --author honors mailmap' '
test_must_fail git commit --author "nick" --allow-empty -meight && test_must_fail git commit --author "nick" --allow-empty -meight &&
git commit --author "Some Dude" --allow-empty -meight && git commit --author "Some Dude" --allow-empty -meight &&
git show --pretty=format:"%an <%ae>%n" >actual && git show --pretty=format:"%an <%ae>%n" >actual &&
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'comment syntax: setup' '
test_create_repo comm &&
test_commit -C comm --author "A <a@example.com>" A &&
test_commit -C comm --author "B <b@example.com>" B &&
test_commit -C comm --author "C <#@example.com>" C &&
test_commit -C comm --author "D <d@e#ample.com>" D &&
test_config -C comm mailmap.file ../doc.map &&
cat >>doc.map <<-\EOF &&
# Ah <a@example.com>
; Bee <b@example.com>
Cee <cee@example.com> <#@example.com>
Dee <dee@example.com> <d@e#ample.com>
EOF
cat >expect <<-\EOF &&
Author A <a@example.com> maps to A <a@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author B <b@example.com> maps to ; Bee <b@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author C <#@example.com> maps to Cee <cee@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author D <d@e#ample.com> maps to Dee <dee@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
EOF
git -C comm log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual &&
test_cmp expect actual
'
test_expect_success 'whitespace syntax: setup' '
test_create_repo space &&
test_commit -C space --author "A <a@example.com>" A &&
test_commit -C space --author "B <b@example.com>" B &&
test_commit -C space --author " C <c@example.com>" C &&
test_commit -C space --author " D <d@example.com>" D &&
test_commit -C space --author "E E <e@example.com>" E &&
test_commit -C space --author "F F <f@example.com>" F &&
test_commit -C space --author "G G <g@example.com>" G &&
test_commit -C space --author "H H <h@example.com>" H &&
test_config -C space mailmap.file ../space.map &&
cat >>space.map <<-\EOF &&
Ah <ah@example.com> < a@example.com >
Bee <bee@example.com > < b@example.com >
Cee <cee@example.com> C <c@example.com>
dee <dee@example.com> D <d@example.com>
eee <eee@example.com> E E <e@example.com>
eff <eff@example.com> F F <f@example.com>
gee <gee@example.com> G G <g@example.com>
aitch <aitch@example.com> H H <h@example.com>
EOF
cat >expect <<-\EOF &&
Author A <a@example.com> maps to A <a@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author B <b@example.com> maps to B <b@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author C <c@example.com> maps to Cee <cee@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author D <d@example.com> maps to dee <dee@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author E E <e@example.com> maps to eee <eee@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author F F <f@example.com> maps to eff <eff@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author G G <g@example.com> maps to gee <gee@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author H H <h@example.com> maps to H H <h@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
EOF
git -C space log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual &&
test_cmp expect actual
'
test_expect_success 'empty syntax: setup' '
test_create_repo empty &&
test_commit -C empty --author "A <>" A &&
test_commit -C empty --author "B <b@example.com>" B &&
test_commit -C empty --author "C <c@example.com>" C &&
test_config -C empty mailmap.file ../empty.map &&
cat >>empty.map <<-\EOF &&
Ah <ah@example.com> <>
Bee <bee@example.com> <>
Cee <> <c@example.com>
EOF
cat >expect <<-\EOF &&
Author A <> maps to Bee <bee@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author B <b@example.com> maps to B <b@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
Author C <c@example.com> maps to C <c@example.com>
Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com>
EOF
git -C empty log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual &&
test_cmp expect actual
'
test_done test_done

View file

@ -18,11 +18,8 @@ message_body () {
} }
test_expect_success '-C option copies authorship and message' ' test_expect_success '-C option copies authorship and message' '
echo "Initial" >foo && test_commit --author Frigate\ \<flying@over.world\> \
git add foo && "Initial Commit" foo Initial Initial &&
test_tick &&
git commit -m "Initial Commit" --author Frigate\ \<flying@over.world\> &&
git tag Initial &&
echo "Test 1" >>foo && echo "Test 1" >>foo &&
test_tick && test_tick &&
git commit -a -C Initial && git commit -a -C Initial &&

View file

@ -690,21 +690,9 @@ test_expect_success 'grep -C1 hunk mark between files' '
' '
test_expect_success 'log grep setup' ' test_expect_success 'log grep setup' '
echo a >>file && test_commit --append --author "With * Asterisk <xyzzy@frotz.com>" second file a &&
test_tick && test_commit --append third file a &&
GIT_AUTHOR_NAME="With * Asterisk" \ test_commit --append --author "Night Fall <nitfol@frobozz.com>" fourth file a
GIT_AUTHOR_EMAIL="xyzzy@frotz.com" \
git commit -a -m "second" &&
echo a >>file &&
test_tick &&
git commit -a -m "third" &&
echo a >>file &&
test_tick &&
GIT_AUTHOR_NAME="Night Fall" \
GIT_AUTHOR_EMAIL="nitfol@frobozz.com" \
git commit -a -m "fourth"
' '
test_expect_success 'log grep (1)' ' test_expect_success 'log grep (1)' '

View file

@ -178,19 +178,28 @@ debug () {
GIT_DEBUGGER="${GIT_DEBUGGER}" "$@" <&6 >&5 2>&7 GIT_DEBUGGER="${GIT_DEBUGGER}" "$@" <&6 >&5 2>&7
} }
# Call test_commit with the arguments # Usage: test_commit [options] <message> [<file> [<contents> [<tag>]]]
# [-C <directory>] <message> [<file> [<contents> [<tag>]]]" # -C <dir>:
# Run all git commands in directory <dir>
# --notick
# Do not call test_tick before making a commit
# --append
# Use "echo >>" instead of "echo >" when writing "<contents>" to
# "<file>"
# --signoff
# Invoke "git commit" with --signoff
# --author=<author>
# Invoke "git commit" with --author=<author>
# #
# This will commit a file with the given contents and the given commit # This will commit a file with the given contents and the given commit
# message, and tag the resulting commit with the given tag name. # message, and tag the resulting commit with the given tag name.
# #
# <file>, <contents>, and <tag> all default to <message>. # <file>, <contents>, and <tag> all default to <message>.
#
# If the first argument is "-C", the second argument is used as a path for
# the git invocations.
test_commit () { test_commit () {
notick= && notick= &&
append= &&
author= &&
signoff= && signoff= &&
indir= && indir= &&
while test $# != 0 while test $# != 0
@ -199,6 +208,13 @@ test_commit () {
--notick) --notick)
notick=yes notick=yes
;; ;;
--append)
append=yes
;;
--author)
author="$2"
shift
;;
--signoff) --signoff)
signoff="$1" signoff="$1"
;; ;;
@ -214,13 +230,20 @@ test_commit () {
done && done &&
indir=${indir:+"$indir"/} && indir=${indir:+"$indir"/} &&
file=${2:-"$1.t"} && file=${2:-"$1.t"} &&
echo "${3-$1}" > "$indir$file" && if test -n "$append"
then
echo "${3-$1}" >>"$indir$file"
else
echo "${3-$1}" >"$indir$file"
fi &&
git ${indir:+ -C "$indir"} add "$file" && git ${indir:+ -C "$indir"} add "$file" &&
if test -z "$notick" if test -z "$notick"
then then
test_tick test_tick
fi && fi &&
git ${indir:+ -C "$indir"} commit $signoff -m "$1" && git ${indir:+ -C "$indir"} commit \
${author:+ --author "$author"} \
$signoff -m "$1" &&
git ${indir:+ -C "$indir"} tag "${4:-$1}" git ${indir:+ -C "$indir"} tag "${4:-$1}"
} }