send-email: support validate hook
authorJonathan Tan <jonathantanmy@google.com>
Fri, 12 May 2017 22:38:26 +0000 (15:38 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 16 May 2017 02:13:00 +0000 (11:13 +0900)
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>
Documentation/git-send-email.txt
Documentation/githooks.txt
git-send-email.perl
t/t9001-send-email.sh
index 9d66166f69d93e544c949ad80fe0f432fa3f1ffd..bb23b02caf3ee50a32c86d97e0451cd4be6ab232 100644 (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
                        is due to SMTP limits as described by http://www.ietf.org/rfc/rfc2821.txt.
 --
                *       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.
 --
index 706091a569c17cae93e250ed7cb34d056a5b25f0..b2514f4d4426a730e65bcae264a6364eb50bcd60 100644 (file)
@@ -447,6 +447,14 @@ rebase::
 The commits are guaranteed to be listed in the order that they were
 processed by rebase.
 
 The commits are guaranteed to be listed in the order that they were
 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
 ---
index eea0a517f71b66f861db38f70fac0593f8c8cea4..c314cc2b51e363defcd216391df1ef6dd5897f16 100755 (executable)
@@ -25,8 +25,9 @@
 use Text::ParseWords;
 use Term::ANSIColor;
 use File::Temp qw/ tempdir tempfile /;
 use Text::ParseWords;
 use Term::ANSIColor;
 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::I18N;
 
 use Git;
 use Git::I18N;
 
@@ -1737,6 +1738,23 @@ sub unique_email_list {
 
 sub validate_patch {
        my $fn = shift;
 
 sub validate_patch {
        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)
                or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
        while (my $line = <$fh>) {
        open(my $fh, '<', $fn)
                or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
        while (my $line = <$fh>) {
index 60a80f60b2685c461f80cdbf4256eb17dc18b85b..15128c755a4eb820b9735e1a94616a694b1b8054 100755 (executable)
@@ -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