X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=git-send-email-script;h=86b676a0409579d8d94f7a7a60a72b339426c9f2;hb=452ce291a99131768e2d61d2dcf8a4a1b78d39a3;hp=4927cec3d00c7947a6ee9bfd3f5404a762b9b02b;hpb=3342d8500f8393ace9030a44496943b6a8de1dc3;p=git.git diff --git a/git-send-email-script b/git-send-email-script index 4927cec3..86b676a0 100755 --- a/git-send-email-script +++ b/git-send-email-script @@ -4,17 +4,17 @@ # Copyright 2005 Ryan Anderson # # GPL v2 (See COPYING) -# +# # Ported to support git "mbox" format files by Ryan Anderson # # Sends a collection of emails to the given email addresses, disturbingly fast. -# +# # Supports two formats: # 1. mbox format files (ignoring most headers and MIME formatting - this is designed for sending patches) # 2. The original format support by Greg's script: -# first line of the message is who to CC, +# first line of the message is who to CC, # and second line is the subject of the message. -# +# use strict; use warnings; @@ -24,8 +24,14 @@ use Getopt::Long; use Data::Dumper; use Email::Valid; +sub unique_email_list(@); +sub cleanup_compose_files(); + +# Constants (essentially) +my $compose_filename = ".msg.$$"; + # Variables we fill in automatically, or via prompting: -my (@to,@cc,$initial_reply_to,$initial_subject,@files,$from); +my (@to,@cc,$initial_reply_to,$initial_subject,@files,$from,$compose); # Behavior modification variables my ($chain_reply_to, $smtp_server) = (1, "localhost"); @@ -44,6 +50,7 @@ my $rc = GetOptions("from=s" => \$from, "to=s" => \@to, "chain-reply-to!" => \$chain_reply_to, "smtp-server=s" => \$smtp_server, + "compose" => \$compose, ); # Now, let's fill any that aren't set in with defaults: @@ -67,38 +74,41 @@ while() { } close(GITVAR); - +my $prompting = 0; if (!defined $from) { $from = $author || $committer; do { $_ = $term->readline("Who should the emails appear to be from? ", $from); - while (!defined $_); + } while (!defined $_); $from = $_; print "Emails will be sent from: ", $from, "\n"; + $prompting++; } if (!@to) { do { - $_ = $term->readline("Who should the emails be sent to? ", + $_ = $term->readline("Who should the emails be sent to? ", ""); } while (!defined $_); my $to = $_; push @to, split /,/, $to; + $prompting++; } -if (!defined $initial_subject) { +if (!defined $initial_subject && $compose) { do { - $_ = $term->readline("What subject should the emails start with? ", + $_ = $term->readline("What subject should the emails start with? ", $initial_subject); } while (!defined $_); $initial_subject = $_; + $prompting++; } -if (!defined $initial_reply_to) { +if (!defined $initial_reply_to && $prompting) { do { - $_= $term->readline("Message-ID to be used as In-Reply-To? ", + $_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ", $initial_reply_to); } while (!defined $_); @@ -110,6 +120,52 @@ if (!defined $smtp_server) { $smtp_server = "localhost"; } +if ($compose) { + # Note that this does not need to be secure, but we will make a small + # effort to have it be unique + open(C,">",$compose_filename) + or die "Failed to open for writing $compose_filename: $!"; + print C "From \n"; + printf C "Subject: %s\n\n", $initial_subject; + printf C <",$compose_filename . ".final") + or die "Failed to open $compose_filename.final : " . $!; + + open(C,"<",$compose_filename) + or die "Failed to open $compose_filename : " . $!; + + while() { + next if m/^GIT: /; + print C2 $_; + } + close(C); + close(C2); + + do { + $_ = $term->readline("Send this email? (y|n) "); + } while (!defined $_); + + if (uc substr($_,0,1) ne 'Y') { + cleanup_compose_files(); + exit(0); + } + + @files = ($compose_filename . ".final"); +} + + # Now that all the defaults are set, process the rest of the command line # arguments and collect up the files that need to be processed. for my $f (@ARGV) { @@ -117,7 +173,7 @@ for my $f (@ARGV) { opendir(DH,$f) or die "Failed to opendir $f: $!"; - push @files, map { +$f . "/" . $_ } grep { -f $_ } + push @files, grep { -f $_ } map { +$f . "/" . $_ } sort readdir(DH); } elsif (-f $f) { @@ -135,11 +191,24 @@ if (@files) { git-send-email-script [options] [... file | directory ] Options: --from Specify the "From:" line of the email to be sent. - --to Specify the primary "To:" line of the email. + + --to Specify the primary "To:" line of the email. + + --compose Use \$EDITOR to edit an introductory message for the + patch series. + --subject Specify the initial "Subject:" line. + Only necessary if --compose is also set. If --compose + is not set, this will be prompted for. + --in-reply-to Specify the first "In-Reply-To:" header line. - --chain-reply-to If set, the replies will all be to the first - email sent, rather than to the last email sent. + Only used if --compose is also set. If --compose is not + set, this will be prompted for. + + --chain-reply-to If set, the replies will all be to the previous + email sent, rather than to the first email sent. + Defaults to on. + --smtp-server If set, specifies the outgoing SMTP server to use. Defaults to localhost. @@ -161,7 +230,7 @@ our ($message_id, $cc, %mail, $subject, $reply_to, $message); # We'll setup a template for the message id, using the "from" address: my $message_id_from = Email::Valid->address($from); -my $message_id_template = "<%s-git-send-email-$from>"; +my $message_id_template = "<%s-git-send-email-$message_id_from>"; sub make_message_id { @@ -178,10 +247,7 @@ $cc = ""; sub send_message { - my %to; - $to{lc(Email::Valid->address($_))}++ for (@to); - - my $to = join(",", keys %to); + my $to = join (", ", unique_email_list(@to)); %mail = ( To => $to, From => $from, @@ -249,7 +315,7 @@ foreach my $t (@files) { $subject = $_; } } - + # A whitespace line will terminate the headers if (m/^\s*$/) { $header_done = 1; @@ -267,10 +333,7 @@ foreach my $t (@files) { } close F; - my %clean_ccs; - $clean_ccs{lc(Email::Valid->address($_))}++ for @cc; - - $cc = join(",", keys %clean_ccs); + $cc = join(", ", unique_email_list(@cc)); send_message(); @@ -279,5 +342,27 @@ foreach my $t (@files) { $reply_to = $message_id; } make_message_id(); -# $subject = "Re: ".$initial_subject; +} + +if ($compose) { + cleanup_compose_files(); +} + +sub cleanup_compose_files() { + unlink($compose_filename, $compose_filename . ".final"); + +} + + + +sub unique_email_list(@) { + my %seen; + my @emails; + + foreach my $entry (@_) { + my $clean = Email::Valid->address($entry); + next if $seen{$clean}++; + push @emails, $entry; + } + return @emails; }