From: Junio C Hamano Date: Fri, 28 Nov 2008 03:24:00 +0000 (-0800) Subject: Merge branch 'ph/send-email' X-Git-Tag: v1.6.1-rc1~14 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/496db64202b11e66a080873ca9e32f1354dcfd3e?ds=inline;hp=-c Merge branch 'ph/send-email' * ph/send-email: git send-email: ask less questions when --compose is used. git send-email: add --annotate option git send-email: interpret unknown files as revision lists git send-email: make the message file name more specific. --- 496db64202b11e66a080873ca9e32f1354dcfd3e diff --combined git-send-email.perl index 007e2c6ee1,9039cfde06..7508f8ff24 --- a/git-send-email.perl +++ b/git-send-email.perl @@@ -22,8 -22,12 +22,12 @@@ use Term::ReadLine use Getopt::Long; use Data::Dumper; use Term::ANSIColor; + use File::Temp qw/ tempdir /; + use Error qw(:try); use Git; + Getopt::Long::Configure qw/ pass_through /; + package FakeTerm; sub new { my ($class, $reason) = @_; @@@ -38,7 -42,7 +42,7 @@@ package main sub usage { print <... + git send-email [options] Composing: --from * Email From: @@@ -47,6 -51,7 +51,7 @@@ --bcc * Email Bcc: --subject * Email "Subject:" --in-reply-to * Email "In-Reply-To:" + --annotate * Review each patch that will be sent in an editor. --compose * Open an editor for introduction. Sending: @@@ -73,6 -78,8 +78,8 @@@ --quiet * Output one line of info per email. --dry-run * Don't actually send the emails. --[no-]validate * Perform patch sanity checks. Default on. + --[no-]format-patch * understand any non optional arguments as + `git format-patch` ones. EOT exit(1); @@@ -124,12 -131,10 +131,10 @@@ my $auth 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_cc,@bcclist,@xh, - $initial_reply_to,$initial_subject,@files,$author,$sender,$smtp_authpass,$compose,$time); + $initial_reply_to,$initial_subject,@files, + $author,$sender,$smtp_authpass,$annotate,$compose,$time); my $envelope_sender; @@@ -149,6 -154,27 +154,27 @@@ if ($@) # Behavior modification variables my ($quiet, $dry_run) = (0, 0); + my $format_patch; + my $compose_filename = $repo->repo_path() . "/.gitsendemail.msg.$$"; + + # Handle interactive edition of files. + my $multiedit; + my $editor = $ENV{GIT_EDITOR} || Git::config(@repo, "core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi"; + sub do_edit { + if (defined($multiedit) && !$multiedit) { + map { + system('sh', '-c', $editor.' "$@"', $editor, $_); + if (($? & 127) || ($? >> 8)) { + die("the editor exited uncleanly, aborting everything"); + } + } @_; + } else { + system('sh', '-c', $editor.' "$@"', $editor, @_); + if (($? & 127) || ($? >> 8)) { + die("the editor exited uncleanly, aborting everything"); + } + } + } # Variables with corresponding config settings my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc, $cc_cmd); @@@ -179,6 -205,7 +205,7 @@@ my %config_settings = "aliasesfile" => \@alias_files, "suppresscc" => \@suppress_cc, "envelopesender" => \$envelope_sender, + "multiedit" => \$multiedit, ); # Handle Uncouth Termination @@@ -221,6 -248,7 +248,7 @@@ my $rc = GetOptions("sender|from=s" => "smtp-ssl" => sub { $smtp_encryption = 'ssl' }, "smtp-encryption=s" => \$smtp_encryption, "identity=s" => \$identity, + "annotate" => \$annotate, "compose" => \$compose, "quiet" => \$quiet, "cc-cmd=s" => \$cc_cmd, @@@ -231,6 -259,7 +259,7 @@@ "envelope-sender=s" => \$envelope_sender, "thread!" => \$thread, "validate!" => \$validate, + "format-patch!" => \$format_patch, ); unless ($rc) { @@@ -345,13 -374,10 +374,13 @@@ my %parse_alias = # spaces delimit multiple addresses $aliases{$1} = [ split(/\s+/, $2) ]; }}}, - pine => sub { my $fh = shift; while (<$fh>) { - if (/^(\S+)\t.*\t(.*)$/) { + pine => sub { my $fh = shift; my $f='\t[^\t]*'; + for (my $x = ''; defined($x); $x = $_) { + chomp $x; + $x .= $1 while(defined($_ = <$fh>) && /^ +(.*)$/); + $x =~ /^(\S+)$f\t\(?([^\t]+?)\)?(:?$f){0,2}$/ or next; $aliases{$1} = [ split(/\s*,\s*/, $2) ]; - }}}, + }}, gnus => sub { my $fh = shift; while (<$fh>) { if (/\(define-mail-alias\s+"(\S+?)"\s+"(\S+?)"\)/) { $aliases{$1} = [ $2 ]; @@@ -368,23 -394,52 +397,52 @@@ if (@alias_files and $aliasfiletype an ($sender) = expand_aliases($sender) if defined $sender; + # returns 1 if the conflict must be solved using it as a format-patch argument + sub check_file_rev_conflict($) { + my $f = shift; + try { + $repo->command('rev-parse', '--verify', '--quiet', $f); + if (defined($format_patch)) { + print "foo\n"; + return $format_patch; + } + die(<command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts); + } + if ($validate) { foreach my $f (@files) { unless (-p $f) { @@@ -403,6 -458,108 +461,108 @@@ if (@files) usage(); } + sub get_patch_subject($) { + my $fn = shift; + open (my $fh, '<', $fn); + while (my $line = <$fh>) { + next unless ($line =~ /^Subject: (.*)$/); + close $fh; + return "GIT: $1\n"; + } + close $fh; + die "No subject line in $fn ?"; + } + + 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: $!"; + + + my $tpl_sender = $sender || $repoauthor || $repocommitter || ''; + my $tpl_subject = $initial_subject || ''; + my $tpl_reply_to = $initial_reply_to || ''; + + print C <",$compose_filename . ".final") + or die "Failed to open $compose_filename.final : " . $!; + + open(C,"<",$compose_filename) + or die "Failed to open $compose_filename : " . $!; + + my $need_8bit_cte = file_has_nonascii($compose_filename); + my $in_body = 0; + my $summary_empty = 1; + while() { + next if m/^GIT: /; + if ($in_body) { + $summary_empty = 0 unless (/^\n$/); + } elsif (/^\n$/) { + $in_body = 1; + if ($need_8bit_cte) { + print C2 "MIME-Version: 1.0\n", + "Content-Type: text/plain; ", + "charset=utf-8\n", + "Content-Transfer-Encoding: 8bit\n"; + } + } elsif (/^MIME-Version:/i) { + $need_8bit_cte = 0; + } elsif (/^Subject:\s*(.+)\s*$/i) { + $initial_subject = $1; + my $subject = $initial_subject; + $_ = "Subject: " . + ($subject =~ /[^[:ascii:]]/ ? + quote_rfc2047($subject) : + $subject) . + "\n"; + } elsif (/^In-Reply-To:\s*(.+)\s*$/i) { + $initial_reply_to = $1; + next; + } elsif (/^From:\s*(.+)\s*$/i) { + $sender = $1; + next; + } elsif (/^(?:To|Cc|Bcc):/i) { + print "To/Cc/Bcc fields are not interpreted yet, they have been ignored\n"; + next; + } + print C2 $_; + } + close(C); + close(C2); + + if ($summary_empty) { + print "Summary email is empty, skipping it\n"; + $compose = -1; + } + } elsif ($annotate) { + do_edit(@files); + } + my $prompting = 0; if (!defined $sender) { $sender = $repoauthor || $repocommitter || ''; @@@ -447,17 -604,6 +607,6 @@@ sub expand_aliases @initial_cc = expand_aliases(@initial_cc); @bcclist = expand_aliases(@bcclist); - if (!defined $initial_subject && $compose) { - while (1) { - $_ = $term->readline("What subject should the initial email start with? ", $initial_subject); - last if defined $_; - print "\n"; - } - - $initial_subject = $_; - $prompting++; - } - if ($thread && !defined $initial_reply_to && $prompting) { while (1) { $_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ", $initial_reply_to); @@@ -484,59 -630,6 +633,6 @@@ if (!defined $smtp_server) } 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 $sender # This line is ignored.\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 : " . $!; - - my $need_8bit_cte = file_has_nonascii($compose_filename); - my $in_body = 0; - while() { - next if m/^GIT: /; - if (!$in_body && /^\n$/) { - $in_body = 1; - if ($need_8bit_cte) { - print C2 "MIME-Version: 1.0\n", - "Content-Type: text/plain; ", - "charset=utf-8\n", - "Content-Transfer-Encoding: 8bit\n"; - } - } - if (!$in_body && /^MIME-Version:/i) { - $need_8bit_cte = 0; - } - if (!$in_body && /^Subject: ?(.*)/i) { - my $subject = $1; - $_ = "Subject: " . - ($subject =~ /[^[:ascii:]]/ ? - quote_rfc2047($subject) : - $subject) . - "\n"; - } - print C2 $_; - } - close(C); - close(C2); - while (1) { $_ = $term->readline("Send this email? (y|n) "); last if defined $_; @@@ -548,7 -641,9 +644,9 @@@ exit(0); } - @files = ($compose_filename . ".final", @files); + if ($compose > 0) { + @files = ($compose_filename . ".final", @files); + } } # Variables we set as part of the loop over files