mirror of
https://github.com/git/git
synced 2024-10-02 14:45:21 +00:00
Merge branch 'ms/send-email-feed-header-to-validate-hook'
"git send-email" learned to give the e-mail headers to the validate hook by passing an extra argument from the command line. * ms/send-email-feed-header-to-validate-hook: send-email: expose header information to git-send-email's sendemail-validate hook send-email: refactor header generation functions
This commit is contained in:
commit
b6e9521956
|
@ -595,10 +595,29 @@ processed by rebase.
|
|||
sendemail-validate
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This hook is invoked by linkgit:git-send-email[1]. It takes a single parameter,
|
||||
the name of the file that holds the e-mail to be sent. Exiting with a
|
||||
non-zero status causes `git send-email` to abort before sending any
|
||||
e-mails.
|
||||
This hook is invoked by linkgit:git-send-email[1].
|
||||
|
||||
It takes these command line arguments. They are,
|
||||
1. the name of the file which holds the contents of the email to be sent.
|
||||
2. The name of the file which holds the SMTP headers of the email.
|
||||
|
||||
The SMTP headers are passed in the exact same way as they are passed to the
|
||||
user's Mail Transport Agent (MTA). In effect, the email given to the user's
|
||||
MTA, is the contents of $2 followed by the contents of $1.
|
||||
|
||||
An example of a few common headers is shown below. Take notice of the
|
||||
capitalization and multi-line tab structure.
|
||||
|
||||
From: Example <from@example.com>
|
||||
To: to@example.com
|
||||
Cc: cc@example.com,
|
||||
A <author@example.com>,
|
||||
One <one@example.com>,
|
||||
two@example.com
|
||||
Subject: PATCH-STRING
|
||||
|
||||
Exiting with a non-zero status causes `git send-email` to abort
|
||||
before sending any e-mails.
|
||||
|
||||
The following environment variables are set when executing the hook.
|
||||
|
||||
|
|
|
@ -792,7 +792,19 @@ sub is_format_patch_arg {
|
|||
@rev_list_opts);
|
||||
}
|
||||
|
||||
@files = handle_backup_files(@files);
|
||||
if (defined $sender) {
|
||||
$sender =~ s/^\s+|\s+$//g;
|
||||
($sender) = expand_aliases($sender);
|
||||
} else {
|
||||
$sender = $repoauthor->() || $repocommitter->() || '';
|
||||
}
|
||||
|
||||
# $sender could be an already sanitized address
|
||||
# (e.g. sendemail.from could be manually sanitized by user).
|
||||
# But it's a no-op to run sanitize_address on an already sanitized address.
|
||||
$sender = sanitize_address($sender);
|
||||
|
||||
$time = time - scalar $#files;
|
||||
|
||||
if ($validate) {
|
||||
# FIFOs can only be read once, exclude them from validation.
|
||||
|
@ -810,6 +822,7 @@ sub is_format_patch_arg {
|
|||
$ENV{GIT_SENDEMAIL_FILE_TOTAL} = "$num_files";
|
||||
foreach my $r (@real_files) {
|
||||
$ENV{GIT_SENDEMAIL_FILE_COUNTER} = "$num";
|
||||
pre_process_file($r, 1);
|
||||
validate_patch($r, $target_xfer_encoding);
|
||||
$num += 1;
|
||||
}
|
||||
|
@ -817,6 +830,8 @@ sub is_format_patch_arg {
|
|||
delete $ENV{GIT_SENDEMAIL_FILE_TOTAL};
|
||||
}
|
||||
|
||||
@files = handle_backup_files(@files);
|
||||
|
||||
if (@files) {
|
||||
unless ($quiet) {
|
||||
print $_,"\n" for (@files);
|
||||
|
@ -1065,18 +1080,6 @@ sub file_declares_8bit_cte {
|
|||
}
|
||||
}
|
||||
|
||||
if (defined $sender) {
|
||||
$sender =~ s/^\s+|\s+$//g;
|
||||
($sender) = expand_aliases($sender);
|
||||
} else {
|
||||
$sender = $repoauthor->() || $repocommitter->() || '';
|
||||
}
|
||||
|
||||
# $sender could be an already sanitized address
|
||||
# (e.g. sendemail.from could be manually sanitized by user).
|
||||
# But it's a no-op to run sanitize_address on an already sanitized address.
|
||||
$sender = sanitize_address($sender);
|
||||
|
||||
my $to_whom = __("To whom should the emails be sent (if anyone)?");
|
||||
my $prompting = 0;
|
||||
if (!@initial_to && !defined $to_cmd) {
|
||||
|
@ -1236,10 +1239,6 @@ sub make_message_id {
|
|||
#print "new message id = $message_id\n"; # Was useful for debugging
|
||||
}
|
||||
|
||||
|
||||
|
||||
$time = time - scalar $#files;
|
||||
|
||||
sub unquote_rfc2047 {
|
||||
local ($_) = @_;
|
||||
my $charset;
|
||||
|
@ -1517,16 +1516,7 @@ sub file_name_is_absolute {
|
|||
return File::Spec::Functions::file_name_is_absolute($path);
|
||||
}
|
||||
|
||||
# Prepares the email, then asks the user what to do.
|
||||
#
|
||||
# If the user chooses to send the email, it's sent and 1 is returned.
|
||||
# If the user chooses not to send the email, 0 is returned.
|
||||
# If the user decides they want to make further edits, -1 is returned and the
|
||||
# caller is expected to call send_message again after the edits are performed.
|
||||
#
|
||||
# If an error occurs sending the email, this just dies.
|
||||
|
||||
sub send_message {
|
||||
sub gen_header {
|
||||
my @recipients = unique_email_list(@to);
|
||||
@cc = (grep { my $cc = extract_valid_address_or_die($_);
|
||||
not grep { $cc eq $_ || $_ =~ /<\Q${cc}\E>$/ } @recipients
|
||||
|
@ -1568,6 +1558,22 @@ sub send_message {
|
|||
if (@xh) {
|
||||
$header .= join("\n", @xh) . "\n";
|
||||
}
|
||||
my $recipients_ref = \@recipients;
|
||||
return ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header);
|
||||
}
|
||||
|
||||
# Prepares the email, then asks the user what to do.
|
||||
#
|
||||
# If the user chooses to send the email, it's sent and 1 is returned.
|
||||
# If the user chooses not to send the email, 0 is returned.
|
||||
# If the user decides they want to make further edits, -1 is returned and the
|
||||
# caller is expected to call send_message again after the edits are performed.
|
||||
#
|
||||
# If an error occurs sending the email, this just dies.
|
||||
|
||||
sub send_message {
|
||||
my ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();
|
||||
my @recipients = @$recipients_ref;
|
||||
|
||||
my @sendmail_parameters = ('-i', @recipients);
|
||||
my $raw_from = $sender;
|
||||
|
@ -1757,11 +1763,8 @@ sub send_message {
|
|||
$references = $initial_in_reply_to || '';
|
||||
$message_num = 0;
|
||||
|
||||
# Prepares the email, prompts the user, sends it out
|
||||
# Returns 0 if an edit was done and the function should be called again, or 1
|
||||
# otherwise.
|
||||
sub process_file {
|
||||
my ($t) = @_;
|
||||
sub pre_process_file {
|
||||
my ($t, $quiet) = @_;
|
||||
|
||||
open my $fh, "<", $t or die sprintf(__("can't open file %s"), $t);
|
||||
|
||||
|
@ -1915,9 +1918,9 @@ sub process_file {
|
|||
}
|
||||
close $fh;
|
||||
|
||||
push @to, recipients_cmd("to-cmd", "to", $to_cmd, $t)
|
||||
push @to, recipients_cmd("to-cmd", "to", $to_cmd, $t, $quiet)
|
||||
if defined $to_cmd;
|
||||
push @cc, recipients_cmd("cc-cmd", "cc", $cc_cmd, $t)
|
||||
push @cc, recipients_cmd("cc-cmd", "cc", $cc_cmd, $t, $quiet)
|
||||
if defined $cc_cmd && !$suppress_cc{'cccmd'};
|
||||
|
||||
if ($broken_encoding{$t} && !$has_content_type) {
|
||||
|
@ -1976,6 +1979,15 @@ sub process_file {
|
|||
@initial_to = @to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Prepares the email, prompts the user, and sends it out
|
||||
# Returns 0 if an edit was done and the function should be called again, or 1
|
||||
# on the email being successfully sent out.
|
||||
sub process_file {
|
||||
my ($t) = @_;
|
||||
|
||||
pre_process_file($t, $quiet);
|
||||
|
||||
my $message_was_sent = send_message();
|
||||
if ($message_was_sent == -1) {
|
||||
|
@ -2024,7 +2036,7 @@ sub process_file {
|
|||
# Execute a command (e.g. $to_cmd) to get a list of email addresses
|
||||
# and return a results array
|
||||
sub recipients_cmd {
|
||||
my ($prefix, $what, $cmd, $file) = @_;
|
||||
my ($prefix, $what, $cmd, $file, $quiet) = @_;
|
||||
|
||||
my @addresses = ();
|
||||
open my $fh, "-|", "$cmd \Q$file\E"
|
||||
|
@ -2110,10 +2122,21 @@ sub validate_patch {
|
|||
chdir($repo->wc_path() or $repo->repo_path())
|
||||
or die("chdir: $!");
|
||||
local $ENV{"GIT_DIR"} = $repo->repo_path();
|
||||
|
||||
my ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();
|
||||
|
||||
require File::Temp;
|
||||
my ($header_filehandle, $header_filename) = File::Temp::tempfile(
|
||||
TEMPLATE => ".gitsendemail.header.XXXXXX",
|
||||
DIR => $repo->repo_path(),
|
||||
UNLINK => 1,
|
||||
);
|
||||
print $header_filehandle $header;
|
||||
|
||||
my @cmd = ("git", "hook", "run", "--ignore-missing",
|
||||
$hook_name, "--");
|
||||
my @cmd_msg = (@cmd, "<patch>");
|
||||
my @cmd_run = (@cmd, $target);
|
||||
my @cmd_msg = (@cmd, "<patch>", "<header>");
|
||||
my @cmd_run = (@cmd, $target, $header_filename);
|
||||
$hook_error = system_or_msg(\@cmd_run, undef, "@cmd_msg");
|
||||
chdir($cwd_save) or die("chdir: $!");
|
||||
}
|
||||
|
|
|
@ -540,7 +540,7 @@ test_expect_success $PREREQ "--validate respects relative core.hooksPath path" '
|
|||
test_path_is_file my-hooks.ran &&
|
||||
cat >expect <<-EOF &&
|
||||
fatal: longline.patch: rejected by sendemail-validate hook
|
||||
fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1
|
||||
fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1
|
||||
warning: no patches were sent
|
||||
EOF
|
||||
test_cmp expect actual
|
||||
|
@ -559,12 +559,35 @@ test_expect_success $PREREQ "--validate respects absolute core.hooksPath path" '
|
|||
test_path_is_file my-hooks.ran &&
|
||||
cat >expect <<-EOF &&
|
||||
fatal: longline.patch: rejected by sendemail-validate hook
|
||||
fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1
|
||||
fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1
|
||||
warning: no patches were sent
|
||||
EOF
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success $PREREQ "--validate hook supports header argument" '
|
||||
write_script my-hooks/sendemail-validate <<-\EOF &&
|
||||
if test "$#" -ge 2
|
||||
then
|
||||
grep "X-test-header: v1.0" "$2"
|
||||
else
|
||||
echo "No header arg passed"
|
||||
exit 1
|
||||
fi
|
||||
EOF
|
||||
test_config core.hooksPath "my-hooks" &&
|
||||
rm -fr outdir &&
|
||||
git format-patch \
|
||||
--add-header="X-test-header: v1.0" \
|
||||
-n HEAD^1 -o outdir &&
|
||||
git send-email \
|
||||
--dry-run \
|
||||
--to=nobody@example.com \
|
||||
--smtp-server="$(pwd)/fake.sendmail" \
|
||||
--validate \
|
||||
outdir/000?-*.patch
|
||||
'
|
||||
|
||||
for enc in 7bit 8bit quoted-printable base64
|
||||
do
|
||||
test_expect_success $PREREQ "--transfer-encoding=$enc produces correct header" '
|
||||
|
|
Loading…
Reference in a new issue