diff options
-rw-r--r-- | Documentation/Makefile | 1 | ||||
-rw-r--r-- | Documentation/git-blame.txt | 2 | ||||
-rw-r--r-- | Documentation/git-check-mailmap.txt | 9 | ||||
-rw-r--r-- | Documentation/git-shortlog.txt | 6 | ||||
-rw-r--r-- | Documentation/gitmailmap.txt | 123 | ||||
-rw-r--r-- | Documentation/mailmap.txt | 75 | ||||
-rw-r--r-- | builtin/blame.c | 2 | ||||
-rw-r--r-- | builtin/check-mailmap.c | 2 | ||||
-rw-r--r-- | builtin/commit.c | 2 | ||||
-rw-r--r-- | builtin/log.c | 2 | ||||
-rw-r--r-- | builtin/shortlog.c | 16 | ||||
-rw-r--r-- | command-list.txt | 1 | ||||
-rw-r--r-- | mailmap.c | 48 | ||||
-rw-r--r-- | mailmap.h | 2 | ||||
-rw-r--r-- | pretty.c | 2 | ||||
-rw-r--r-- | shortlog.h | 1 | ||||
-rwxr-xr-x | t/t1412-reflog-loop.sh | 7 | ||||
-rwxr-xr-x | t/t2012-checkout-last.sh | 12 | ||||
-rwxr-xr-x | t/t4203-mailmap.sh | 825 | ||||
-rwxr-xr-x | t/t7509-commit-authorship.sh | 7 | ||||
-rwxr-xr-x | t/t7810-grep.sh | 18 | ||||
-rw-r--r-- | t/test-lib-functions.sh | 37 |
22 files changed, 771 insertions, 429 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile index b980407059..81d1bf7a04 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -21,6 +21,7 @@ MAN1_TXT += gitweb.txt MAN5_TXT += gitattributes.txt MAN5_TXT += githooks.txt MAN5_TXT += gitignore.txt +MAN5_TXT += gitmailmap.txt MAN5_TXT += gitmodules.txt MAN5_TXT += gitrepository-layout.txt MAN5_TXT += gitweb.conf.txt diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt index 34b496d485..3bf5d5d8b4 100644 --- a/Documentation/git-blame.txt +++ b/Documentation/git-blame.txt @@ -226,7 +226,7 @@ commit commentary), a blame viewer will not care. MAPPING AUTHORS --------------- -include::mailmap.txt[] +See linkgit:gitmailmap[5]. SEE ALSO diff --git a/Documentation/git-check-mailmap.txt b/Documentation/git-check-mailmap.txt index aa2055dbeb..02f4418323 100644 --- a/Documentation/git-check-mailmap.txt +++ b/Documentation/git-check-mailmap.txt @@ -36,10 +36,17 @@ name is provided or known to the 'mailmap', ``Name $$<user@host>$$'' is 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 --------------- -include::mailmap.txt[] +See linkgit:gitmailmap[5]. GIT diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt index fd93cd41e9..c16cc3b608 100644 --- a/Documentation/git-shortlog.txt +++ b/Documentation/git-shortlog.txt @@ -111,11 +111,7 @@ include::rev-list-options.txt[] MAPPING AUTHORS --------------- -The `.mailmap` feature is used to coalesce together commits by the same -person in the shortlog, where their name and/or email address was -spelled differently. - -include::mailmap.txt[] +See linkgit:gitmailmap[5]. GIT --- diff --git a/Documentation/gitmailmap.txt b/Documentation/gitmailmap.txt new file mode 100644 index 0000000000..7f1089786d --- /dev/null +++ b/Documentation/gitmailmap.txt @@ -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 diff --git a/Documentation/mailmap.txt b/Documentation/mailmap.txt deleted file mode 100644 index 4a8c276529..0000000000 --- a/Documentation/mailmap.txt +++ /dev/null @@ -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. diff --git a/builtin/blame.c b/builtin/blame.c index 2c1c02c455..b66e938022 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -1151,7 +1151,7 @@ parse_done: sb.xdl_opts = xdl_opts; 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_data = π diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c index cdce144f3b..7dc47e4793 100644 --- a/builtin/check-mailmap.c +++ b/builtin/check-mailmap.c @@ -47,7 +47,7 @@ int cmd_check_mailmap(int argc, const char **argv, const char *prefix) if (argc == 0 && !use_stdin) die(_("no contacts specified")); - read_mailmap(&mailmap, NULL); + read_mailmap(&mailmap); for (i = 0; i < argc; ++i) check_mailmap(&mailmap, argv[i]); diff --git a/builtin/commit.c b/builtin/commit.c index 505fe60956..739110c5a7 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1039,7 +1039,7 @@ static const char *find_author_by_nickname(const char *name) av[++ac] = NULL; setup_revisions(ac, av, &revs, NULL); revs.mailmap = &mailmap; - read_mailmap(revs.mailmap, NULL); + read_mailmap(revs.mailmap); if (prepare_revision_walk(&revs)) die(_("revision walk setup failed")); diff --git a/builtin/log.c b/builtin/log.c index f23ccdbec3..fd282def43 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -230,7 +230,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix, if (mailmap) { 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) { diff --git a/builtin/shortlog.c b/builtin/shortlog.c index 1c0b3a9b05..3e7ab1ca82 100644 --- a/builtin/shortlog.c +++ b/builtin/shortlog.c @@ -61,8 +61,7 @@ static void insert_one_record(struct shortlog *log, if (log->summary) item->util = (void *)(UTIL_TO_INT(item) + 1); else { - const char *dot3 = log->common_repo_prefix; - char *buffer, *p; + char *buffer; struct strbuf subject = STRBUF_INIT; const char *eol; @@ -82,17 +81,6 @@ static void insert_one_record(struct shortlog *log, format_subject(&subject, oneline, " "); 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) item->util = xcalloc(1, sizeof(struct string_list)); string_list_append(item->util, buffer); @@ -342,7 +330,7 @@ void shortlog_init(struct shortlog *log) { memset(log, 0, sizeof(*log)); - read_mailmap(&log->mailmap, &log->common_repo_prefix); + read_mailmap(&log->mailmap); log->list.strdup_strings = 1; log->wrap = DEFAULT_WRAPLEN; diff --git a/command-list.txt b/command-list.txt index 9379b02e5e..a289f09ed6 100644 --- a/command-list.txt +++ b/command-list.txt @@ -204,6 +204,7 @@ gitfaq guide gitglossary guide githooks guide gitignore guide +gitmailmap guide gitmodules guide gitnamespaces guide gitremote-helpers guide @@ -143,31 +143,13 @@ static char *parse_name_and_email(char *buffer, char **name, return (*right == '\0' ? NULL : right); } -static void read_mailmap_line(struct string_list *map, char *buffer, - char **repo_abbrev) +static void read_mailmap_line(struct string_list *map, char *buffer) { 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; - - free(*repo_abbrev); - - for (cp = buffer + abblen; isspace(*cp); cp++) - ; /* nothing */ - *repo_abbrev = xstrdup(cp); - } + if (buffer[0] == '#') return; - } + if ((name2 = parse_name_and_email(buffer, &name1, &email1, 0)) != NULL) 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); } -static int read_mailmap_file(struct string_list *map, const char *filename, - char **repo_abbrev) +static int read_mailmap_file(struct string_list *map, const char *filename) { char buffer[1024]; 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) - read_mailmap_line(map, buffer, repo_abbrev); + read_mailmap_line(map, buffer); fclose(f); return 0; } -static void read_mailmap_string(struct string_list *map, char *buf, - char **repo_abbrev) +static void read_mailmap_string(struct string_list *map, char *buf) { while (*buf) { char *end = strchrnul(buf, '\n'); @@ -206,14 +186,12 @@ static void read_mailmap_string(struct string_list *map, char *buf, if (*end) *end++ = '\0'; - read_mailmap_line(map, buf, repo_abbrev); + read_mailmap_line(map, buf); buf = end; } } -static int read_mailmap_blob(struct string_list *map, - const char *name, - char **repo_abbrev) +static int read_mailmap_blob(struct string_list *map, const char *name) { struct object_id oid; char *buf; @@ -231,13 +209,13 @@ static int read_mailmap_blob(struct string_list *map, if (type != OBJ_BLOB) return error("mailmap is not a blob: %s", name); - read_mailmap_string(map, buf, repo_abbrev); + read_mailmap_string(map, buf); free(buf); return 0; } -int read_mailmap(struct string_list *map, char **repo_abbrev) +int read_mailmap(struct string_list *map) { int err = 0; @@ -247,10 +225,10 @@ int read_mailmap(struct string_list *map, char **repo_abbrev) if (!git_mailmap_blob && is_bare_repository()) git_mailmap_blob = "HEAD:.mailmap"; - err |= read_mailmap_file(map, ".mailmap", repo_abbrev); + err |= read_mailmap_file(map, ".mailmap"); if (startup_info->have_repository) - err |= read_mailmap_blob(map, git_mailmap_blob, repo_abbrev); - err |= read_mailmap_file(map, git_mailmap_file, repo_abbrev); + err |= read_mailmap_blob(map, git_mailmap_blob); + err |= read_mailmap_file(map, git_mailmap_file); return err; } @@ -3,7 +3,7 @@ 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); int map_user(struct string_list *map, @@ -679,7 +679,7 @@ static int mailmap_name(const char **email, size_t *email_len, static struct string_list *mail_map; if (!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); } diff --git a/shortlog.h b/shortlog.h index 64be879b24..3f7e9aabca 100644 --- a/shortlog.h +++ b/shortlog.h @@ -23,7 +23,6 @@ struct shortlog { } groups; struct string_list trailers; - char *common_repo_prefix; int email; struct string_list mailmap; FILE *file; diff --git a/t/t1412-reflog-loop.sh b/t/t1412-reflog-loop.sh index 3acd895afb..977603f7f1 100755 --- a/t/t1412-reflog-loop.sh +++ b/t/t1412-reflog-loop.sh @@ -4,11 +4,8 @@ test_description='reflog walk shows repeated commits again' . ./test-lib.sh test_expect_success 'setup commits' ' - test_tick && - echo content >file && git add file && git commit -m one && - git tag one && - echo content >>file && git add file && git commit -m two && - git tag two + test_commit one file content && + test_commit --append two file content ' test_expect_success 'setup reflog with alternating commits' ' diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh index 028a00d6ba..0e7d47ab31 100755 --- a/t/t2012-checkout-last.sh +++ b/t/t2012-checkout-last.sh @@ -8,13 +8,9 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh test_expect_success 'setup' ' - echo hello >world && - git add world && - git commit -m initial && + test_commit initial world hello && git branch other && - echo "hello again" >>world && - git add world && - git commit -m second + test_commit --append second world "hello again" ' 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' ' git checkout -b another other && - echo "hello again" >>world && - git add world && - git commit -m third + test_commit --append third world "hello again" ' test_expect_success 'another...main' ' diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 3f82c651b4..6fb18a34b0 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -7,28 +7,9 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh -fuzz_blame () { - sed " - s/$_x05[0-9a-f][0-9a-f][0-9a-f]/OBJID/g - 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 'setup commits and contacts file' ' + test_commit initial one one && + test_commit --author "nick1 <bugs@company.xx>" --append second one two ' test_expect_success 'check-mailmap no arguments' ' @@ -36,7 +17,7 @@ test_expect_success 'check-mailmap no arguments' ' ' test_expect_success 'check-mailmap arguments' ' - cat >expect <<- EOF && + cat >expect <<-EOF && $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> nick1 <bugs@company.xx> EOF @@ -47,150 +28,229 @@ test_expect_success 'check-mailmap arguments' ' ' test_expect_success 'check-mailmap --stdin' ' - cat >expect <<- EOF && + cat >expect <<-EOF && $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> nick1 <bugs@company.xx> EOF - git check-mailmap --stdin <contacts >actual && + git check-mailmap --stdin <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 && Internal Guy <bugs@company.xy> EOF - cat <contacts >>expect && + cat contacts >>expect && + git check-mailmap --stdin "Internal Guy <bugs@company.xy>" \ <contacts >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_must_fail git check-mailmap bogus ' -cat >expect << EOF -$GIT_AUTHOR_NAME (1): - initial +test_expect_success 'check-mailmap bogus contact --stdin' ' + test_must_fail git check-mailmap --stdin bogus </dev/null +' -nick1 (1): - second +test_expect_success 'No mailmap' ' + cat >expect <<-EOF && + $GIT_AUTHOR_NAME (1): + initial -EOF + nick1 (1): + second -test_expect_success 'No mailmap' ' + EOF git shortlog HEAD >actual && test_cmp expect actual ' -cat >expect <<\EOF -Repo Guy (1): - initial +test_expect_success 'setup default .mailmap' ' + cat >default.map <<-EOF + Repo Guy <$GIT_AUTHOR_EMAIL> + EOF +' -nick1 (1): - second +test_expect_success 'test default .mailmap' ' + test_when_finished "rm .mailmap" && + cp default.map .mailmap && -EOF + cat >expect <<-\EOF && + Repo Guy (1): + initial + + nick1 (1): + second -test_expect_success 'default .mailmap' ' - echo "Repo Guy <$GIT_AUTHOR_EMAIL>" > .mailmap && + EOF git shortlog HEAD >actual && test_cmp expect actual ' -# Using a mailmap file in a subdirectory of the repo here, but -# could just as well have been a file outside of the repository -cat >expect <<\EOF -Internal Guy (1): - second +test_expect_success 'mailmap.file set' ' + test_when_finished "rm .mailmap" && + cp default.map .mailmap && -Repo Guy (1): - initial + test_config mailmap.file internal.map && + cat >internal.map <<-\EOF && + Internal Guy <bugs@company.xx> + 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 && + cat >expect <<-\EOF && + Internal Guy (1): + second + + Repo Guy (1): + initial + + EOF 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 -External Guy (1): - initial +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 -Internal Guy (1): - second + cat >expect <<-\EOF && + External Guy (1): + initial -EOF -test_expect_success 'mailmap.file override' ' - echo "External Guy <$GIT_AUTHOR_EMAIL>" >> internal_mailmap/.mailmap && - git config mailmap.file internal_mailmap/.mailmap && + Internal Guy (1): + second + + EOF git shortlog HEAD >actual && test_cmp expect actual ' -cat >expect <<\EOF -Repo Guy (1): - initial +test_expect_success 'mailmap.file non-existent' ' + test_when_finished "rm .mailmap" && + cp default.map .mailmap && -nick1 (1): - second + cat >expect <<-\EOF && + Repo Guy (1): + initial -EOF + nick1 (1): + second -test_expect_success 'mailmap.file non-existent' ' - rm internal_mailmap/.mailmap && - rmdir internal_mailmap && + EOF git shortlog HEAD >actual && test_cmp expect actual ' -cat >expect <<\EOF -Internal Guy (1): - second +test_expect_success 'name entry after email entry' ' + 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 -Repo Guy (1): - initial + cat >expect <<-\EOF && + Internal Guy (1): + second -EOF + Repo Guy (1): + initial + + EOF -test_expect_success 'name entry after email entry' ' - 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 && test_cmp expect actual ' -cat >expect <<\EOF -Internal Guy (1): - second +test_expect_success 'name entry after email entry, case-insensitive' ' + test_when_finished "rm .mailmap" && + cp default.map .mailmap && -Repo Guy (1): - initial + test_config mailmap.file internal.map && + cat >internal.map <<-\EOF && + <bugs@company.xy> <bugs@company.xx> + Internal Guy <BUGS@Company.xx> + EOF -EOF + cat >expect <<-\EOF && + Internal Guy (1): + second -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 && + 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 ' -cat >expect << EOF -$GIT_AUTHOR_NAME (1): - initial +test_expect_success 'No mailmap files, but configured' ' + cat >expect <<-EOF && + $GIT_AUTHOR_NAME (1): + initial -nick1 (1): - second + nick1 (1): + second -EOF -test_expect_success 'No mailmap files, but configured' ' - rm -f .mailmap internal_mailmap/.mailmap && + EOF git shortlog HEAD >actual && test_cmp expect actual ' @@ -198,21 +258,26 @@ test_expect_success 'No mailmap files, but configured' ' test_expect_success 'setup mailmap blob tests' ' git checkout -b map && test_when_finished "git checkout main" && - cat >just-bugs <<- EOF && + cat >just-bugs <<-\EOF && Blob Guy <bugs@company.xx> EOF - cat >both <<- EOF && + cat >both <<-EOF && Blob Guy <$GIT_AUTHOR_EMAIL> Blob Guy <bugs@company.xx> EOF printf "Tricky Guy <$GIT_AUTHOR_EMAIL>" >no-newline && git add just-bugs both no-newline && 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_when_finished "rm .mailmap" && + cp default.map .mailmap && + cat >expect <<-\EOF && Blob Guy (1): second @@ -226,6 +291,9 @@ test_expect_success 'mailmap.blob set' ' ' test_expect_success 'mailmap.blob overrides .mailmap' ' + test_when_finished "rm .mailmap" && + cp default.map .mailmap && + cat >expect <<-\EOF && Blob Guy (2): initial @@ -252,7 +320,28 @@ test_expect_success 'mailmap.file overrides mailmap.blob' ' test_cmp expect actual ' +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 && + Repo Guy (1): + initial + + nick1 (1): + second + + EOF + 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 @@ -261,7 +350,17 @@ test_expect_success 'mailmap.blob can be missing' ' second EOF - git -c mailmap.blob=map:nonexistent shortlog HEAD >actual && + 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 ' @@ -270,11 +369,15 @@ test_expect_success 'mailmap.blob defaults to off in non-bare repo' ' ( cd non-bare && 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 && test_cmp expect actual && rm .mailmap && - echo " 1 $GIT_AUTHOR_NAME" >expect && + cat >expect <<-EOF && + 1 $GIT_AUTHOR_NAME + EOF git shortlog -ns HEAD >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 && ( cd bare && - echo " 1 Fake Name" >expect && + cat >expect <<-\EOF && + 1 Fake Name + EOF git shortlog -ns HEAD >actual && test_cmp expect actual ) @@ -303,178 +408,258 @@ test_expect_success 'mailmap.blob can handle blobs without trailing newline' ' test_cmp expect actual ' -test_expect_success 'cleanup after mailmap.blob tests' ' - rm -f .mailmap -' - 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" && + 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 && test_cmp expect actual ' 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" && + 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 && test_cmp expect actual ' -# Extended mailmap configurations should give us the following output for shortlog -cat >expect << EOF -$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> (1): - initial +test_expect_success 'gitmailmap(5) example output: setup' ' + 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 -CTO <cto@company.xx> (1): - seventh + test_commit -C doc --author "Joe <bugs@example.com>" F && + test_commit -C doc --author "Jane <bugs@example.com>" G && -Other Author <other@author.xx> (2): - third - fourth + cat >>expect <<-\EOF && -Santa Claus <santa.claus@northpole.xx> (2): - fifth - sixth + 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> -Some Dude <some@dude.xx> (1): - second + 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 +' -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 && + 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): + initial + + CTO <cto@company.xx> (1): + seventh + + Other Author <other@author.xx> (2): + third + fourth + + Santa Claus <santa.claus@northpole.xx> (2): + fifth + sixth + + Some Dude <some@dude.xx> (1): + second + + EOF git shortlog -e HEAD >actual && test_cmp expect actual ' -# git log with --pretty format which uses the name and email mailmap placemarkers -cat >expect << EOF -Author CTO <cto@coompany.xx> maps to CTO <cto@company.xx> -Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> +test_expect_success 'Log output (complex mapping)' ' + test_config mailmap.file complex.map && -Author claus <me@company.xx> maps to Santa Claus <santa.claus@northpole.xx> -Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> + cat >expect <<-EOF && + Author CTO <cto@coompany.xx> maps to CTO <cto@company.xx> + Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> -Author santa <me@company.xx> maps to Santa Claus <santa.claus@northpole.xx> -Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> + Author claus <me@company.xx> maps to Santa Claus <santa.claus@northpole.xx> + Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> -Author nick2 <nick2@company.xx> maps to Other Author <other@author.xx> -Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> + Author santa <me@company.xx> maps to Santa Claus <santa.claus@northpole.xx> + Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> -Author nick2 <bugs@company.xx> maps to Other Author <other@author.xx> -Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> + Author nick2 <nick2@company.xx> maps to Other Author <other@author.xx> + Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> -Author nick1 <bugs@company.xx> maps to Some Dude <some@dude.xx> -Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> + Author nick2 <bugs@company.xx> maps to Other Author <other@author.xx> + Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> -Author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> maps to $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> -Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> -EOF + Author nick1 <bugs@company.xx> maps to Some Dude <some@dude.xx> + Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> + + Author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> maps to $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> + Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> + 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 && test_cmp expect actual ' -cat >expect << EOF -Author email cto@coompany.xx has local-part cto -Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME +test_expect_success 'Log output (local-part email address)' ' + cat >expect <<-EOF && + Author email cto@coompany.xx has local-part cto + Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME -Author email me@company.xx has local-part me -Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + Author email me@company.xx has local-part me + Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME -Author email me@company.xx has local-part me -Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + Author email me@company.xx has local-part me + Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME -Author email nick2@company.xx has local-part nick2 -Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + Author email nick2@company.xx has local-part nick2 + Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME -Author email bugs@company.xx has local-part bugs -Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + Author email bugs@company.xx has local-part bugs + Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME -Author email bugs@company.xx has local-part bugs -Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + Author email bugs@company.xx has local-part bugs + Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME -Author email author@example.com has local-part author -Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME -EOF + Author email author@example.com has local-part author + Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + 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 && test_cmp expect actual ' -cat >expect << EOF -Author: CTO <cto@company.xx> -Author: Santa Claus <santa.claus@northpole.xx> -Author: Santa Claus <santa.claus@northpole.xx> -Author: Other Author <other@author.xx> -Author: Other Author <other@author.xx> -Author: Some Dude <some@dude.xx> -Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> -EOF - test_expect_success 'Log output with --use-mailmap' ' + test_config mailmap.file complex.map && + + cat >expect <<-EOF && + Author: CTO <cto@company.xx> + Author: Santa Claus <santa.claus@northpole.xx> + Author: Santa Claus <santa.claus@northpole.xx> + Author: Other Author <other@author.xx> + Author: Other Author <other@author.xx> + Author: Some Dude <some@dude.xx> + Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> + EOF + git log --use-mailmap | grep Author >actual && test_cmp expect actual ' -cat >expect << EOF -Author: CTO <cto@company.xx> -Author: Santa Claus <santa.claus@northpole.xx> -Author: Santa Claus <santa.claus@northpole.xx> -Author: Other Author <other@author.xx> -Author: Other Author <other@author.xx> -Author: Some Dude <some@dude.xx> -Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> -EOF - test_expect_success 'Log output with log.mailmap' ' + test_config mailmap.file complex.map && + + cat >expect <<-EOF && + Author: CTO <cto@company.xx> + Author: Santa Claus <santa.claus@northpole.xx> + Author: Santa Claus <santa.claus@northpole.xx> + Author: Other Author <other@author.xx> + Author: Other Author <other@author.xx> + Author: Some Dude <some@dude.xx> + Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> + EOF + git -c log.mailmap=True log | grep Author >actual && test_cmp expect actual ' test_expect_success 'log.mailmap=false disables mailmap' ' - cat >expect <<- EOF && + cat >expect <<-EOF && Author: CTO <cto@coompany.xx> Author: claus <me@company.xx> Author: santa <me@company.xx> @@ -483,12 +668,12 @@ test_expect_success 'log.mailmap=false disables mailmap' ' Author: nick1 <bugs@company.xx> Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> EOF - git -c log.mailmap=False log | grep Author > actual && + git -c log.mailmap=false log | grep Author >actual && test_cmp expect actual ' test_expect_success '--no-use-mailmap disables mailmap' ' - cat >expect <<- EOF && + cat >expect <<-EOF && Author: CTO <cto@coompany.xx> Author: claus <me@company.xx> Author: santa <me@company.xx> @@ -501,60 +686,200 @@ test_expect_success '--no-use-mailmap disables mailmap' ' test_cmp expect actual ' -cat >expect <<\EOF -Author: Santa Claus <santa.claus@northpole.xx> -Author: Santa Claus <santa.claus@northpole.xx> -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> + EOF git log --use-mailmap --author Santa | grep Author >actual && test_cmp expect actual ' -cat >expect <<\EOF -Author: Santa Claus <santa.claus@northpole.xx> -Author: Santa Claus <santa.claus@northpole.xx> -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> + EOF + git -c log.mailmap=True log --author Santa | grep Author >actual && test_cmp expect actual ' test_expect_success 'log.mailmap is true by default these days' ' + test_config mailmap.file complex.map && git log --author Santa | grep Author >actual && test_cmp expect actual ' 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 && test_must_be_empty actual ' -# git blame -cat >expect <<EOF -^OBJI ($GIT_AUTHOR_NAME DATE 1) one -OBJID (Some Dude DATE 2) two -OBJID (Other Author DATE 3) three -OBJID (Other Author DATE 4) four -OBJID (Santa Claus DATE 5) five -OBJID (Santa Claus DATE 6) six -OBJID (CTO DATE 7) seven -EOF -test_expect_success 'Blame output (complex mapping)' ' - git blame one >actual && - fuzz_blame actual >actual.fuzz && +test_expect_success 'Blame --porcelain output (complex mapping)' ' + test_config mailmap.file complex.map && + + cat >expect <<-EOF && + 1 1 1 + A U Thor + 2 2 1 + Some Dude + 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 + + git blame --porcelain one >actual.blame && + 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 ' -cat >expect <<\EOF -Some Dude <some@dude.xx> -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> + EOF + test_must_fail git commit --author "nick" --allow-empty -meight && git commit --author "Some Dude" --allow-empty -meight && git show --pretty=format:"%an <%ae>%n" >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 diff --git a/t/t7509-commit-authorship.sh b/t/t7509-commit-authorship.sh index 500ab2fe72..ee6c47416e 100755 --- a/t/t7509-commit-authorship.sh +++ b/t/t7509-commit-authorship.sh @@ -18,11 +18,8 @@ message_body () { } test_expect_success '-C option copies authorship and message' ' - echo "Initial" >foo && - git add foo && - test_tick && - git commit -m "Initial Commit" --author Frigate\ \<flying@over.world\> && - git tag Initial && + test_commit --author Frigate\ \<flying@over.world\> \ + "Initial Commit" foo Initial Initial && echo "Test 1" >>foo && test_tick && git commit -a -C Initial && diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 9f1aa9ef25..8f7591c9cc 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -690,21 +690,9 @@ test_expect_success 'grep -C1 hunk mark between files' ' ' test_expect_success 'log grep setup' ' - echo a >>file && - test_tick && - GIT_AUTHOR_NAME="With * Asterisk" \ - 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_commit --append --author "With * Asterisk <xyzzy@frotz.com>" second file a && + test_commit --append third file a && + test_commit --append --author "Night Fall <nitfol@frobozz.com>" fourth file a ' test_expect_success 'log grep (1)' ' diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 2f08ce7cba..c31a411372 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -178,19 +178,28 @@ debug () { GIT_DEBUGGER="${GIT_DEBUGGER}" "$@" <&6 >&5 2>&7 } -# Call test_commit with the arguments -# [-C <directory>] <message> [<file> [<contents> [<tag>]]]" +# Usage: test_commit [options] <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 # message, and tag the resulting commit with the given tag name. # # <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 () { notick= && + append= && + author= && signoff= && indir= && while test $# != 0 @@ -199,6 +208,13 @@ test_commit () { --notick) notick=yes ;; + --append) + append=yes + ;; + --author) + author="$2" + shift + ;; --signoff) signoff="$1" ;; @@ -214,13 +230,20 @@ test_commit () { done && indir=${indir:+"$indir"/} && 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" && if test -z "$notick" then test_tick 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}" } |