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 <ava...@gmail.com>
Signed-off-by: Jonathan Tan <jonathanta...@google.com>
---

Change from v1: followed Ævar's suggestions, and also moved the new
functionality into validate_patch().
---
 Documentation/git-send-email.txt |  1 +
 Documentation/githooks.txt       |  8 ++++++++
 git-send-email.perl              | 20 +++++++++++++++++++-
 t/t9001-send-email.sh            | 40 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 9d66166f6..bb23b02ca 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -377,6 +377,7 @@ have been specified, in which case default to 'compose'.
        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.
 --
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 706091a56..b2514f4d4 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -447,6 +447,14 @@ 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
 ---
diff --git a/git-send-email.perl b/git-send-email.perl
index eea0a517f..c314cc2b5 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -25,8 +25,9 @@ use Getopt::Long;
 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 Cwd qw(abs_path cwd);
 use Git;
 use Git::I18N;
 
@@ -1737,6 +1738,23 @@ sub unique_email_list {
 
 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>) {
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 60a80f60b..f3f238d40 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -1913,4 +1913,44 @@ test_expect_success $PREREQ 'leading and trailing 
whitespaces are removed' '
        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 -e 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 <nob...@example.com>" \
+                       --to=nob...@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 <nob...@example.com>" \
+                       --to=nob...@example.com \
+                       --smtp-server="$(pwd)/../fake.sendmail" \
+                       ../another.patch 2>err
+               test_i18ngrep "rejected by sendemail-validate hook" err
+       )
+'
+
 test_done
-- 
2.13.0.rc2.291.g57267f2277-goog

Reply via email to