send-email: support validate hook

Currently, send-email has support for rudimentary e-mail validation.
Allow the user to add support for more validation by providing a
sendemail-validate hook.

Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jonathan Tan 2017-05-12 15:38:26 -07:00 committed by Junio C Hamano
parent b06d364310
commit 6489660b4b
4 changed files with 68 additions and 1 deletions

View file

@ -377,6 +377,7 @@ have been specified, in which case default to 'compose'.
Currently, validation means the following: Currently, validation means the following:
+ +
-- --
* Invoke the sendemail-validate hook if present (see linkgit:githooks[5]).
* Warn of patches that contain lines longer than 998 characters; this * Warn of patches that contain lines longer than 998 characters; this
is due to SMTP limits as described by http://www.ietf.org/rfc/rfc2821.txt. is due to SMTP limits as described by http://www.ietf.org/rfc/rfc2821.txt.
-- --

View file

@ -447,6 +447,14 @@ rebase::
The commits are guaranteed to be listed in the order that they were The commits are guaranteed to be listed in the order that they were
processed by rebase. processed by rebase.
sendemail-validate
~~~~~~~~~~~~~~~~~~
This hook is invoked by 'git send-email'. 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.
GIT GIT
--- ---

View file

@ -25,8 +25,9 @@
use Text::ParseWords; use Text::ParseWords;
use Term::ANSIColor; use Term::ANSIColor;
use File::Temp qw/ tempdir tempfile /; use File::Temp qw/ tempdir tempfile /;
use File::Spec::Functions qw(catfile); use File::Spec::Functions qw(catdir catfile);
use Error qw(:try); use Error qw(:try);
use Cwd qw(abs_path cwd);
use Git; use Git;
use Git::I18N; use Git::I18N;
@ -1737,6 +1738,23 @@ sub unique_email_list {
sub validate_patch { sub validate_patch {
my $fn = shift; my $fn = shift;
my $validate_hook = catfile(catdir($repo->repo_path(), 'hooks'),
'sendemail-validate');
my $hook_error;
if (-x $validate_hook) {
my $target = abs_path($fn);
# The hook needs a correct cwd and GIT_DIR.
my $cwd_save = cwd();
chdir($repo->wc_path() or $repo->repo_path())
or die("chdir: $!");
local $ENV{"GIT_DIR"} = $repo->repo_path();
$hook_error = "rejected by sendemail-validate hook"
if system($validate_hook, $target);
chdir($cwd_save) or die("chdir: $!");
}
return $hook_error if $hook_error;
open(my $fh, '<', $fn) open(my $fh, '<', $fn)
or die sprintf(__("unable to open %s: %s\n"), $fn, $!); or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
while (my $line = <$fh>) { while (my $line = <$fh>) {

View file

@ -1913,4 +1913,44 @@ 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 'invoke hook' '
mkdir -p .git/hooks &&
write_script .git/hooks/sendemail-validate <<-\EOF &&
# test that we have the correct environment variable, pwd, and
# argument
case "$GIT_DIR" in
*.git)
true
;;
*)
false
;;
esac &&
test -f 0001-add-master.patch &&
grep "add master" "$1"
EOF
mkdir subdir &&
(
# Test that it works even if we are not at the root of the
# working tree
cd subdir &&
git send-email \
--from="Example <nobody@example.com>" \
--to=nobody@example.com \
--smtp-server="$(pwd)/../fake.sendmail" \
../0001-add-master.patch &&
# Verify error message when a patch is rejected by the hook
sed -e "s/add master/x/" ../0001-add-master.patch >../another.patch &&
git send-email \
--from="Example <nobody@example.com>" \
--to=nobody@example.com \
--smtp-server="$(pwd)/../fake.sendmail" \
../another.patch 2>err
test_i18ngrep "rejected by sendemail-validate hook" err
)
'
test_done test_done