]> git.ipfire.org Git - thirdparty/git.git/blobdiff - git-send-email.perl
hex: introduce functions to print arbitrary hashes
[thirdparty/git.git] / git-send-email.perl
index 2fa7818ca9a8ac7363d17aef17b864f7361b3eb8..2be5dac337a0e2f4a0ea1538c7873aa43382cb04 100755 (executable)
@@ -231,7 +231,7 @@ my ($validate, $confirm);
 my (@suppress_cc);
 my ($auto_8bit_encoding);
 my ($compose_encoding);
-my ($target_xfer_encoding);
+my $target_xfer_encoding = 'auto';
 
 my ($debug_net_smtp) = 0;              # Net::SMTP, see send_message()
 
@@ -645,7 +645,7 @@ if (@rev_list_opts) {
 if ($validate) {
        foreach my $f (@files) {
                unless (-p $f) {
-                       my $error = validate_patch($f);
+                       my $error = validate_patch($f, $target_xfer_encoding);
                        $error and die sprintf(__("fatal: %s: %s\nwarning: no patches were sent\n"),
                                                  $f, $error);
                }
@@ -1330,9 +1330,14 @@ sub file_name_is_absolute {
        return File::Spec::Functions::file_name_is_absolute($path);
 }
 
-# Returns 1 if the message was sent, and 0 otherwise.
-# In actuality, the whole program dies when there
-# is an error sending a message.
+# 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 = unique_email_list(@to);
@@ -1404,15 +1409,17 @@ Message-Id: $message_id
 
 EOF
                }
-               # TRANSLATORS: Make sure to include [y] [n] [q] [a] in your
+               # TRANSLATORS: Make sure to include [y] [n] [e] [q] [a] in your
                # translation. The program will only accept English input
                # at this point.
-               $_ = ask(__("Send this email? ([y]es|[n]o|[q]uit|[a]ll): "),
-                        valid_re => qr/^(?:yes|y|no|n|quit|q|all|a)/i,
+               $_ = ask(__("Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): "),
+                        valid_re => qr/^(?:yes|y|no|n|edit|e|quit|q|all|a)/i,
                         default => $ask_default);
                die __("Send this email reply required") unless defined $_;
                if (/^n/i) {
                        return 0;
+               } elsif (/^e/i) {
+                       return -1;
                } elsif (/^q/i) {
                        cleanup_compose_files();
                        exit(0);
@@ -1472,7 +1479,7 @@ EOF
                                                         SSL => 1);
                        }
                }
-               else {
+               elsif (!$smtp) {
                        $smtp_server_port ||= 25;
                        $smtp ||= Net::SMTP->new($smtp_server,
                                                 Hello => $smtp_domain,
@@ -1494,7 +1501,6 @@ EOF
                                        $smtp->starttls(ssl_verify_params())
                                                or die sprintf(__("STARTTLS failed! %s"), IO::Socket::SSL::errstr());
                                }
-                               $smtp_encryption = '';
                                # Send EHLO again to receive fresh
                                # supported commands
                                $smtp->hello($smtp_domain);
@@ -1552,7 +1558,12 @@ $references = $initial_in_reply_to || '';
 $subject = $initial_subject;
 $message_num = 0;
 
-foreach my $t (@files) {
+# 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) = @_;
+
        open my $fh, "<", $t or die sprintf(__("can't open file %s"), $t);
 
        my $author = undef;
@@ -1642,10 +1653,15 @@ foreach my $t (@files) {
                        elsif (/^Content-Transfer-Encoding: (.*)/i) {
                                $xfer_encoding = $1 if not defined $xfer_encoding;
                        }
+                       elsif (/^In-Reply-To: (.*)/i) {
+                               $in_reply_to = $1;
+                       }
+                       elsif (/^References: (.*)/i) {
+                               $references = $1;
+                       }
                        elsif (!/^Date:\s/i && /^[-A-Za-z]+:\s+\S/) {
                                push @xh, $_;
                        }
-
                } else {
                        # In the traditional
                        # "send lots of email" format,
@@ -1720,18 +1736,11 @@ foreach my $t (@files) {
                        }
                }
        }
-       if (defined $target_xfer_encoding) {
-               $xfer_encoding = '8bit' if not defined $xfer_encoding;
-               $message = apply_transfer_encoding(
-                       $message, $xfer_encoding, $target_xfer_encoding);
-               $xfer_encoding = $target_xfer_encoding;
-       }
-       if (defined $xfer_encoding) {
-               push @xh, "Content-Transfer-Encoding: $xfer_encoding";
-       }
-       if (defined $xfer_encoding or $has_content_type) {
-               unshift @xh, 'MIME-Version: 1.0' unless $has_mime_version;
-       }
+       $xfer_encoding = '8bit' if not defined $xfer_encoding;
+       ($message, $xfer_encoding) = apply_transfer_encoding(
+               $message, $xfer_encoding, $target_xfer_encoding);
+       push @xh, "Content-Transfer-Encoding: $xfer_encoding";
+       unshift @xh, 'MIME-Version: 1.0' unless $has_mime_version;
 
        $needs_confirm = (
                $confirm eq "always" or
@@ -1755,6 +1764,10 @@ foreach my $t (@files) {
        }
 
        my $message_was_sent = send_message();
+       if ($message_was_sent == -1) {
+               do_edit($t);
+               return 0;
+       }
 
        # set up for the next message
        if ($thread && $message_was_sent &&
@@ -1776,6 +1789,14 @@ foreach my $t (@files) {
                undef $auth;
                sleep($relogin_delay) if defined $relogin_delay;
        }
+
+       return 1;
+}
+
+foreach my $t (@files) {
+       while (!process_file($t)) {
+               # user edited the file
+       }
 }
 
 # Execute a command (e.g. $to_cmd) to get a list of email addresses
@@ -1823,13 +1844,16 @@ sub apply_transfer_encoding {
        $message = MIME::Base64::decode($message)
                if ($from eq 'base64');
 
+       $to = ($message =~ /.{999,}/) ? 'quoted-printable' : '8bit'
+               if $to eq 'auto';
+
        die __("cannot send message as 7bit")
                if ($to eq '7bit' and $message =~ /[^[:ascii:]]/);
-       return $message
+       return ($message, $to)
                if ($to eq '7bit' or $to eq '8bit');
-       return MIME::QuotedPrint::encode($message, "\n", 0)
+       return (MIME::QuotedPrint::encode($message, "\n", 0), $to)
                if ($to eq 'quoted-printable');
-       return MIME::Base64::encode($message, "\n")
+       return (MIME::Base64::encode($message, "\n"), $to)
                if ($to eq 'base64');
        die __("invalid transfer encoding");
 }
@@ -1848,7 +1872,7 @@ sub unique_email_list {
 }
 
 sub validate_patch {
-       my $fn = shift;
+       my ($fn, $xfer_encoding) = @_;
 
        if ($repo) {
                my $validate_hook = catfile(catdir($repo->repo_path(), 'hooks'),
@@ -1868,11 +1892,15 @@ sub validate_patch {
                return $hook_error if $hook_error;
        }
 
-       open(my $fh, '<', $fn)
-               or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
-       while (my $line = <$fh>) {
-               if (length($line) > 998) {
-                       return sprintf(__("%s: patch contains a line longer than 998 characters"), $.);
+       # Any long lines will be automatically fixed if we use a suitable transfer
+       # encoding.
+       unless ($xfer_encoding =~ /^(?:auto|quoted-printable|base64)$/) {
+               open(my $fh, '<', $fn)
+                       or die sprintf(__("unable to open %s: %s\n"), $fn, $!);
+               while (my $line = <$fh>) {
+                       if (length($line) > 998) {
+                               return sprintf(__("%s: patch contains a line longer than 998 characters"), $.);
+                       }
                }
        }
        return;