mirror of
https://github.com/git/git.git
synced 2025-12-12 20:36:24 +01:00
Merge branch 'jk/send-email-mailmap'
"git send-email" learned "--mailmap" option to allow rewriting the recipient addresses. * jk/send-email-mailmap: send-email: add mailmap support via sendemail.mailmap and --mailmap check-mailmap: add options for additional mailmap sources check-mailmap: accept "user@host" contacts
This commit is contained in:
@@ -15,10 +15,10 @@ SYNOPSIS
|
|||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
For each ``Name $$<user@host>$$'' or ``$$<user@host>$$'' from the command-line
|
For each ``Name $$<user@host>$$'', ``$$<user@host>$$'', or ``$$user@host$$''
|
||||||
or standard input (when using `--stdin`), look up the person's canonical name
|
from the command-line or standard input (when using `--stdin`), look up the
|
||||||
and email address (see "Mapping Authors" below). If found, print them;
|
person's canonical name and email address (see "Mapping Authors" below). If
|
||||||
otherwise print the input as-is.
|
found, print them; otherwise print the input as-is.
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
@@ -27,6 +27,16 @@ OPTIONS
|
|||||||
Read contacts, one per line, from the standard input after exhausting
|
Read contacts, one per line, from the standard input after exhausting
|
||||||
contacts provided on the command-line.
|
contacts provided on the command-line.
|
||||||
|
|
||||||
|
--mailmap-file=<file>::
|
||||||
|
In addition to any configured mailmap files, read the specified
|
||||||
|
mailmap file. Entries in this file take precedence over entries in
|
||||||
|
either the default mailmap file or any configured mailmap file.
|
||||||
|
|
||||||
|
--mailmap-blob=<blob>::
|
||||||
|
Like `--mailmap-file`, but consider the value as a reference to a
|
||||||
|
blob in the repository. If both `--mailmap-file` and
|
||||||
|
`--mailmap-blob` are specified, entries in `--mailmap-file` will
|
||||||
|
take precedence.
|
||||||
|
|
||||||
OUTPUT
|
OUTPUT
|
||||||
------
|
------
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "write-or-die.h"
|
#include "write-or-die.h"
|
||||||
|
|
||||||
static int use_stdin;
|
static int use_stdin;
|
||||||
|
static const char *mailmap_file, *mailmap_blob;
|
||||||
static const char * const check_mailmap_usage[] = {
|
static const char * const check_mailmap_usage[] = {
|
||||||
N_("git check-mailmap [<options>] <contact>..."),
|
N_("git check-mailmap [<options>] <contact>..."),
|
||||||
NULL
|
NULL
|
||||||
@@ -16,6 +17,8 @@ NULL
|
|||||||
|
|
||||||
static const struct option check_mailmap_options[] = {
|
static const struct option check_mailmap_options[] = {
|
||||||
OPT_BOOL(0, "stdin", &use_stdin, N_("also read contacts from stdin")),
|
OPT_BOOL(0, "stdin", &use_stdin, N_("also read contacts from stdin")),
|
||||||
|
OPT_FILENAME(0, "mailmap-file", &mailmap_file, N_("read additional mailmap entries from file")),
|
||||||
|
OPT_STRING(0, "mailmap-blob", &mailmap_blob, N_("blob"), N_("read additional mailmap entries from blob")),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,13 +28,17 @@ static void check_mailmap(struct string_list *mailmap, const char *contact)
|
|||||||
size_t namelen, maillen;
|
size_t namelen, maillen;
|
||||||
struct ident_split ident;
|
struct ident_split ident;
|
||||||
|
|
||||||
if (split_ident_line(&ident, contact, strlen(contact)))
|
if (!split_ident_line(&ident, contact, strlen(contact))) {
|
||||||
die(_("unable to parse contact: %s"), contact);
|
name = ident.name_begin;
|
||||||
|
namelen = ident.name_end - ident.name_begin;
|
||||||
name = ident.name_begin;
|
mail = ident.mail_begin;
|
||||||
namelen = ident.name_end - ident.name_begin;
|
maillen = ident.mail_end - ident.mail_begin;
|
||||||
mail = ident.mail_begin;
|
} else {
|
||||||
maillen = ident.mail_end - ident.mail_begin;
|
name = NULL;
|
||||||
|
namelen = 0;
|
||||||
|
mail = contact;
|
||||||
|
maillen = strlen(contact);
|
||||||
|
}
|
||||||
|
|
||||||
map_user(mailmap, &mail, &maillen, &name, &namelen);
|
map_user(mailmap, &mail, &maillen, &name, &namelen);
|
||||||
|
|
||||||
@@ -52,6 +59,10 @@ int cmd_check_mailmap(int argc, const char **argv, const char *prefix)
|
|||||||
die(_("no contacts specified"));
|
die(_("no contacts specified"));
|
||||||
|
|
||||||
read_mailmap(&mailmap);
|
read_mailmap(&mailmap);
|
||||||
|
if (mailmap_blob)
|
||||||
|
read_mailmap_blob(&mailmap, mailmap_blob);
|
||||||
|
if (mailmap_file)
|
||||||
|
read_mailmap_file(&mailmap, mailmap_file, 0);
|
||||||
|
|
||||||
for (i = 0; i < argc; ++i)
|
for (i = 0; i < argc; ++i)
|
||||||
check_mailmap(&mailmap, argv[i]);
|
check_mailmap(&mailmap, argv[i]);
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ git send-email --translate-aliases
|
|||||||
--compose-encoding <str> * Encoding to assume for introduction.
|
--compose-encoding <str> * Encoding to assume for introduction.
|
||||||
--8bit-encoding <str> * Encoding to assume 8bit mails if undeclared
|
--8bit-encoding <str> * Encoding to assume 8bit mails if undeclared
|
||||||
--transfer-encoding <str> * Transfer encoding to use (quoted-printable, 8bit, base64)
|
--transfer-encoding <str> * Transfer encoding to use (quoted-printable, 8bit, base64)
|
||||||
|
--[no-]mailmap * Use mailmap file to map all email addresses to canonical
|
||||||
|
real names and email addresses.
|
||||||
|
|
||||||
Sending:
|
Sending:
|
||||||
--envelope-sender <str> * Email envelope sender.
|
--envelope-sender <str> * Email envelope sender.
|
||||||
@@ -278,12 +280,14 @@ my (@suppress_cc);
|
|||||||
my ($auto_8bit_encoding);
|
my ($auto_8bit_encoding);
|
||||||
my ($compose_encoding);
|
my ($compose_encoding);
|
||||||
my ($sendmail_cmd);
|
my ($sendmail_cmd);
|
||||||
|
my ($mailmap_file, $mailmap_blob);
|
||||||
# Variables with corresponding config settings & hardcoded defaults
|
# Variables with corresponding config settings & hardcoded defaults
|
||||||
my ($debug_net_smtp) = 0; # Net::SMTP, see send_message()
|
my ($debug_net_smtp) = 0; # Net::SMTP, see send_message()
|
||||||
my $thread = 1;
|
my $thread = 1;
|
||||||
my $chain_reply_to = 0;
|
my $chain_reply_to = 0;
|
||||||
my $use_xmailer = 1;
|
my $use_xmailer = 1;
|
||||||
my $validate = 1;
|
my $validate = 1;
|
||||||
|
my $mailmap = 0;
|
||||||
my $target_xfer_encoding = 'auto';
|
my $target_xfer_encoding = 'auto';
|
||||||
my $forbid_sendmail_variables = 1;
|
my $forbid_sendmail_variables = 1;
|
||||||
|
|
||||||
@@ -300,6 +304,7 @@ my %config_bool_settings = (
|
|||||||
"annotate" => \$annotate,
|
"annotate" => \$annotate,
|
||||||
"xmailer" => \$use_xmailer,
|
"xmailer" => \$use_xmailer,
|
||||||
"forbidsendmailvariables" => \$forbid_sendmail_variables,
|
"forbidsendmailvariables" => \$forbid_sendmail_variables,
|
||||||
|
"mailmap" => \$mailmap,
|
||||||
);
|
);
|
||||||
|
|
||||||
my %config_settings = (
|
my %config_settings = (
|
||||||
@@ -333,6 +338,8 @@ my %config_settings = (
|
|||||||
my %config_path_settings = (
|
my %config_path_settings = (
|
||||||
"aliasesfile" => \@alias_files,
|
"aliasesfile" => \@alias_files,
|
||||||
"smtpsslcertpath" => \$smtp_ssl_cert_path,
|
"smtpsslcertpath" => \$smtp_ssl_cert_path,
|
||||||
|
"mailmap.file" => \$mailmap_file,
|
||||||
|
"mailmap.blob" => \$mailmap_blob,
|
||||||
);
|
);
|
||||||
|
|
||||||
# Handle Uncouth Termination
|
# Handle Uncouth Termination
|
||||||
@@ -533,6 +540,8 @@ my %options = (
|
|||||||
"thread!" => \$thread,
|
"thread!" => \$thread,
|
||||||
"validate!" => \$validate,
|
"validate!" => \$validate,
|
||||||
"transfer-encoding=s" => \$target_xfer_encoding,
|
"transfer-encoding=s" => \$target_xfer_encoding,
|
||||||
|
"mailmap!" => \$mailmap,
|
||||||
|
"use-mailmap!" => \$mailmap,
|
||||||
"format-patch!" => \$format_patch,
|
"format-patch!" => \$format_patch,
|
||||||
"8bit-encoding=s" => \$auto_8bit_encoding,
|
"8bit-encoding=s" => \$auto_8bit_encoding,
|
||||||
"compose-encoding=s" => \$compose_encoding,
|
"compose-encoding=s" => \$compose_encoding,
|
||||||
@@ -1104,6 +1113,16 @@ if ($compose && $compose > 0) {
|
|||||||
our ($message_id, %mail, $subject, $in_reply_to, $references, $message,
|
our ($message_id, %mail, $subject, $in_reply_to, $references, $message,
|
||||||
$needs_confirm, $message_num, $ask_default);
|
$needs_confirm, $message_num, $ask_default);
|
||||||
|
|
||||||
|
sub mailmap_address_list {
|
||||||
|
return @_ unless @_ and $mailmap;
|
||||||
|
my @options = ();
|
||||||
|
push(@options, "--mailmap-file=$mailmap_file") if $mailmap_file;
|
||||||
|
push(@options, "--mailmap-blob=$mailmap_blob") if $mailmap_blob;
|
||||||
|
my @addr_list = Git::command('check-mailmap', @options, @_);
|
||||||
|
s/^<(.*)>$/$1/ for @addr_list;
|
||||||
|
return @addr_list;
|
||||||
|
}
|
||||||
|
|
||||||
sub extract_valid_address {
|
sub extract_valid_address {
|
||||||
my $address = shift;
|
my $address = shift;
|
||||||
my $local_part_regexp = qr/[^<>"\s@]+/;
|
my $local_part_regexp = qr/[^<>"\s@]+/;
|
||||||
@@ -1313,6 +1332,7 @@ sub process_address_list {
|
|||||||
@addr_list = expand_aliases(@addr_list);
|
@addr_list = expand_aliases(@addr_list);
|
||||||
@addr_list = sanitize_address_list(@addr_list);
|
@addr_list = sanitize_address_list(@addr_list);
|
||||||
@addr_list = validate_address_list(@addr_list);
|
@addr_list = validate_address_list(@addr_list);
|
||||||
|
@addr_list = mailmap_address_list(@addr_list);
|
||||||
return @addr_list;
|
return @addr_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,11 +142,8 @@ static void read_mailmap_line(struct string_list *map, char *buffer)
|
|||||||
add_mapping(map, name1, email1, name2, email2);
|
add_mapping(map, name1, email1, name2, email2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flags for read_mailmap_file() */
|
int read_mailmap_file(struct string_list *map, const char *filename,
|
||||||
#define MAILMAP_NOFOLLOW (1<<0)
|
unsigned flags)
|
||||||
|
|
||||||
static int read_mailmap_file(struct string_list *map, const char *filename,
|
|
||||||
unsigned flags)
|
|
||||||
{
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
FILE *f;
|
FILE *f;
|
||||||
@@ -186,7 +183,7 @@ static void read_mailmap_string(struct string_list *map, char *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_mailmap_blob(struct string_list *map, const char *name)
|
int read_mailmap_blob(struct string_list *map, const char *name)
|
||||||
{
|
{
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|||||||
@@ -6,6 +6,13 @@ struct string_list;
|
|||||||
extern char *git_mailmap_file;
|
extern char *git_mailmap_file;
|
||||||
extern char *git_mailmap_blob;
|
extern char *git_mailmap_blob;
|
||||||
|
|
||||||
|
/* Flags for read_mailmap_file() */
|
||||||
|
#define MAILMAP_NOFOLLOW (1<<0)
|
||||||
|
|
||||||
|
int read_mailmap_file(struct string_list *map, const char *filename,
|
||||||
|
unsigned flags);
|
||||||
|
int read_mailmap_blob(struct string_list *map, const char *name);
|
||||||
|
|
||||||
int read_mailmap(struct string_list *map);
|
int read_mailmap(struct string_list *map);
|
||||||
void clear_mailmap(struct string_list *map);
|
void clear_mailmap(struct string_list *map);
|
||||||
|
|
||||||
|
|||||||
@@ -72,12 +72,46 @@ test_expect_success 'check-mailmap --stdin arguments: mapping' '
|
|||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'check-mailmap bogus contact' '
|
test_expect_success 'check-mailmap simple address: mapping' '
|
||||||
test_must_fail git check-mailmap bogus
|
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 bogus contact --stdin' '
|
test_expect_success 'check-mailmap --stdin simple address: mapping' '
|
||||||
test_must_fail git check-mailmap --stdin bogus </dev/null
|
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 &&
|
||||||
|
<bugs@company.xx>
|
||||||
|
EOF
|
||||||
|
git check-mailmap "bugs@company.xx" >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'check-mailmap --stdin simple address: no mapping' '
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
<bugs@company.xx>
|
||||||
|
EOF
|
||||||
|
cat >stdin <<-EOF &&
|
||||||
|
bugs@company.xx
|
||||||
|
EOF
|
||||||
|
git check-mailmap --stdin <stdin >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'No mailmap' '
|
test_expect_success 'No mailmap' '
|
||||||
|
|||||||
@@ -2485,6 +2485,128 @@ test_expect_success $PREREQ 'leading and trailing whitespaces are removed' '
|
|||||||
test_cmp expected-list actual-list
|
test_cmp expected-list actual-list
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success $PREREQ 'mailmap support with --to' '
|
||||||
|
clean_fake_sendmail &&
|
||||||
|
test_config mailmap.file "mailmap.test" &&
|
||||||
|
cat >mailmap.test <<-EOF &&
|
||||||
|
Some Body <someone@example.com> <someone@example.org>
|
||||||
|
EOF
|
||||||
|
git format-patch --stdout -1 >a.patch &&
|
||||||
|
git send-email \
|
||||||
|
--from="Example <nobody@example.com>" \
|
||||||
|
--smtp-server="$(pwd)/fake.sendmail" \
|
||||||
|
--to=someone@example.org \
|
||||||
|
--mailmap \
|
||||||
|
a.patch \
|
||||||
|
2>errors >out &&
|
||||||
|
grep "^!someone@example\.com!$" commandline1
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success $PREREQ 'sendemail.mailmap configuration' '
|
||||||
|
clean_fake_sendmail &&
|
||||||
|
test_config mailmap.file "mailmap.test" &&
|
||||||
|
test_config sendemail.mailmap "true" &&
|
||||||
|
cat >mailmap.test <<-EOF &&
|
||||||
|
Some Body <someone@example.com> <someone@example.org>
|
||||||
|
EOF
|
||||||
|
git format-patch --stdout -1 >a.patch &&
|
||||||
|
git send-email \
|
||||||
|
--from="Example <nobody@example.com>" \
|
||||||
|
--smtp-server="$(pwd)/fake.sendmail" \
|
||||||
|
--to=someone@example.org \
|
||||||
|
a.patch \
|
||||||
|
2>errors >out &&
|
||||||
|
grep "^!someone@example\.com!$" commandline1
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success $PREREQ 'sendemail.mailmap.file configuration' '
|
||||||
|
clean_fake_sendmail &&
|
||||||
|
test_config sendemail.mailmap.file "mailmap.test" &&
|
||||||
|
test_config sendemail.mailmap "true" &&
|
||||||
|
cat >mailmap.test <<-EOF &&
|
||||||
|
Some Body <someone@example.com> <someone@example.org>
|
||||||
|
EOF
|
||||||
|
git format-patch --stdout -1 >a.patch &&
|
||||||
|
git send-email \
|
||||||
|
--from="Example <nobody@example.com>" \
|
||||||
|
--smtp-server="$(pwd)/fake.sendmail" \
|
||||||
|
--to=someone@example.org \
|
||||||
|
a.patch \
|
||||||
|
2>errors >out &&
|
||||||
|
grep "^!someone@example\.com!$" commandline1
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success $PREREQ 'sendemail.mailmap identity overrides configuration' '
|
||||||
|
clean_fake_sendmail &&
|
||||||
|
test_config sendemail.cloud.mailmap.file "mailmap.test" &&
|
||||||
|
test_config sendemail.mailmap "false" &&
|
||||||
|
test_config sendemail.cloud.mailmap "true" &&
|
||||||
|
cat >mailmap.test <<-EOF &&
|
||||||
|
Some Body <someone@example.com> <someone@example.org>
|
||||||
|
EOF
|
||||||
|
git format-patch --stdout -1 >a.patch &&
|
||||||
|
git send-email \
|
||||||
|
--from="Example <nobody@example.com>" \
|
||||||
|
--smtp-server="$(pwd)/fake.sendmail" \
|
||||||
|
--identity=cloud \
|
||||||
|
--to=someone@example.org \
|
||||||
|
a.patch \
|
||||||
|
2>errors >out &&
|
||||||
|
grep "^!someone@example\.com!$" commandline1
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success $PREREQ '--no-mailmap overrides configuration' '
|
||||||
|
clean_fake_sendmail &&
|
||||||
|
test_config sendemail.cloud.mailmap.file "mailmap.test" &&
|
||||||
|
test_config sendemail.mailmap "false" &&
|
||||||
|
test_config sendemail.cloud.mailmap "true" &&
|
||||||
|
cat >mailmap.test <<-EOF &&
|
||||||
|
Some Body <someone@example.com> <someone@example.org>
|
||||||
|
EOF
|
||||||
|
git format-patch --stdout -1 >a.patch &&
|
||||||
|
git send-email \
|
||||||
|
--from="Example <nobody@example.com>" \
|
||||||
|
--smtp-server="$(pwd)/fake.sendmail" \
|
||||||
|
--identity=cloud \
|
||||||
|
--to=someone@example.org \
|
||||||
|
--no-mailmap \
|
||||||
|
a.patch \
|
||||||
|
2>errors >out &&
|
||||||
|
grep "^!someone@example\.org!$" commandline1
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success $PREREQ 'mailmap support in To header' '
|
||||||
|
clean_fake_sendmail &&
|
||||||
|
test_config mailmap.file "mailmap.test" &&
|
||||||
|
cat >mailmap.test <<-EOF &&
|
||||||
|
<someone@example.com> <someone@example.org>
|
||||||
|
EOF
|
||||||
|
git format-patch --stdout -1 --to=someone@example.org >a.patch &&
|
||||||
|
git send-email \
|
||||||
|
--from="Example <nobody@example.com>" \
|
||||||
|
--smtp-server="$(pwd)/fake.sendmail" \
|
||||||
|
--mailmap \
|
||||||
|
a.patch \
|
||||||
|
2>errors >out &&
|
||||||
|
grep "^!someone@example\.com!$" commandline1
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success $PREREQ 'mailmap support in Cc header' '
|
||||||
|
clean_fake_sendmail &&
|
||||||
|
test_config mailmap.file "mailmap.test" &&
|
||||||
|
cat >mailmap.test <<-EOF &&
|
||||||
|
<someone@example.com> <someone@example.org>
|
||||||
|
EOF
|
||||||
|
git format-patch --stdout -1 --cc=someone@example.org >a.patch &&
|
||||||
|
git send-email \
|
||||||
|
--from="Example <nobody@example.com>" \
|
||||||
|
--smtp-server="$(pwd)/fake.sendmail" \
|
||||||
|
--mailmap \
|
||||||
|
a.patch \
|
||||||
|
2>errors >out &&
|
||||||
|
grep "^!someone@example\.com!$" commandline1
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success $PREREQ 'test using command name with --sendmail-cmd' '
|
test_expect_success $PREREQ 'test using command name with --sendmail-cmd' '
|
||||||
clean_fake_sendmail &&
|
clean_fake_sendmail &&
|
||||||
PATH="$PWD:$PATH" \
|
PATH="$PWD:$PATH" \
|
||||||
|
|||||||
Reference in New Issue
Block a user