Merge branch 'pb/pretty-email-without-domain-part'

The custom format for "git log --format=<format>" learned the l/L
placeholder that is similar to e/E that fills in the e-mail
address, but only the local part on the left side of '@'.

* pb/pretty-email-without-domain-part:
  pretty: add "%aL" etc. to show local-part of email addresses
  t4203: use test-lib.sh definitions
  t6006: use test-lib.sh definitions
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index b87e2e8..31c6e8d 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -163,6 +163,9 @@
 '%ae':: author email
 '%aE':: author email (respecting .mailmap, see linkgit:git-shortlog[1]
 	or linkgit:git-blame[1])
+'%al':: author email local-part (the part before the '@' sign)
+'%aL':: author local-part (see '%al') respecting .mailmap, see
+	linkgit:git-shortlog[1] or linkgit:git-blame[1])
 '%ad':: author date (format respects --date= option)
 '%aD':: author date, RFC2822 style
 '%ar':: author date, relative
@@ -175,6 +178,9 @@
 '%ce':: committer email
 '%cE':: committer email (respecting .mailmap, see
 	linkgit:git-shortlog[1] or linkgit:git-blame[1])
+'%cl':: author email local-part (the part before the '@' sign)
+'%cL':: author local-part (see '%cl') respecting .mailmap, see
+	linkgit:git-shortlog[1] or linkgit:git-blame[1])
 '%cd':: committer date (format respects --date= option)
 '%cD':: committer date, RFC2822 style
 '%cr':: committer date, relative
diff --git a/pretty.c b/pretty.c
index b32f036..93eb6e8 100644
--- a/pretty.c
+++ b/pretty.c
@@ -696,7 +696,7 @@
 	mail = s.mail_begin;
 	maillen = s.mail_end - s.mail_begin;
 
-	if (part == 'N' || part == 'E') /* mailmap lookup */
+	if (part == 'N' || part == 'E' || part == 'L') /* mailmap lookup */
 		mailmap_name(&mail, &maillen, &name, &namelen);
 	if (part == 'n' || part == 'N') {	/* name */
 		strbuf_add(sb, name, namelen);
@@ -706,6 +706,13 @@
 		strbuf_add(sb, mail, maillen);
 		return placeholder_len;
 	}
+	if (part == 'l' || part == 'L') {	/* local-part */
+		const char *at = memchr(mail, '@', maillen);
+		if (at)
+			maillen = at - mail;
+		strbuf_add(sb, mail, maillen);
+		return placeholder_len;
+	}
 
 	if (!s.date_begin)
 		goto skip;
diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh
index 918ada6..586c3a8 100755
--- a/t/t4203-mailmap.sh
+++ b/t/t4203-mailmap.sh
@@ -13,8 +13,8 @@
 }
 
 test_expect_success setup '
-	cat >contacts <<-\EOF &&
-	A U Thor <author@example.com>
+	cat >contacts <<- EOF &&
+	$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
 	nick1 <bugs@company.xx>
 	EOF
 
@@ -33,19 +33,19 @@
 '
 
 test_expect_success 'check-mailmap arguments' '
-	cat >expect <<-\EOF &&
-	A U Thor <author@example.com>
+	cat >expect <<- EOF &&
+	$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
 	nick1 <bugs@company.xx>
 	EOF
 	git check-mailmap \
-		"A U Thor <author@example.com>" \
+		"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" \
 		"nick1 <bugs@company.xx>" >actual &&
 	test_cmp expect actual
 '
 
 test_expect_success 'check-mailmap --stdin' '
-	cat >expect <<-\EOF &&
-	A U Thor <author@example.com>
+	cat >expect <<- EOF &&
+	$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
 	nick1 <bugs@company.xx>
 	EOF
 	git check-mailmap --stdin <contacts >actual &&
@@ -66,8 +66,8 @@
 	test_must_fail git check-mailmap bogus
 '
 
-cat >expect <<\EOF
-A U Thor (1):
+cat >expect << EOF
+$GIT_AUTHOR_NAME (1):
       initial
 
 nick1 (1):
@@ -90,7 +90,7 @@
 EOF
 
 test_expect_success 'default .mailmap' '
-	echo "Repo Guy <author@example.com>" > .mailmap &&
+	echo "Repo Guy <$GIT_AUTHOR_EMAIL>" > .mailmap &&
 	git shortlog HEAD >actual &&
 	test_cmp expect actual
 '
@@ -122,7 +122,7 @@
 
 EOF
 test_expect_success 'mailmap.file override' '
-	echo "External Guy <author@example.com>" >> internal_mailmap/.mailmap &&
+	echo "External Guy <$GIT_AUTHOR_EMAIL>" >> internal_mailmap/.mailmap &&
 	git config mailmap.file internal_mailmap/.mailmap &&
 	git shortlog HEAD >actual &&
 	test_cmp expect actual
@@ -178,8 +178,8 @@
 	test_cmp expect actual
 '
 
-cat >expect <<\EOF
-A U Thor (1):
+cat >expect << EOF
+$GIT_AUTHOR_NAME (1):
       initial
 
 nick1 (1):
@@ -195,18 +195,18 @@
 test_expect_success 'setup mailmap blob tests' '
 	git checkout -b map &&
 	test_when_finished "git checkout master" &&
-	cat >just-bugs <<-\EOF &&
+	cat >just-bugs <<- EOF &&
 	Blob Guy <bugs@company.xx>
 	EOF
-	cat >both <<-\EOF &&
-	Blob Guy <author@example.com>
+	cat >both <<- EOF &&
+	Blob Guy <$GIT_AUTHOR_EMAIL>
 	Blob Guy <bugs@company.xx>
 	EOF
-	printf "Tricky Guy <author@example.com>" >no-newline &&
+	printf "Tricky Guy <$GIT_AUTHOR_EMAIL>" >no-newline &&
 	git add just-bugs both no-newline &&
 	git commit -m "my mailmaps" &&
-	echo "Repo Guy <author@example.com>" >.mailmap &&
-	echo "Internal Guy <author@example.com>" >internal.map
+	echo "Repo Guy <$GIT_AUTHOR_EMAIL>" >.mailmap &&
+	echo "Internal Guy <$GIT_AUTHOR_EMAIL>" >internal.map
 '
 
 test_expect_success 'mailmap.blob set' '
@@ -266,12 +266,12 @@
 	git init non-bare &&
 	(
 		cd non-bare &&
-		test_commit one .mailmap "Fake Name <author@example.com>" &&
+		test_commit one .mailmap "Fake Name <$GIT_AUTHOR_EMAIL>" &&
 		echo "     1	Fake Name" >expect &&
 		git shortlog -ns HEAD >actual &&
 		test_cmp expect actual &&
 		rm .mailmap &&
-		echo "     1	A U Thor" >expect &&
+		echo "     1	$GIT_AUTHOR_NAME" >expect &&
 		git shortlog -ns HEAD >actual &&
 		test_cmp expect actual
 	)
@@ -305,26 +305,26 @@
 '
 
 test_expect_success 'single-character name' '
-	echo "     1	A <author@example.com>" >expect &&
+	echo "     1	A <$GIT_AUTHOR_EMAIL>" >expect &&
 	echo "     1	nick1 <bugs@company.xx>" >>expect &&
-	echo "A <author@example.com>" >.mailmap &&
+	echo "A <$GIT_AUTHOR_EMAIL>" >.mailmap &&
 	test_when_finished "rm .mailmap" &&
 	git shortlog -es HEAD >actual &&
 	test_cmp expect actual
 '
 
 test_expect_success 'preserve canonical email case' '
-	echo "     1	A U Thor <AUTHOR@example.com>" >expect &&
+	echo "     1	$GIT_AUTHOR_NAME <AUTHOR@example.com>" >expect &&
 	echo "     1	nick1 <bugs@company.xx>" >>expect &&
-	echo "<AUTHOR@example.com> <author@example.com>" >.mailmap &&
+	echo "<AUTHOR@example.com> <$GIT_AUTHOR_EMAIL>" >.mailmap &&
 	test_when_finished "rm .mailmap" &&
 	git shortlog -es HEAD >actual &&
 	test_cmp expect actual
 '
 
 # Extended mailmap configurations should give us the following output for shortlog
-cat >expect <<\EOF
-A U Thor <author@example.com> (1):
+cat >expect << EOF
+$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> (1):
       initial
 
 CTO <cto@company.xx> (1):
@@ -370,7 +370,7 @@
 	git commit --author "CTO <cto@coompany.xx>" -m seventh &&
 
 	mkdir -p internal_mailmap &&
-	echo "Committed <committer@example.com>" > internal_mailmap/.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 &&
@@ -384,27 +384,27 @@
 '
 
 # git log with --pretty format which uses the name and email mailmap placemarkers
-cat >expect <<\EOF
+cat >expect << EOF
 Author CTO <cto@coompany.xx> maps to CTO <cto@company.xx>
-Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+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 C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+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 C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+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 C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+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 C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+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 C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL>
 
-Author A U Thor <author@example.com> maps to A U Thor <author@example.com>
-Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com>
+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)' '
@@ -412,14 +412,42 @@
 	test_cmp expect actual
 '
 
-cat >expect <<\EOF
+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 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 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: A U Thor <author@example.com>
+Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
 EOF
 
 test_expect_success 'Log output with --use-mailmap' '
@@ -427,14 +455,14 @@
 	test_cmp expect actual
 '
 
-cat >expect <<\EOF
+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: A U Thor <author@example.com>
+Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
 EOF
 
 test_expect_success 'Log output with log.mailmap' '
@@ -443,28 +471,28 @@
 '
 
 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>
 	Author: nick2 <nick2@company.xx>
 	Author: nick2 <bugs@company.xx>
 	Author: nick1 <bugs@company.xx>
-	Author: A U Thor <author@example.com>
+	Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
 	EOF
 	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>
 	Author: nick2 <nick2@company.xx>
 	Author: nick2 <bugs@company.xx>
 	Author: nick1 <bugs@company.xx>
-	Author: A U Thor <author@example.com>
+	Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>
 	EOF
 	git log --no-use-mailmap | grep Author > actual &&
 	test_cmp expect actual
@@ -500,8 +528,8 @@
 '
 
 # git blame
-cat >expect <<\EOF
-^OBJI (A U Thor     DATE 1) one
+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
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index cfb74d0..ebdc49c 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -109,31 +109,35 @@
 EOF
 
 # we don't test relative here
-test_format author %an%n%ae%n%ad%n%aD%n%at <<EOF
+test_format author %an%n%ae%n%al%n%ad%n%aD%n%at <<EOF
 commit $head2
-A U Thor
-author@example.com
+$GIT_AUTHOR_NAME
+$GIT_AUTHOR_EMAIL
+$TEST_AUTHOR_LOCALNAME
 Thu Apr 7 15:13:13 2005 -0700
 Thu, 7 Apr 2005 15:13:13 -0700
 1112911993
 commit $head1
-A U Thor
-author@example.com
+$GIT_AUTHOR_NAME
+$GIT_AUTHOR_EMAIL
+$TEST_AUTHOR_LOCALNAME
 Thu Apr 7 15:13:13 2005 -0700
 Thu, 7 Apr 2005 15:13:13 -0700
 1112911993
 EOF
 
-test_format committer %cn%n%ce%n%cd%n%cD%n%ct <<EOF
+test_format committer %cn%n%ce%n%cl%n%cd%n%cD%n%ct <<EOF
 commit $head2
-C O Mitter
-committer@example.com
+$GIT_COMMITTER_NAME
+$GIT_COMMITTER_EMAIL
+$TEST_COMMITTER_LOCALNAME
 Thu Apr 7 15:13:13 2005 -0700
 Thu, 7 Apr 2005 15:13:13 -0700
 1112911993
 commit $head1
-C O Mitter
-committer@example.com
+$GIT_COMMITTER_NAME
+$GIT_COMMITTER_EMAIL
+$TEST_COMMITTER_LOCALNAME
 Thu Apr 7 15:13:13 2005 -0700
 Thu, 7 Apr 2005 15:13:13 -0700
 1112911993
@@ -410,7 +414,7 @@
 	test_tick &&
 	C=$(GIT_AUTHOR_EMAIL= git commit-tree HEAD^{tree} </dev/null) &&
 	A=$(git show --pretty=format:%an,%ae,%ad%n -s $C) &&
-	verbose test "$A" = "A U Thor,,Thu Apr 7 15:14:13 2005 -0700"
+	verbose test "$A" = "$GIT_AUTHOR_NAME,,Thu Apr 7 15:14:13 2005 -0700"
 '
 
 test_expect_success 'del LF before empty (1)' '
@@ -495,7 +499,7 @@
 '
 
 test_expect_success 'reflog identity' '
-	echo "C O Mitter:committer@example.com" >expect &&
+	echo "$GIT_COMMITTER_NAME:$GIT_COMMITTER_EMAIL" >expect &&
 	git log -g -1 --format="%gn:%ge" >actual &&
 	test_cmp expect actual
 '
diff --git a/t/test-lib.sh b/t/test-lib.sh
index e06fa02..46c4440 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -404,9 +404,13 @@
 unset XDG_CACHE_HOME
 unset XDG_CONFIG_HOME
 unset GITPERLLIB
-GIT_AUTHOR_EMAIL=author@example.com
+TEST_AUTHOR_LOCALNAME=author
+TEST_AUTHOR_DOMAIN=example.com
+GIT_AUTHOR_EMAIL=${TEST_AUTHOR_LOCALNAME}@${TEST_AUTHOR_DOMAIN}
 GIT_AUTHOR_NAME='A U Thor'
-GIT_COMMITTER_EMAIL=committer@example.com
+TEST_COMMITTER_LOCALNAME=committer
+TEST_COMMITTER_DOMAIN=example.com
+GIT_COMMITTER_EMAIL=${TEST_COMMITTER_LOCALNAME}@${TEST_COMMITTER_DOMAIN}
 GIT_COMMITTER_NAME='C O Mitter'
 GIT_MERGE_VERBOSITY=5
 GIT_MERGE_AUTOEDIT=no