mirror of
https://github.com/git/git.git
synced 2024-05-04 10:06:12 +02:00
Merge branch 'ab/send-email-optim' into next
"git send-email" optimization. * ab/send-email-optim: perl: nano-optimize by replacing Cwd::cwd() with Cwd::getcwd() send-email: move trivial config handling to Perl perl: lazily load some common Git.pm setup code send-email: lazily load modules for a big speedup send-email: get rid of indirect object syntax send-email: use function syntax instead of barewords send-email: lazily shell out to "git var" send-email: lazily load config for a big speedup send-email: copy "config_regxp" into git-send-email.perl send-email: refactor sendemail.smtpencryption config parsing send-email: remove non-working support for "sendemail.smtpssl" send-email tests: test for boolean variables without a value send-email tests: support GIT_TEST_PERL_FATAL_WARNINGS=true
This commit is contained in:
commit
35ac315894
|
@ -8,9 +8,6 @@ sendemail.smtpEncryption::
|
||||||
See linkgit:git-send-email[1] for description. Note that this
|
See linkgit:git-send-email[1] for description. Note that this
|
||||||
setting is not subject to the 'identity' mechanism.
|
setting is not subject to the 'identity' mechanism.
|
||||||
|
|
||||||
sendemail.smtpssl (deprecated)::
|
|
||||||
Deprecated alias for 'sendemail.smtpEncryption = ssl'.
|
|
||||||
|
|
||||||
sendemail.smtpsslcertpath::
|
sendemail.smtpsslcertpath::
|
||||||
Path to ca-certificates (either a directory or a single file).
|
Path to ca-certificates (either a directory or a single file).
|
||||||
Set it to an empty string to disable certificate verification.
|
Set it to an empty string to disable certificate verification.
|
||||||
|
|
|
@ -18,21 +18,11 @@
|
||||||
|
|
||||||
use 5.008;
|
use 5.008;
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
|
||||||
use POSIX qw/strftime/;
|
|
||||||
use Term::ReadLine;
|
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
use Text::ParseWords;
|
|
||||||
use Term::ANSIColor;
|
|
||||||
use File::Temp qw/ tempdir tempfile /;
|
|
||||||
use File::Spec::Functions qw(catdir catfile);
|
|
||||||
use Git::LoadCPAN::Error qw(:try);
|
use Git::LoadCPAN::Error qw(:try);
|
||||||
use Cwd qw(abs_path cwd);
|
|
||||||
use Git;
|
use Git;
|
||||||
use Git::I18N;
|
use Git::I18N;
|
||||||
use Net::Domain ();
|
|
||||||
use Net::SMTP ();
|
|
||||||
use Git::LoadCPAN::Mail::Address;
|
|
||||||
|
|
||||||
Getopt::Long::Configure qw/ pass_through /;
|
Getopt::Long::Configure qw/ pass_through /;
|
||||||
|
|
||||||
|
@ -167,7 +157,6 @@ sub format_2822_time {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
my $have_email_valid = eval { require Email::Valid; 1 };
|
|
||||||
my $smtp;
|
my $smtp;
|
||||||
my $auth;
|
my $auth;
|
||||||
my $num_sent = 0;
|
my $num_sent = 0;
|
||||||
|
@ -193,14 +182,6 @@ sub format_2822_time {
|
||||||
|
|
||||||
my $repo = eval { Git->repository() };
|
my $repo = eval { Git->repository() };
|
||||||
my @repo = $repo ? ($repo) : ();
|
my @repo = $repo ? ($repo) : ();
|
||||||
my $term = eval {
|
|
||||||
$ENV{"GIT_SEND_EMAIL_NOTTY"}
|
|
||||||
? new Term::ReadLine 'git-send-email', \*STDIN, \*STDOUT
|
|
||||||
: new Term::ReadLine 'git-send-email';
|
|
||||||
};
|
|
||||||
if ($@) {
|
|
||||||
$term = new FakeTerm "$@: going non-interactive";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Behavior modification variables
|
# Behavior modification variables
|
||||||
my ($quiet, $dry_run) = (0, 0);
|
my ($quiet, $dry_run) = (0, 0);
|
||||||
|
@ -289,6 +270,7 @@ sub do_edit {
|
||||||
);
|
);
|
||||||
|
|
||||||
my %config_settings = (
|
my %config_settings = (
|
||||||
|
"smtpencryption" => \$smtp_encryption,
|
||||||
"smtpserver" => \$smtp_server,
|
"smtpserver" => \$smtp_server,
|
||||||
"smtpserverport" => \$smtp_server_port,
|
"smtpserverport" => \$smtp_server_port,
|
||||||
"smtpserveroption" => \@smtp_server_options,
|
"smtpserveroption" => \@smtp_server_options,
|
||||||
|
@ -321,9 +303,9 @@ sub do_edit {
|
||||||
|
|
||||||
# Handle Uncouth Termination
|
# Handle Uncouth Termination
|
||||||
sub signal_handler {
|
sub signal_handler {
|
||||||
|
|
||||||
# Make text normal
|
# Make text normal
|
||||||
print color("reset"), "\n";
|
require Term::ANSIColor;
|
||||||
|
print Term::ANSIColor::color("reset"), "\n";
|
||||||
|
|
||||||
# SMTP password masked
|
# SMTP password masked
|
||||||
system "stty echo";
|
system "stty echo";
|
||||||
|
@ -349,11 +331,17 @@ sub signal_handler {
|
||||||
|
|
||||||
# Read our sendemail.* config
|
# Read our sendemail.* config
|
||||||
sub read_config {
|
sub read_config {
|
||||||
my ($configured, $prefix) = @_;
|
my ($known_keys, $configured, $prefix) = @_;
|
||||||
|
|
||||||
foreach my $setting (keys %config_bool_settings) {
|
foreach my $setting (keys %config_bool_settings) {
|
||||||
my $target = $config_bool_settings{$setting};
|
my $target = $config_bool_settings{$setting};
|
||||||
my $v = Git::config_bool(@repo, "$prefix.$setting");
|
my $key = "$prefix.$setting";
|
||||||
|
next unless exists $known_keys->{$key};
|
||||||
|
my $v = (@{$known_keys->{$key}} == 1 &&
|
||||||
|
(defined $known_keys->{$key}->[0] &&
|
||||||
|
$known_keys->{$key}->[0] =~ /^(?:true|false)$/s))
|
||||||
|
? $known_keys->{$key}->[0] eq 'true'
|
||||||
|
: Git::config_bool(@repo, $key);
|
||||||
next unless defined $v;
|
next unless defined $v;
|
||||||
next if $configured->{$setting}++;
|
next if $configured->{$setting}++;
|
||||||
$$target = $v;
|
$$target = $v;
|
||||||
|
@ -361,8 +349,10 @@ sub read_config {
|
||||||
|
|
||||||
foreach my $setting (keys %config_path_settings) {
|
foreach my $setting (keys %config_path_settings) {
|
||||||
my $target = $config_path_settings{$setting};
|
my $target = $config_path_settings{$setting};
|
||||||
|
my $key = "$prefix.$setting";
|
||||||
|
next unless exists $known_keys->{$key};
|
||||||
if (ref($target) eq "ARRAY") {
|
if (ref($target) eq "ARRAY") {
|
||||||
my @values = Git::config_path(@repo, "$prefix.$setting");
|
my @values = Git::config_path(@repo, $key);
|
||||||
next unless @values;
|
next unless @values;
|
||||||
next if $configured->{$setting}++;
|
next if $configured->{$setting}++;
|
||||||
@$target = @values;
|
@$target = @values;
|
||||||
|
@ -377,36 +367,64 @@ sub read_config {
|
||||||
|
|
||||||
foreach my $setting (keys %config_settings) {
|
foreach my $setting (keys %config_settings) {
|
||||||
my $target = $config_settings{$setting};
|
my $target = $config_settings{$setting};
|
||||||
|
my $key = "$prefix.$setting";
|
||||||
|
next unless exists $known_keys->{$key};
|
||||||
if (ref($target) eq "ARRAY") {
|
if (ref($target) eq "ARRAY") {
|
||||||
my @values = Git::config(@repo, "$prefix.$setting");
|
my @values = @{$known_keys->{$key}};
|
||||||
next unless @values;
|
@values = grep { defined } @values;
|
||||||
next if $configured->{$setting}++;
|
next if $configured->{$setting}++;
|
||||||
@$target = @values;
|
@$target = @values;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
my $v = Git::config(@repo, "$prefix.$setting");
|
my $v = $known_keys->{$key}->[0];
|
||||||
next unless defined $v;
|
next unless defined $v;
|
||||||
next if $configured->{$setting}++;
|
next if $configured->{$setting}++;
|
||||||
$$target = $v;
|
$$target = $v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!defined $smtp_encryption) {
|
sub config_regexp {
|
||||||
my $setting = "$prefix.smtpencryption";
|
my ($regex) = @_;
|
||||||
my $enc = Git::config(@repo, $setting);
|
my @ret;
|
||||||
return unless defined $enc;
|
eval {
|
||||||
return if $configured->{$setting}++;
|
my $ret = Git::command(
|
||||||
if (defined $enc) {
|
'config',
|
||||||
$smtp_encryption = $enc;
|
'--null',
|
||||||
} elsif (Git::config_bool(@repo, "$prefix.smtpssl")) {
|
'--get-regexp',
|
||||||
$smtp_encryption = 'ssl';
|
$regex,
|
||||||
}
|
);
|
||||||
|
@ret = map {
|
||||||
|
# We must always return ($k, $v) here, since
|
||||||
|
# empty config values will be just "key\0",
|
||||||
|
# not "key\nvalue\0".
|
||||||
|
my ($k, $v) = split /\n/, $_, 2;
|
||||||
|
($k, $v);
|
||||||
|
} split /\0/, $ret;
|
||||||
|
1;
|
||||||
|
} or do {
|
||||||
|
# If we have no keys we're OK, otherwise re-throw
|
||||||
|
die $@ if $@->value != 1;
|
||||||
|
};
|
||||||
|
return @ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Save ourselves a lot of work of shelling out to 'git config' (it
|
||||||
|
# parses 'bool' etc.) by only doing so for config keys that exist.
|
||||||
|
my %known_config_keys;
|
||||||
|
{
|
||||||
|
my @kv = config_regexp("^sende?mail[.]");
|
||||||
|
while (my ($k, $v) = splice @kv, 0, 2) {
|
||||||
|
push @{$known_config_keys{$k}} => $v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# sendemail.identity yields to --identity. We must parse this
|
# sendemail.identity yields to --identity. We must parse this
|
||||||
# special-case first before the rest of the config is read.
|
# special-case first before the rest of the config is read.
|
||||||
$identity = Git::config(@repo, "sendemail.identity");
|
{
|
||||||
|
my $key = "sendemail.identity";
|
||||||
|
$identity = Git::config(@repo, $key) if exists $known_config_keys{$key};
|
||||||
|
}
|
||||||
my $rc = GetOptions(
|
my $rc = GetOptions(
|
||||||
"identity=s" => \$identity,
|
"identity=s" => \$identity,
|
||||||
"no-identity" => \$no_identity,
|
"no-identity" => \$no_identity,
|
||||||
|
@ -417,8 +435,8 @@ sub read_config {
|
||||||
# Now we know enough to read the config
|
# Now we know enough to read the config
|
||||||
{
|
{
|
||||||
my %configured;
|
my %configured;
|
||||||
read_config(\%configured, "sendemail.$identity") if defined $identity;
|
read_config(\%known_config_keys, \%configured, "sendemail.$identity") if defined $identity;
|
||||||
read_config(\%configured, "sendemail");
|
read_config(\%known_config_keys, \%configured, "sendemail");
|
||||||
}
|
}
|
||||||
|
|
||||||
# Begin by accumulating all the variables (defined above), that we will end up
|
# Begin by accumulating all the variables (defined above), that we will end up
|
||||||
|
@ -503,7 +521,7 @@ sub read_config {
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($forbid_sendmail_variables && (scalar Git::config_regexp("^sendmail[.]")) != 0) {
|
if ($forbid_sendmail_variables && grep { /^sendmail/s } keys %known_config_keys) {
|
||||||
die __("fatal: found configuration options for 'sendmail'\n" .
|
die __("fatal: found configuration options for 'sendmail'\n" .
|
||||||
"git-send-email is configured with the sendemail.* options - note the 'e'.\n" .
|
"git-send-email is configured with the sendemail.* options - note the 'e'.\n" .
|
||||||
"Set sendemail.forbidSendmailVariables to false to disable this check.\n");
|
"Set sendemail.forbidSendmailVariables to false to disable this check.\n");
|
||||||
|
@ -568,15 +586,27 @@ sub read_config {
|
||||||
}
|
}
|
||||||
|
|
||||||
my ($repoauthor, $repocommitter);
|
my ($repoauthor, $repocommitter);
|
||||||
($repoauthor) = Git::ident_person(@repo, 'author');
|
{
|
||||||
($repocommitter) = Git::ident_person(@repo, 'committer');
|
my %cache;
|
||||||
|
my ($author, $committer);
|
||||||
|
my $common = sub {
|
||||||
|
my ($what) = @_;
|
||||||
|
return $cache{$what} if exists $cache{$what};
|
||||||
|
($cache{$what}) = Git::ident_person(@repo, $what);
|
||||||
|
return $cache{$what};
|
||||||
|
};
|
||||||
|
$repoauthor = sub { $common->('author') };
|
||||||
|
$repocommitter = sub { $common->('committer') };
|
||||||
|
}
|
||||||
|
|
||||||
sub parse_address_line {
|
sub parse_address_line {
|
||||||
|
require Git::LoadCPAN::Mail::Address;
|
||||||
return map { $_->format } Mail::Address->parse($_[0]);
|
return map { $_->format } Mail::Address->parse($_[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub split_addrs {
|
sub split_addrs {
|
||||||
return quotewords('\s*,\s*', 1, @_);
|
require Text::ParseWords;
|
||||||
|
return Text::ParseWords::quotewords('\s*,\s*', 1, @_);
|
||||||
}
|
}
|
||||||
|
|
||||||
my %aliases;
|
my %aliases;
|
||||||
|
@ -625,10 +655,11 @@ sub parse_sendmail_aliases {
|
||||||
s/\\"/"/g foreach @addr;
|
s/\\"/"/g foreach @addr;
|
||||||
$aliases{$alias} = \@addr
|
$aliases{$alias} = \@addr
|
||||||
}}},
|
}}},
|
||||||
mailrc => sub { my $fh = shift; while (<$fh>) {
|
mailrc => sub { my $fh = shift; while (<$fh>) {
|
||||||
if (/^alias\s+(\S+)\s+(.*?)\s*$/) {
|
if (/^alias\s+(\S+)\s+(.*?)\s*$/) {
|
||||||
|
require Text::ParseWords;
|
||||||
# spaces delimit multiple addresses
|
# spaces delimit multiple addresses
|
||||||
$aliases{$1} = [ quotewords('\s+', 0, $2) ];
|
$aliases{$1} = [ Text::ParseWords::quotewords('\s+', 0, $2) ];
|
||||||
}}},
|
}}},
|
||||||
pine => sub { my $fh = shift; my $f='\t[^\t]*';
|
pine => sub { my $fh = shift; my $f='\t[^\t]*';
|
||||||
for (my $x = ''; defined($x); $x = $_) {
|
for (my $x = ''; defined($x); $x = $_) {
|
||||||
|
@ -676,7 +707,7 @@ sub is_format_patch_arg {
|
||||||
if (defined($format_patch)) {
|
if (defined($format_patch)) {
|
||||||
return $format_patch;
|
return $format_patch;
|
||||||
}
|
}
|
||||||
die sprintf(__ <<EOF, $f, $f);
|
die sprintf(__(<<EOF), $f, $f);
|
||||||
File '%s' exists but it could also be the range of commits
|
File '%s' exists but it could also be the range of commits
|
||||||
to produce patches for. Please disambiguate by...
|
to produce patches for. Please disambiguate by...
|
||||||
|
|
||||||
|
@ -700,7 +731,8 @@ sub is_format_patch_arg {
|
||||||
opendir my $dh, $f
|
opendir my $dh, $f
|
||||||
or die sprintf(__("Failed to opendir %s: %s"), $f, $!);
|
or die sprintf(__("Failed to opendir %s: %s"), $f, $!);
|
||||||
|
|
||||||
push @files, grep { -f $_ } map { catfile($f, $_) }
|
require File::Spec;
|
||||||
|
push @files, grep { -f $_ } map { File::Spec->catfile($f, $_) }
|
||||||
sort readdir $dh;
|
sort readdir $dh;
|
||||||
closedir $dh;
|
closedir $dh;
|
||||||
} elsif ((-f $f or -p $f) and !is_format_patch_arg($f)) {
|
} elsif ((-f $f or -p $f) and !is_format_patch_arg($f)) {
|
||||||
|
@ -713,7 +745,8 @@ sub is_format_patch_arg {
|
||||||
if (@rev_list_opts) {
|
if (@rev_list_opts) {
|
||||||
die __("Cannot run git format-patch from outside a repository\n")
|
die __("Cannot run git format-patch from outside a repository\n")
|
||||||
unless $repo;
|
unless $repo;
|
||||||
push @files, $repo->command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts);
|
require File::Temp;
|
||||||
|
push @files, $repo->command('format-patch', '-o', File::Temp::tempdir(CLEANUP => 1), @rev_list_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@files = handle_backup_files(@files);
|
@files = handle_backup_files(@files);
|
||||||
|
@ -750,19 +783,20 @@ sub get_patch_subject {
|
||||||
if ($compose) {
|
if ($compose) {
|
||||||
# Note that this does not need to be secure, but we will make a small
|
# Note that this does not need to be secure, but we will make a small
|
||||||
# effort to have it be unique
|
# effort to have it be unique
|
||||||
|
require File::Temp;
|
||||||
$compose_filename = ($repo ?
|
$compose_filename = ($repo ?
|
||||||
tempfile(".gitsendemail.msg.XXXXXX", DIR => $repo->repo_path()) :
|
File::Temp::tempfile(".gitsendemail.msg.XXXXXX", DIR => $repo->repo_path()) :
|
||||||
tempfile(".gitsendemail.msg.XXXXXX", DIR => "."))[1];
|
File::Temp::tempfile(".gitsendemail.msg.XXXXXX", DIR => "."))[1];
|
||||||
open my $c, ">", $compose_filename
|
open my $c, ">", $compose_filename
|
||||||
or die sprintf(__("Failed to open for writing %s: %s"), $compose_filename, $!);
|
or die sprintf(__("Failed to open for writing %s: %s"), $compose_filename, $!);
|
||||||
|
|
||||||
|
|
||||||
my $tpl_sender = $sender || $repoauthor || $repocommitter || '';
|
my $tpl_sender = $sender || $repoauthor->() || $repocommitter->() || '';
|
||||||
my $tpl_subject = $initial_subject || '';
|
my $tpl_subject = $initial_subject || '';
|
||||||
my $tpl_in_reply_to = $initial_in_reply_to || '';
|
my $tpl_in_reply_to = $initial_in_reply_to || '';
|
||||||
my $tpl_reply_to = $reply_to || '';
|
my $tpl_reply_to = $reply_to || '';
|
||||||
|
|
||||||
print $c <<EOT1, Git::prefix_lines("GIT: ", __ <<EOT2), <<EOT3;
|
print $c <<EOT1, Git::prefix_lines("GIT: ", __(<<EOT2)), <<EOT3;
|
||||||
From $tpl_sender # This line is ignored.
|
From $tpl_sender # This line is ignored.
|
||||||
EOT1
|
EOT1
|
||||||
Lines beginning in "GIT:" will be removed.
|
Lines beginning in "GIT:" will be removed.
|
||||||
|
@ -859,6 +893,19 @@ sub get_patch_subject {
|
||||||
do_edit(@files);
|
do_edit(@files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub term {
|
||||||
|
my $term = eval {
|
||||||
|
require Term::ReadLine;
|
||||||
|
$ENV{"GIT_SEND_EMAIL_NOTTY"}
|
||||||
|
? Term::ReadLine->new('git-send-email', \*STDIN, \*STDOUT)
|
||||||
|
: Term::ReadLine->new('git-send-email');
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
$term = FakeTerm->new("$@: going non-interactive");
|
||||||
|
}
|
||||||
|
return $term;
|
||||||
|
}
|
||||||
|
|
||||||
sub ask {
|
sub ask {
|
||||||
my ($prompt, %arg) = @_;
|
my ($prompt, %arg) = @_;
|
||||||
my $valid_re = $arg{valid_re};
|
my $valid_re = $arg{valid_re};
|
||||||
|
@ -866,6 +913,7 @@ sub ask {
|
||||||
my $confirm_only = $arg{confirm_only};
|
my $confirm_only = $arg{confirm_only};
|
||||||
my $resp;
|
my $resp;
|
||||||
my $i = 0;
|
my $i = 0;
|
||||||
|
my $term = term();
|
||||||
return defined $default ? $default : undef
|
return defined $default ? $default : undef
|
||||||
unless defined $term->IN and defined fileno($term->IN) and
|
unless defined $term->IN and defined fileno($term->IN) and
|
||||||
defined $term->OUT and defined fileno($term->OUT);
|
defined $term->OUT and defined fileno($term->OUT);
|
||||||
|
@ -963,7 +1011,7 @@ sub file_declares_8bit_cte {
|
||||||
$sender =~ s/^\s+|\s+$//g;
|
$sender =~ s/^\s+|\s+$//g;
|
||||||
($sender) = expand_aliases($sender);
|
($sender) = expand_aliases($sender);
|
||||||
} else {
|
} else {
|
||||||
$sender = $repoauthor || $repocommitter || '';
|
$sender = $repoauthor->() || $repocommitter->() || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
# $sender could be an already sanitized address
|
# $sender could be an already sanitized address
|
||||||
|
@ -1049,6 +1097,7 @@ sub extract_valid_address {
|
||||||
return $address if ($address =~ /^($local_part_regexp)$/);
|
return $address if ($address =~ /^($local_part_regexp)$/);
|
||||||
|
|
||||||
$address =~ s/^\s*<(.*)>\s*$/$1/;
|
$address =~ s/^\s*<(.*)>\s*$/$1/;
|
||||||
|
my $have_email_valid = eval { require Email::Valid; 1 };
|
||||||
if ($have_email_valid) {
|
if ($have_email_valid) {
|
||||||
return scalar Email::Valid->address($address);
|
return scalar Email::Valid->address($address);
|
||||||
}
|
}
|
||||||
|
@ -1108,14 +1157,15 @@ sub validate_address_list {
|
||||||
sub make_message_id {
|
sub make_message_id {
|
||||||
my $uniq;
|
my $uniq;
|
||||||
if (!defined $message_id_stamp) {
|
if (!defined $message_id_stamp) {
|
||||||
$message_id_stamp = strftime("%Y%m%d%H%M%S.$$", gmtime(time));
|
require POSIX;
|
||||||
|
$message_id_stamp = POSIX::strftime("%Y%m%d%H%M%S.$$", gmtime(time));
|
||||||
$message_id_serial = 0;
|
$message_id_serial = 0;
|
||||||
}
|
}
|
||||||
$message_id_serial++;
|
$message_id_serial++;
|
||||||
$uniq = "$message_id_stamp-$message_id_serial";
|
$uniq = "$message_id_stamp-$message_id_serial";
|
||||||
|
|
||||||
my $du_part;
|
my $du_part;
|
||||||
for ($sender, $repocommitter, $repoauthor) {
|
for ($sender, $repocommitter->(), $repoauthor->()) {
|
||||||
$du_part = extract_valid_address(sanitize_address($_));
|
$du_part = extract_valid_address(sanitize_address($_));
|
||||||
last if (defined $du_part and $du_part ne '');
|
last if (defined $du_part and $du_part ne '');
|
||||||
}
|
}
|
||||||
|
@ -1278,6 +1328,7 @@ sub valid_fqdn {
|
||||||
sub maildomain_net {
|
sub maildomain_net {
|
||||||
my $maildomain;
|
my $maildomain;
|
||||||
|
|
||||||
|
require Net::Domain;
|
||||||
my $domain = Net::Domain::domainname();
|
my $domain = Net::Domain::domainname();
|
||||||
$maildomain = $domain if valid_fqdn($domain);
|
$maildomain = $domain if valid_fqdn($domain);
|
||||||
|
|
||||||
|
@ -1288,6 +1339,7 @@ sub maildomain_mta {
|
||||||
my $maildomain;
|
my $maildomain;
|
||||||
|
|
||||||
for my $host (qw(mailhost localhost)) {
|
for my $host (qw(mailhost localhost)) {
|
||||||
|
require Net::SMTP;
|
||||||
my $smtp = Net::SMTP->new($host);
|
my $smtp = Net::SMTP->new($host);
|
||||||
if (defined $smtp) {
|
if (defined $smtp) {
|
||||||
my $domain = $smtp->domain;
|
my $domain = $smtp->domain;
|
||||||
|
@ -1980,13 +2032,15 @@ sub validate_patch {
|
||||||
|
|
||||||
if ($repo) {
|
if ($repo) {
|
||||||
my $hooks_path = $repo->command_oneline('rev-parse', '--git-path', 'hooks');
|
my $hooks_path = $repo->command_oneline('rev-parse', '--git-path', 'hooks');
|
||||||
my $validate_hook = catfile($hooks_path,
|
require File::Spec;
|
||||||
|
my $validate_hook = File::Spec->catfile($hooks_path,
|
||||||
'sendemail-validate');
|
'sendemail-validate');
|
||||||
my $hook_error;
|
my $hook_error;
|
||||||
if (-x $validate_hook) {
|
if (-x $validate_hook) {
|
||||||
my $target = abs_path($fn);
|
require Cwd;
|
||||||
|
my $target = Cwd::abs_path($fn);
|
||||||
# The hook needs a correct cwd and GIT_DIR.
|
# The hook needs a correct cwd and GIT_DIR.
|
||||||
my $cwd_save = cwd();
|
my $cwd_save = Cwd::getcwd();
|
||||||
chdir($repo->wc_path() or $repo->repo_path())
|
chdir($repo->wc_path() or $repo->repo_path())
|
||||||
or die("chdir: $!");
|
or die("chdir: $!");
|
||||||
local $ENV{"GIT_DIR"} = $repo->repo_path();
|
local $ENV{"GIT_DIR"} = $repo->repo_path();
|
||||||
|
|
32
perl/Git.pm
32
perl/Git.pm
|
@ -11,9 +11,6 @@ package Git;
|
||||||
use strict;
|
use strict;
|
||||||
use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
|
use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
|
||||||
|
|
||||||
use File::Temp ();
|
|
||||||
use File::Spec ();
|
|
||||||
|
|
||||||
BEGIN {
|
BEGIN {
|
||||||
|
|
||||||
our ($VERSION, @ISA, @EXPORT, @EXPORT_OK);
|
our ($VERSION, @ISA, @EXPORT, @EXPORT_OK);
|
||||||
|
@ -103,12 +100,9 @@ =head1 DESCRIPTION
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
|
|
||||||
use Carp qw(carp croak); # but croak is bad - throw instead
|
sub carp { require Carp; goto &Carp::carp }
|
||||||
|
sub croak { require Carp; goto &Carp::croak }
|
||||||
use Git::LoadCPAN::Error qw(:try);
|
use Git::LoadCPAN::Error qw(:try);
|
||||||
use Cwd qw(abs_path cwd);
|
|
||||||
use IPC::Open2 qw(open2);
|
|
||||||
use Fcntl qw(SEEK_SET SEEK_CUR);
|
|
||||||
use Time::Local qw(timegm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -191,13 +185,15 @@ sub repository {
|
||||||
$dir = undef;
|
$dir = undef;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
require Cwd;
|
||||||
if ($dir) {
|
if ($dir) {
|
||||||
|
require File::Spec;
|
||||||
File::Spec->file_name_is_absolute($dir) or $dir = $opts{Directory} . '/' . $dir;
|
File::Spec->file_name_is_absolute($dir) or $dir = $opts{Directory} . '/' . $dir;
|
||||||
$opts{Repository} = abs_path($dir);
|
$opts{Repository} = Cwd::abs_path($dir);
|
||||||
|
|
||||||
# If --git-dir went ok, this shouldn't die either.
|
# If --git-dir went ok, this shouldn't die either.
|
||||||
my $prefix = $search->command_oneline('rev-parse', '--show-prefix');
|
my $prefix = $search->command_oneline('rev-parse', '--show-prefix');
|
||||||
$dir = abs_path($opts{Directory}) . '/';
|
$dir = Cwd::abs_path($opts{Directory}) . '/';
|
||||||
if ($prefix) {
|
if ($prefix) {
|
||||||
if (substr($dir, -length($prefix)) ne $prefix) {
|
if (substr($dir, -length($prefix)) ne $prefix) {
|
||||||
throw Error::Simple("rev-parse confused me - $dir does not have trailing $prefix");
|
throw Error::Simple("rev-parse confused me - $dir does not have trailing $prefix");
|
||||||
|
@ -223,7 +219,7 @@ sub repository {
|
||||||
throw Error::Simple("fatal: Not a git repository: $dir");
|
throw Error::Simple("fatal: Not a git repository: $dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
$opts{Repository} = abs_path($dir);
|
$opts{Repository} = Cwd::abs_path($dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete $opts{Directory};
|
delete $opts{Directory};
|
||||||
|
@ -408,10 +404,12 @@ sub command_bidi_pipe {
|
||||||
my $cwd_save = undef;
|
my $cwd_save = undef;
|
||||||
if ($self) {
|
if ($self) {
|
||||||
shift;
|
shift;
|
||||||
$cwd_save = cwd();
|
require Cwd;
|
||||||
|
$cwd_save = Cwd::getcwd();
|
||||||
_setup_git_cmd_env($self);
|
_setup_git_cmd_env($self);
|
||||||
}
|
}
|
||||||
$pid = open2($in, $out, 'git', @_);
|
require IPC::Open2;
|
||||||
|
$pid = IPC::Open2::open2($in, $out, 'git', @_);
|
||||||
chdir($cwd_save) if $cwd_save;
|
chdir($cwd_save) if $cwd_save;
|
||||||
return ($pid, $in, $out, join(' ', @_));
|
return ($pid, $in, $out, join(' ', @_));
|
||||||
}
|
}
|
||||||
|
@ -538,7 +536,8 @@ sub get_tz_offset {
|
||||||
my $t = shift || time;
|
my $t = shift || time;
|
||||||
my @t = localtime($t);
|
my @t = localtime($t);
|
||||||
$t[5] += 1900;
|
$t[5] += 1900;
|
||||||
my $gm = timegm(@t);
|
require Time::Local;
|
||||||
|
my $gm = Time::Local::timegm(@t);
|
||||||
my $sign = qw( + + - )[ $gm <=> $t ];
|
my $sign = qw( + + - )[ $gm <=> $t ];
|
||||||
return sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]);
|
return sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]);
|
||||||
}
|
}
|
||||||
|
@ -1340,6 +1339,7 @@ sub _temp_cache {
|
||||||
my $n = $name;
|
my $n = $name;
|
||||||
$n =~ s/\W/_/g; # no strange chars
|
$n =~ s/\W/_/g; # no strange chars
|
||||||
|
|
||||||
|
require File::Temp;
|
||||||
($$temp_fd, $fname) = File::Temp::tempfile(
|
($$temp_fd, $fname) = File::Temp::tempfile(
|
||||||
"Git_${n}_XXXXXX", UNLINK => 1, DIR => $tmpdir,
|
"Git_${n}_XXXXXX", UNLINK => 1, DIR => $tmpdir,
|
||||||
) or throw Error::Simple("couldn't open new temp file");
|
) or throw Error::Simple("couldn't open new temp file");
|
||||||
|
@ -1362,9 +1362,9 @@ sub temp_reset {
|
||||||
|
|
||||||
truncate $temp_fd, 0
|
truncate $temp_fd, 0
|
||||||
or throw Error::Simple("couldn't truncate file");
|
or throw Error::Simple("couldn't truncate file");
|
||||||
sysseek($temp_fd, 0, SEEK_SET) and seek($temp_fd, 0, SEEK_SET)
|
sysseek($temp_fd, 0, Fcntl::SEEK_SET()) and seek($temp_fd, 0, Fcntl::SEEK_SET())
|
||||||
or throw Error::Simple("couldn't seek to beginning of file");
|
or throw Error::Simple("couldn't seek to beginning of file");
|
||||||
sysseek($temp_fd, 0, SEEK_CUR) == 0 and tell($temp_fd) == 0
|
sysseek($temp_fd, 0, Fcntl::SEEK_CUR()) == 0 and tell($temp_fd) == 0
|
||||||
or throw Error::Simple("expected file position to be reset");
|
or throw Error::Simple("expected file position to be reset");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1368,6 +1368,16 @@ test_expect_success $PREREQ 'sendemail.identity: bool variable fallback' '
|
||||||
! grep "X-Mailer" stdout
|
! grep "X-Mailer" stdout
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success $PREREQ 'sendemail.identity: bool variable without a value' '
|
||||||
|
git -c sendemail.xmailer \
|
||||||
|
send-email \
|
||||||
|
--dry-run \
|
||||||
|
--from="nobody@example.com" \
|
||||||
|
$patches >stdout &&
|
||||||
|
grep "To: default@example.com" stdout &&
|
||||||
|
grep "X-Mailer" stdout
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success $PREREQ '--no-to overrides sendemail.to' '
|
test_expect_success $PREREQ '--no-to overrides sendemail.to' '
|
||||||
git send-email \
|
git send-email \
|
||||||
--dry-run \
|
--dry-run \
|
||||||
|
@ -2092,6 +2102,18 @@ test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=true' '
|
||||||
do_xmailer_test 1 "--xmailer"
|
do_xmailer_test 1 "--xmailer"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer' '
|
||||||
|
test_when_finished "test_unconfig sendemail.xmailer" &&
|
||||||
|
cat >>.git/config <<-\EOF &&
|
||||||
|
[sendemail]
|
||||||
|
xmailer
|
||||||
|
EOF
|
||||||
|
test_config sendemail.xmailer true &&
|
||||||
|
do_xmailer_test 1 "" &&
|
||||||
|
do_xmailer_test 0 "--no-xmailer" &&
|
||||||
|
do_xmailer_test 1 "--xmailer"
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=false' '
|
test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=false' '
|
||||||
test_config sendemail.xmailer false &&
|
test_config sendemail.xmailer false &&
|
||||||
do_xmailer_test 0 "" &&
|
do_xmailer_test 0 "" &&
|
||||||
|
@ -2099,6 +2121,13 @@ test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=false' '
|
||||||
do_xmailer_test 1 "--xmailer"
|
do_xmailer_test 1 "--xmailer"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success $PREREQ '--[no-]xmailer with sendemail.xmailer=' '
|
||||||
|
test_config sendemail.xmailer "" &&
|
||||||
|
do_xmailer_test 0 "" &&
|
||||||
|
do_xmailer_test 0 "--no-xmailer" &&
|
||||||
|
do_xmailer_test 1 "--xmailer"
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success $PREREQ 'setup expected-list' '
|
test_expect_success $PREREQ 'setup expected-list' '
|
||||||
git send-email \
|
git send-email \
|
||||||
--dry-run \
|
--dry-run \
|
||||||
|
|
Loading…
Reference in New Issue