Skip to content

Commit 3ff1504

Browse files
avargitster
authored andcommitted
send-email: fix regression in sendemail.identity parsing
Fix a regression in my recent 3494dfd ("send-email: do defaults -> config -> getopt in that order", 2019-05-09). I missed that the $identity variable needs to be extracted from the command-line before we do the config reading, as it determines which config variable we should read first. See [1] for the report. The sendemail.identity feature was added back in 34cc60c ("send-email: Add support for SSL and SMTP-AUTH", 2007-09-03), there were no tests to assert that it worked properly. So let's fix both the regression, and add some tests to assert that this is being parsed properly. While I'm at it I'm adding a --no-identity option to go with --[to|cc|bcc] variable, since the semantics are similar. It's like to/cc/bcc except that unlike those we don't support multiple identities, but we could now easily add it support for it if anyone cares. In just fixing the --identity command-line parsing bug I discovered that a narrow fix to that wouldn't do. In read_config() we had a state machine that would only set config values if they weren't set already, and thus by proxy we wouldn't e.g. set "to" based on sendemail.to if we'd seen sendemail.gmail.to before, with --identity=gmail. I'd modified some of the relevant code in 3494dfd, but just reverting to that wouldn't do, since it would bring back the regression fixed in that commit. Refactor read_config() do what we actually mean here. We don't want to set a given sendemail.VAR if a sendemail.$identity.VAR previously set it. The old code was conflating this desire with the hardcoded defaults for these variables, and as discussed in 3494dfd that was never going to work. Instead pass along the state of whether an identity config set something before, as distinguished from the state of the default just being false, or the default being a non-bool or true (e.g. --transferencoding). I'm still not happy with the test coverage here, e.g. there's nothing testing sendemail.smtpEncryption, but I only have so much time to fix this code. 1. https://public-inbox.org/git/[email protected]/ Signed-off-by: Ævar Arnfjörð Bjarmason <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 564eba4 commit 3ff1504

File tree

3 files changed

+108
-19
lines changed

3 files changed

+108
-19
lines changed

Documentation/git-send-email.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ Automating
277277
Clears any list of "To:", "Cc:", "Bcc:" addresses previously
278278
set via config.
279279

280+
--no-identity::
281+
Clears the previously read value of `sendemail.identity` set
282+
via config, if any.
283+
280284
--to-cmd=<command>::
281285
Specify a command to execute once per patch file which
282286
should generate patch file specific "To:" entries.

git-send-email.perl

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ sub format_2822_time {
174174
$author,$sender,$smtp_authpass,$annotate,$compose,$time);
175175
# Things we either get from config, *or* are overridden on the
176176
# command-line.
177-
my ($no_cc, $no_to, $no_bcc);
177+
my ($no_cc, $no_to, $no_bcc, $no_identity);
178178
my (@config_to, @getopt_to);
179179
my (@config_cc, @getopt_cc);
180180
my (@config_bcc, @getopt_bcc);
@@ -317,44 +317,53 @@ sub signal_handler {
317317

318318
# Read our sendemail.* config
319319
sub read_config {
320-
my ($prefix) = @_;
320+
my ($configured, $prefix) = @_;
321321

322322
foreach my $setting (keys %config_bool_settings) {
323323
my $target = $config_bool_settings{$setting};
324324
my $v = Git::config_bool(@repo, "$prefix.$setting");
325-
$$target = $v if defined $v;
325+
next unless defined $v;
326+
next if $configured->{$setting}++;
327+
$$target = $v;
326328
}
327329

328330
foreach my $setting (keys %config_path_settings) {
329331
my $target = $config_path_settings{$setting};
330332
if (ref($target) eq "ARRAY") {
331-
unless (@$target) {
332-
my @values = Git::config_path(@repo, "$prefix.$setting");
333-
@$target = @values if (@values && defined $values[0]);
334-
}
333+
my @values = Git::config_path(@repo, "$prefix.$setting");
334+
next unless @values;
335+
next if $configured->{$setting}++;
336+
@$target = @values;
335337
}
336338
else {
337339
my $v = Git::config_path(@repo, "$prefix.$setting");
338-
$$target = $v if defined $v;
340+
next unless defined $v;
341+
next if $configured->{$setting}++;
342+
$$target = $v;
339343
}
340344
}
341345

342346
foreach my $setting (keys %config_settings) {
343347
my $target = $config_settings{$setting};
344348
if (ref($target) eq "ARRAY") {
345-
unless (@$target) {
346-
my @values = Git::config(@repo, "$prefix.$setting");
347-
@$target = @values if (@values && defined $values[0]);
348-
}
349+
my @values = Git::config(@repo, "$prefix.$setting");
350+
next unless @values;
351+
next if $configured->{$setting}++;
352+
@$target = @values;
349353
}
350354
else {
351355
my $v = Git::config(@repo, "$prefix.$setting");
352-
$$target = $v if defined $v;
356+
next unless defined $v;
357+
next if $configured->{$setting}++;
358+
$$target = $v;
353359
}
354360
}
355361

356362
if (!defined $smtp_encryption) {
357-
my $enc = Git::config(@repo, "$prefix.smtpencryption");
363+
my $setting = "$prefix.smtpencryption";
364+
my $enc = Git::config(@repo, $setting);
365+
return unless defined $enc;
366+
return if $configured->{$setting}++;
358367
if (defined $enc) {
359368
$smtp_encryption = $enc;
360369
} elsif (Git::config_bool(@repo, "$prefix.smtpssl")) {
@@ -363,16 +372,29 @@ sub read_config {
363372
}
364373
}
365374

375+
# sendemail.identity yields to --identity. We must parse this
376+
# special-case first before the rest of the config is read.
366377
$identity = Git::config(@repo, "sendemail.identity");
367-
read_config("sendemail.$identity") if defined $identity;
368-
read_config("sendemail");
378+
my $rc = GetOptions(
379+
"identity=s" => \$identity,
380+
"no-identity" => \$no_identity,
381+
);
382+
usage() unless $rc;
383+
undef $identity if $no_identity;
384+
385+
# Now we know enough to read the config
386+
{
387+
my %configured;
388+
read_config(\%configured, "sendemail.$identity") if defined $identity;
389+
read_config(\%configured, "sendemail");
390+
}
369391

370392
# Begin by accumulating all the variables (defined above), that we will end up
371393
# needing, first, from the command line:
372394

373395
my $help;
374-
my $rc = GetOptions("h" => \$help,
375-
"dump-aliases" => \$dump_aliases);
396+
$rc = GetOptions("h" => \$help,
397+
"dump-aliases" => \$dump_aliases);
376398
usage() unless $rc;
377399
die __("--dump-aliases incompatible with other options\n")
378400
if !$help and $dump_aliases and @ARGV;
@@ -401,7 +423,6 @@ sub read_config {
401423
"smtp-debug:i" => \$debug_net_smtp,
402424
"smtp-domain:s" => \$smtp_domain,
403425
"smtp-auth=s" => \$smtp_auth,
404-
"identity=s" => \$identity,
405426
"annotate!" => \$annotate,
406427
"no-annotate" => sub {$annotate = 0},
407428
"compose" => \$compose,

t/t9001-send-email.sh

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,61 @@ test_expect_success $PREREQ 'sendemail.to works' '
12001200
grep "To: Somebody <[email protected]>" stdout
12011201
'
12021202

1203+
test_expect_success $PREREQ 'setup sendemail.identity' '
1204+
git config --replace-all sendemail.to "[email protected]" &&
1205+
git config --replace-all sendemail.isp.to "[email protected]" &&
1206+
git config --replace-all sendemail.cloud.to "[email protected]"
1207+
'
1208+
1209+
test_expect_success $PREREQ 'sendemail.identity: reads the correct identity config' '
1210+
git -c sendemail.identity=cloud send-email \
1211+
--dry-run \
1212+
--from="[email protected]" \
1213+
$patches >stdout &&
1214+
grep "To: [email protected]" stdout
1215+
'
1216+
1217+
test_expect_success $PREREQ 'sendemail.identity: identity overrides sendemail.identity' '
1218+
git -c sendemail.identity=cloud send-email \
1219+
--identity=isp \
1220+
--dry-run \
1221+
--from="[email protected]" \
1222+
$patches >stdout &&
1223+
grep "To: [email protected]" stdout
1224+
'
1225+
1226+
test_expect_success $PREREQ 'sendemail.identity: --no-identity clears previous identity' '
1227+
git -c sendemail.identity=cloud send-email \
1228+
--no-identity \
1229+
--dry-run \
1230+
--from="[email protected]" \
1231+
$patches >stdout &&
1232+
grep "To: [email protected]" stdout
1233+
'
1234+
1235+
test_expect_success $PREREQ 'sendemail.identity: bool identity variable existance overrides' '
1236+
git -c sendemail.identity=cloud \
1237+
-c sendemail.xmailer=true \
1238+
-c sendemail.cloud.xmailer=false \
1239+
send-email \
1240+
--dry-run \
1241+
--from="[email protected]" \
1242+
$patches >stdout &&
1243+
grep "To: [email protected]" stdout &&
1244+
! grep "X-Mailer" stdout
1245+
'
1246+
1247+
test_expect_success $PREREQ 'sendemail.identity: bool variable fallback' '
1248+
git -c sendemail.identity=cloud \
1249+
-c sendemail.xmailer=false \
1250+
send-email \
1251+
--dry-run \
1252+
--from="[email protected]" \
1253+
$patches >stdout &&
1254+
grep "To: [email protected]" stdout &&
1255+
! grep "X-Mailer" stdout
1256+
'
1257+
12031258
test_expect_success $PREREQ '--no-to overrides sendemail.to' '
12041259
git send-email \
12051260
--dry-run \
@@ -1757,6 +1812,15 @@ test_expect_success '--dump-aliases must be used alone' '
17571812
test_must_fail git send-email --dump-aliases [email protected] -1 refs/heads/accounting
17581813
'
17591814

1815+
test_expect_success $PREREQ 'aliases and sendemail.identity' '
1816+
test_must_fail git \
1817+
-c sendemail.identity=cloud \
1818+
-c sendemail.aliasesfile=default-aliases \
1819+
-c sendemail.cloud.aliasesfile=cloud-aliases \
1820+
send-email -1 2>stderr &&
1821+
test_i18ngrep "cloud-aliases" stderr
1822+
'
1823+
17601824
test_sendmail_aliases () {
17611825
msg="$1" && shift &&
17621826
expect="$@" &&

0 commit comments

Comments
 (0)