git/t/t4203-mailmap.sh

#!/bin/sh

test_description='.mailmap configurations'

GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME

TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh

test_expect_success 'setup commits and contacts file' '
	test_commit initial one one &&
	test_commit --author "nick1 <[email protected]>" --append second one two
'

test_expect_success 'check-mailmap no arguments' '
	test_must_fail git check-mailmap
'

test_expect_success 'check-mailmap arguments' '
	cat >expect <<-EOF &&
	$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
	nick1 <[email protected]>
	EOF
	git check-mailmap \
		"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" \
		"nick1 <[email protected]>" >actual &&
	test_cmp expect actual
'

test_expect_success 'check-mailmap --stdin' '
	cat >expect <<-EOF &&
	$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
	nick1 <[email protected]>
	EOF
	git check-mailmap --stdin <expect >actual &&
	test_cmp expect actual
'

test_expect_success 'check-mailmap --stdin arguments: no mapping' '
	test_when_finished "rm contacts" &&
	cat >contacts <<-EOF &&
	$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
	nick1 <[email protected]>
	EOF
	cat >expect <<-\EOF &&
	Internal Guy <[email protected]>
	EOF
	cat contacts >>expect &&

	git check-mailmap --stdin "Internal Guy <[email protected]>" \
		<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 simple address: mapping' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-EOF &&
	New Name <$GIT_AUTHOR_EMAIL>
	EOF
	cat .mailmap >expect &&
	git check-mailmap "$GIT_AUTHOR_EMAIL" >actual &&
	test_cmp expect actual
'

test_expect_success 'check-mailmap --stdin simple address: mapping' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-EOF &&
	New Name <$GIT_AUTHOR_EMAIL>
	EOF
	cat >stdin <<-EOF &&
	$GIT_AUTHOR_EMAIL
	EOF
	cat .mailmap >expect &&
	git check-mailmap --stdin <stdin >actual &&
	test_cmp expect actual
'

test_expect_success 'check-mailmap simple address: no mapping' '
	cat >expect <<-EOF &&
	<[email protected]>
	EOF
	git check-mailmap "[email protected]" >actual &&
	test_cmp expect actual
'

test_expect_success 'check-mailmap --stdin simple address: no mapping' '
	cat >expect <<-EOF &&
	<[email protected]>
	EOF
	cat >stdin <<-EOF &&
	[email protected]
	EOF
	git check-mailmap --stdin <stdin >actual &&
	test_cmp expect actual
'

test_expect_success 'No mailmap' '
	cat >expect <<-EOF &&
	$GIT_AUTHOR_NAME (1):
	      initial

	nick1 (1):
	      second

	EOF
	git shortlog HEAD >actual &&
	test_cmp expect actual
'

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):
	      initial

	nick1 (1):
	      second

	EOF
	git shortlog HEAD >actual &&
	test_cmp expect actual
'

test_expect_success 'mailmap.file set' '
	test_when_finished "rm .mailmap" &&
	cp default.map .mailmap &&

	test_config mailmap.file internal.map &&
	cat >internal.map <<-\EOF &&
	Internal Guy <[email protected]>
	EOF

	cat >expect <<-\EOF &&
	Internal Guy (1):
	      second

	Repo Guy (1):
	      initial

	EOF
	git shortlog HEAD >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
	)
'

test_expect_success 'mailmap.file override' '
	test_config mailmap.file internal.map &&
	cat >internal.map <<-EOF &&
	Internal Guy <[email protected]>
	External Guy <$GIT_AUTHOR_EMAIL>
	EOF

	cat >expect <<-\EOF &&
	External Guy (1):
	      initial

	Internal Guy (1):
	      second

	EOF
	git shortlog HEAD >actual &&
	test_cmp expect actual
'

test_expect_success 'mailmap.file non-existent' '
	test_when_finished "rm .mailmap" &&
	cp default.map .mailmap &&

	cat >expect <<-\EOF &&
	Repo Guy (1):
	      initial

	nick1 (1):
	      second

	EOF
	git shortlog HEAD >actual &&
	test_cmp expect actual
'

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 &&
	<[email protected]> <[email protected]>
	Internal Guy <[email protected]>
	EOF

	cat >expect <<-\EOF &&
	Internal Guy (1):
	      second

	Repo Guy (1):
	      initial

	EOF

	git shortlog HEAD >actual &&
	test_cmp expect actual
'

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 &&
	<[email protected]> <[email protected]>
	Internal Guy <[email protected]>
	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 <[email protected]> NICK1 <[email protected]>
	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):
	      initial

	nick1 (1):
	      second

	EOF
	git shortlog HEAD >actual &&
	test_cmp expect actual
'

test_expect_success 'setup mailmap blob tests' '
	git checkout -b map &&
	test_when_finished "git checkout main" &&
	cat >just-bugs <<-\EOF &&
	Blob Guy <[email protected]>
	EOF
	cat >both <<-EOF &&
	Blob Guy <$GIT_AUTHOR_EMAIL>
	Blob Guy <[email protected]>
	EOF
	printf "Tricky Guy <$GIT_AUTHOR_EMAIL>" >no-newline &&
	git add just-bugs both no-newline &&
	git commit -m "my mailmaps" &&

	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

	Repo Guy (1):
	      initial

	EOF
	git -c mailmap.blob=map:just-bugs shortlog HEAD >actual &&
	test_cmp expect actual
'

test_expect_success 'mailmap.blob overrides .mailmap' '
	test_when_finished "rm .mailmap" &&
	cp default.map .mailmap &&

	cat >expect <<-\EOF &&
	Blob Guy (2):
	      initial
	      second

	EOF
	git -c mailmap.blob=map:both shortlog HEAD >actual &&
	test_cmp expect actual
'

test_expect_success 'mailmap.file overrides mailmap.blob' '
	cat >expect <<-\EOF &&
	Blob Guy (1):
	      second

	Internal Guy (1):
	      initial

	EOF
	git \
	  -c mailmap.blob=map:both \
	  -c mailmap.file=internal.map \
	  shortlog HEAD >actual &&
	test_cmp expect actual
'

test_expect_success 'mailmap.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

	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_grep "mailmap is not a blob" err &&
	test_cmp expect actual
'

test_expect_success 'mailmap.blob defaults to off in non-bare repo' '
	git init non-bare &&
	(
		cd non-bare &&
		test_commit one .mailmap "Fake Name <$GIT_AUTHOR_EMAIL>" &&
		cat >expect <<-\EOF &&
		     1	Fake Name
		EOF
		git shortlog -ns HEAD >actual &&
		test_cmp expect actual &&
		rm .mailmap &&
		cat >expect <<-EOF &&
		     1	$GIT_AUTHOR_NAME
		EOF
		git shortlog -ns HEAD >actual &&
		test_cmp expect actual
	)
'

test_expect_success 'mailmap.blob defaults to HEAD:.mailmap in bare repo' '
	git clone --bare non-bare bare &&
	(
		cd bare &&
		cat >expect <<-\EOF &&
		     1	Fake Name
		EOF
		git shortlog -ns HEAD >actual &&
		test_cmp expect actual
	)
'

test_expect_success 'mailmap.blob can handle blobs without trailing newline' '
	cat >expect <<-\EOF &&
	Tricky Guy (1):
	      initial

	nick1 (1):
	      second

	EOF
	git -c mailmap.blob=map:no-newline shortlog HEAD >actual &&
	test_cmp expect actual
'

test_expect_success 'single-character name' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-EOF &&
	A <$GIT_AUTHOR_EMAIL>
	EOF

	cat >expect <<-EOF &&
	     1	A <$GIT_AUTHOR_EMAIL>
	     1	nick1 <[email protected]>
	EOF
	git shortlog -es HEAD >actual &&
	test_cmp expect actual
'

test_expect_success 'preserve canonical email case' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-EOF &&
	<[email protected]> <$GIT_AUTHOR_EMAIL>
	EOF

	cat >expect <<-EOF &&
	     1	$GIT_AUTHOR_NAME <[email protected]>
	     1	nick1 <[email protected]>
	EOF
	git shortlog -es HEAD >actual &&
	test_cmp expect actual
'

test_expect_success 'gitmailmap(5) example output: setup' '
	test_create_repo doc &&
	test_commit -C doc --author "Joe Developer <[email protected]>" A &&
	test_commit -C doc --author "Joe R. Developer <[email protected]>" B &&
	test_commit -C doc --author "Jane Doe <[email protected]>" 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 <[email protected]>
	Jane Doe <[email protected]>
	Jane Doe <jane@desktop.(none)>
	EOF

	cat >expect <<-\EOF &&
	Author Joe Developer <[email protected]> maps to Joe R. Developer <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author Joe R. Developer <[email protected]> maps to Joe R. Developer <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author Jane Doe <[email protected]> maps to Jane Doe <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author Jane Doe <jane@laptop.(none)> maps to Jane Doe <jane@laptop.(none)>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author Jane D. <jane@desktop.(none)> maps to Jane Doe <jane@desktop.(none)>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>
	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 <[email protected]>
	Jane Doe <[email protected]> <jane@laptop.(none)>
	Jane Doe <[email protected]> <jane@desktop.(none)>
	EOF

	cat >expect <<-\EOF &&
	Author Joe Developer <[email protected]> maps to Joe R. Developer <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author Joe R. Developer <[email protected]> maps to Joe R. Developer <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author Jane Doe <[email protected]> maps to Jane Doe <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author Jane Doe <jane@laptop.(none)> maps to Jane Doe <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author Jane D. <jane@desktop.(none)> maps to Jane Doe <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>
	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 <[email protected]> Joe <[email protected]>
	Jane Doe <[email protected]> Jane <[email protected]>
	EOF

	test_commit -C doc --author "Joe <[email protected]>" F &&
	test_commit -C doc --author "Jane <[email protected]>" G &&

	cat >>expect <<-\EOF &&

	Author Joe <[email protected]> maps to Joe R. Developer <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author Jane <[email protected]> maps to Jane Doe <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>
	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>
	<[email protected]> <[email protected]>
	Some Dude <[email protected]>         nick1 <[email protected]>
	Other Author <[email protected]>   nick2 <[email protected]>
	Other Author <[email protected]>         <[email protected]>
	Santa Claus <[email protected]> <[email protected]>
	EOF

	test_commit --author "nick2 <[email protected]>" --append third one three &&
	test_commit --author "nick2 <[email protected]>" --append fourth one four &&
	test_commit --author "santa <[email protected]>" --append fifth one five &&
	test_commit --author "claus <[email protected]>" --append sixth one six &&
	test_commit --author "CTO <[email protected]>" --append seventh one seven &&

	cat >expect <<-EOF &&
	$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> (1):
	      initial

	CTO <[email protected]> (1):
	      seventh

	Other Author <[email protected]> (2):
	      third
	      fourth

	Santa Claus <[email protected]> (2):
	      fifth
	      sixth

	Some Dude <[email protected]> (1):
	      second

	EOF

	git shortlog -e HEAD >actual &&
	test_cmp expect actual

'

test_expect_success 'Log output (complex mapping)' '
	test_config mailmap.file complex.map &&

	cat >expect <<-EOF &&
	Author CTO <[email protected]> maps to CTO <[email protected]>
	Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL>

	Author claus <[email protected]> maps to Santa Claus <[email protected]>
	Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL>

	Author santa <[email protected]> maps to Santa Claus <[email protected]>
	Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL>

	Author nick2 <[email protected]> maps to Other Author <[email protected]>
	Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL>

	Author nick2 <[email protected]> maps to Other Author <[email protected]>
	Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL>

	Author nick1 <[email protected]> maps to Some Dude <[email protected]>
	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

	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_expect_success 'Log output (local-part email address)' '
	cat >expect <<-EOF &&
	Author email [email protected] has local-part cto
	Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME

	Author email [email protected] has local-part me
	Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME

	Author email [email protected] has local-part me
	Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME

	Author email [email protected] has local-part nick2
	Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME

	Author email [email protected] has local-part bugs
	Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME

	Author email [email protected] has local-part bugs
	Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME

	Author email [email protected] has local-part author
	Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME
	EOF

	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_expect_success 'Log output with --use-mailmap' '
	test_config mailmap.file complex.map &&

	cat >expect <<-EOF &&
	Author: CTO <[email protected]>
	Author: Santa Claus <[email protected]>
	Author: Santa Claus <[email protected]>
	Author: Other Author <[email protected]>
	Author: Other Author <[email protected]>
	Author: Some Dude <[email protected]>
	Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
	EOF

	git log --use-mailmap >log &&
	grep Author log >actual &&
	test_cmp expect actual
'

test_expect_success 'Log output with log.mailmap' '
	test_config mailmap.file complex.map &&

	cat >expect <<-EOF &&
	Author: CTO <[email protected]>
	Author: Santa Claus <[email protected]>
	Author: Santa Claus <[email protected]>
	Author: Other Author <[email protected]>
	Author: Other Author <[email protected]>
	Author: Some Dude <[email protected]>
	Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
	EOF

	git -c log.mailmap=True log >log &&
	grep Author log >actual &&
	test_cmp expect actual
'

test_expect_success 'log.mailmap=false disables mailmap' '
	cat >expect <<-EOF &&
	Author: CTO <[email protected]>
	Author: claus <[email protected]>
	Author: santa <[email protected]>
	Author: nick2 <[email protected]>
	Author: nick2 <[email protected]>
	Author: nick1 <[email protected]>
	Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
	EOF
	git -c log.mailmap=false log >log &&
	grep Author log >actual &&
	test_cmp expect actual
'

test_expect_success '--no-use-mailmap disables mailmap' '
	cat >expect <<-EOF &&
	Author: CTO <[email protected]>
	Author: claus <[email protected]>
	Author: santa <[email protected]>
	Author: nick2 <[email protected]>
	Author: nick2 <[email protected]>
	Author: nick1 <[email protected]>
	Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
	EOF
	git log --no-use-mailmap >log &&
	grep Author log >actual &&
	test_cmp expect actual
'

test_expect_success 'Grep author with --use-mailmap' '
	test_config mailmap.file complex.map &&

	cat >expect <<-\EOF &&
	Author: Santa Claus <[email protected]>
	Author: Santa Claus <[email protected]>
	EOF
	git log --use-mailmap --author Santa >log &&
	grep Author log >actual &&
	test_cmp expect actual
'

test_expect_success 'Grep author with log.mailmap' '
	test_config mailmap.file complex.map &&

	cat >expect <<-\EOF &&
	Author: Santa Claus <[email protected]>
	Author: Santa Claus <[email protected]>
	EOF

	git -c log.mailmap=True log --author Santa >log &&
	grep Author log >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 >log &&
	grep Author log >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 "<[email protected]>" >actual &&
	test_must_be_empty actual
'

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 &&

	NUM="[0-9][0-9]*" &&
	sed -n <actual.blame >actual.fuzz \
		-e "s/^author //p" \
		-e "s/^$OID_REGEX \\($NUM $NUM $NUM\\)$/\\1/p"  &&
	test_cmp expect actual.fuzz
'

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 <[email protected]>
	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 <[email protected]>" A &&
	test_commit -C comm --author "B <[email protected]>" 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 <[email protected]>

	; Bee <[email protected]>
	Cee <[email protected]> <#@example.com>
	Dee <[email protected]> <d@e#ample.com>
	EOF

	cat >expect <<-\EOF &&
	Author A <[email protected]> maps to A <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author B <[email protected]> maps to ; Bee <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author C <#@example.com> maps to Cee <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author D <d@e#ample.com> maps to Dee <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>
	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 <[email protected]>" A &&
	test_commit -C space --author "B <[email protected]>" B &&
	test_commit -C space --author " C <[email protected]>" C &&
	test_commit -C space --author " D  <[email protected]>" D &&
	test_commit -C space --author "E E <[email protected]>" E &&
	test_commit -C space --author "F  F <[email protected]>" F &&
	test_commit -C space --author "G   G <[email protected]>" G &&
	test_commit -C space --author "H   H <[email protected]>" H &&

	test_config -C space mailmap.file ../space.map &&
	cat >>space.map <<-\EOF &&
	Ah <[email protected]> < [email protected] >
	Bee <[email protected]  > <  [email protected]  >
	Cee <[email protected]> C <[email protected]>
	dee <[email protected]>  D  <[email protected]>
	eee <[email protected]> E E <[email protected]>
	eff <[email protected]> F  F <[email protected]>
	gee <[email protected]> G   G <[email protected]>
	aitch <[email protected]> H  H <[email protected]>
	EOF

	cat >expect <<-\EOF &&
	Author A <[email protected]> maps to A <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author B <[email protected]> maps to B <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author C <[email protected]> maps to Cee <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author D <[email protected]> maps to dee <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author E E <[email protected]> maps to eee <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author F  F <[email protected]> maps to eff <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author G   G <[email protected]> maps to gee <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author H   H <[email protected]> maps to H   H <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>
	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 <[email protected]>" B &&
	test_commit -C empty --author "C <[email protected]>" C &&

	test_config -C empty mailmap.file ../empty.map &&
	cat >>empty.map <<-\EOF &&
	Ah <[email protected]> <>
	Bee <[email protected]> <>
	Cee <> <[email protected]>
	EOF

	cat >expect <<-\EOF &&
	Author A <> maps to Bee <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author B <[email protected]> maps to B <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>

	Author C <[email protected]> maps to C <[email protected]>
	Committer C O Mitter <[email protected]> maps to C O Mitter <[email protected]>
	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_expect_success 'set up mailmap location tests' '
	git init --bare loc-bare &&
	git --git-dir=loc-bare --work-tree=. commit \
		--allow-empty -m foo --author="Orig <[email protected]>" &&
	echo "New <[email protected]> <[email protected]>" >loc-bare/.mailmap
'

test_expect_success 'bare repo with --work-tree finds mailmap at top-level' '
	git -C loc-bare --work-tree=. log -1 --format=%aE >actual &&
	echo [email protected] >expect &&
	test_cmp expect actual
'

test_expect_success 'bare repo does not look in current directory' '
	git -C loc-bare log -1 --format=%aE >actual &&
	echo [email protected] >expect &&
	test_cmp expect actual
'

test_expect_success 'non-git shortlog respects mailmap in current dir' '
	git --git-dir=loc-bare log -1 >input &&
	nongit cp "$TRASH_DIRECTORY/loc-bare/.mailmap" . &&
	nongit git shortlog -s <input >actual &&
	echo "     1	New" >expect &&
	test_cmp expect actual
'

test_expect_success 'shortlog on stdin respects mailmap from repo' '
	cp loc-bare/.mailmap . &&
	git shortlog -s <input >actual &&
	echo "     1	New" >expect &&
	test_cmp expect actual
'

test_expect_success 'find top-level mailmap from subdir' '
	git clone loc-bare loc-wt &&
	cp loc-bare/.mailmap loc-wt &&
	mkdir loc-wt/subdir &&
	git -C loc-wt/subdir log -1 --format=%aE >actual &&
	echo [email protected] >expect &&
	test_cmp expect actual
'

test_expect_success SYMLINKS 'set up symlink tests' '
	git commit --allow-empty -m foo --author="Orig <[email protected]>" &&
	echo "New <[email protected]> <[email protected]>" >map &&
	rm -f .mailmap
'

test_expect_success SYMLINKS 'symlinks respected in mailmap.file' '
	test_when_finished "rm symlink" &&
	ln -s map symlink &&
	git -c mailmap.file="$(pwd)/symlink" log -1 --format=%aE >actual &&
	echo "[email protected]" >expect &&
	test_cmp expect actual
'

test_expect_success SYMLINKS 'symlinks respected in non-repo shortlog' '
	git log -1 >input &&
	test_when_finished "nongit rm .mailmap" &&
	nongit ln -sf "$TRASH_DIRECTORY/map" .mailmap &&
	nongit git shortlog -s <input >actual &&
	echo "     1	New" >expect &&
	test_cmp expect actual
'

test_expect_success SYMLINKS 'symlinks not respected in-tree' '
	test_when_finished "rm .mailmap" &&
	ln -s map .mailmap &&
	git log -1 --format=%aE >actual &&
	echo "[email protected]" >expect &&
	test_cmp expect actual
'

test_expect_success 'prepare for cat-file --mailmap' '
	rm -f .mailmap &&
	git commit --allow-empty -m foo --author="Orig <[email protected]>"
'

test_expect_success '--no-use-mailmap disables mailmap in cat-file' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-EOF &&
	A U Thor <[email protected]> Orig <[email protected]>
	EOF
	cat >expect <<-EOF &&
	author Orig <[email protected]>
	EOF
	git cat-file --no-use-mailmap commit HEAD >log &&
	sed -n "/^author /s/\([^>]*>\).*/\1/p" log >actual &&
	test_cmp expect actual
'

test_expect_success '--use-mailmap enables mailmap in cat-file' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-EOF &&
	A U Thor <[email protected]> Orig <[email protected]>
	EOF
	cat >expect <<-EOF &&
	author A U Thor <[email protected]>
	EOF
	git cat-file --use-mailmap commit HEAD >log &&
	sed -n "/^author /s/\([^>]*>\).*/\1/p" log >actual &&
	test_cmp expect actual
'

test_expect_success '--no-mailmap disables mailmap in cat-file for annotated tag objects' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-EOF &&
	Orig <[email protected]> C O Mitter <[email protected]>
	EOF
	cat >expect <<-EOF &&
	tagger C O Mitter <[email protected]>
	EOF
	git tag -a -m "annotated tag" v1 &&
	git cat-file --no-mailmap -p v1 >log &&
	sed -n "/^tagger /s/\([^>]*>\).*/\1/p" log >actual &&
	test_cmp expect actual
'

test_expect_success '--mailmap enables mailmap in cat-file for annotated tag objects' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-EOF &&
	Orig <[email protected]> C O Mitter <[email protected]>
	EOF
	cat >expect <<-EOF &&
	tagger Orig <[email protected]>
	EOF
	git tag -a -m "annotated tag" v2 &&
	git cat-file --mailmap -p v2 >log &&
	sed -n "/^tagger /s/\([^>]*>\).*/\1/p" log >actual &&
	test_cmp expect actual
'

test_expect_success 'git cat-file -s returns correct size with --use-mailmap' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-\EOF &&
	C O Mitter <[email protected]> Orig <[email protected]>
	EOF
	git cat-file commit HEAD >commit.out &&
	echo $(wc -c <commit.out) >expect &&
	git cat-file --use-mailmap commit HEAD >commit.out &&
	echo $(wc -c <commit.out) >>expect &&
	git cat-file -s HEAD >actual &&
	git cat-file --use-mailmap -s HEAD >>actual &&
	test_cmp expect actual
'

test_expect_success 'git cat-file -s returns correct size with --use-mailmap for tag objects' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-\EOF &&
	Orig <[email protected]> C O Mitter <[email protected]>
	EOF
	git tag -a -m "annotated tag" v3 &&
	git cat-file tag v3 >tag.out &&
	echo $(wc -c <tag.out) >expect &&
	git cat-file --use-mailmap tag v3 >tag.out &&
	echo $(wc -c <tag.out) >>expect &&
	git cat-file -s v3 >actual &&
	git cat-file --use-mailmap -s v3 >>actual &&
	test_cmp expect actual
'

test_expect_success 'git cat-file --batch-check returns correct size with --use-mailmap' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-\EOF &&
	C O Mitter <[email protected]> Orig <[email protected]>
	EOF
	git cat-file commit HEAD >commit.out &&
	commit_size=$(wc -c <commit.out) &&
	commit_sha=$(git rev-parse HEAD) &&
	echo $commit_sha commit $commit_size >expect &&
	git cat-file --use-mailmap commit HEAD >commit.out &&
	commit_size=$(wc -c <commit.out) &&
	echo $commit_sha commit $commit_size >>expect &&
	echo "HEAD" >in &&
	git cat-file --batch-check <in >actual &&
	git cat-file --use-mailmap --batch-check <in >>actual &&
	test_cmp expect actual
'

test_expect_success 'git cat-file --batch-command returns correct size with --use-mailmap' '
	test_when_finished "rm .mailmap" &&
	cat >.mailmap <<-\EOF &&
	C O Mitter <[email protected]> Orig <[email protected]>
	EOF
	git cat-file commit HEAD >commit.out &&
	commit_size=$(wc -c <commit.out) &&
	commit_sha=$(git rev-parse HEAD) &&
	echo $commit_sha commit $commit_size >expect &&
	git cat-file --use-mailmap commit HEAD >commit.out &&
	commit_size=$(wc -c <commit.out) &&
	echo $commit_sha commit $commit_size >>expect &&
	echo "info HEAD" >in &&
	git cat-file --batch-command <in >actual &&
	git cat-file --use-mailmap --batch-command <in >>actual &&
	test_cmp expect actual
'

test_done