From: Michael Witten <mfwitten@gmail.com>
To: git@vger.kernel.org
Subject: [PATCH RFC3 12/13] send-email: --compose takes optional argument to existing file
Date: Mon, 13 Apr 2009 13:23:56 -0500 [thread overview]
Message-ID: <1239647037-15381-13-git-send-email-mfwitten@gmail.com> (raw)
In-Reply-To: <1239647037-15381-12-git-send-email-mfwitten@gmail.com>
Now, a user may specify an existing (in-progress) file to use as
the introductory/summary email.
The file is opened for any additional editing as usual, but it
is not deleted upon normal termination.
There are also a number of fixes to how the internals and
temporaries are handled.
Also, it is no longer possible to pass --compose multiple times
in order to edit the transformed version as well.
Also, send-email now aborts upon discovering an empty message.
Signed-off-by: Michael Witten <mfwitten@gmail.com>
---
Documentation/git-send-email.txt | 40 +++++++--
git-send-email.perl | 182 ++++++++++++++++++++++++--------------
2 files changed, 145 insertions(+), 77 deletions(-)
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 93cfb34..5ef8b12 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -55,17 +55,39 @@ The --bcc option must be repeated for each user you want on the bcc list.
+
The --cc option must be repeated for each user you want on the cc list.
---compose::
- Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an
- introductory message for the patch series.
+--compose[=<path>]::
+ Create an introductory message for the patch series; the
+ message is opened for editing with (in order of preference)
+ `$GIT_EDITOR`, 'core.editor', `$VISUAL`, `$EDITOR`, or `vi`.
+
-When '--compose' is used, git send-email will use the From, Subject, and
-In-Reply-To headers specified in the message. If the body of the message
-(what you type after the headers and a blank line) only contains blank
-(or GIT: prefixed) lines the summary won't be sent, but From, Subject,
-and In-Reply-To headers will be used unless they are removed.
+A path for the composition may be given. If the path exists, then
+the file at the path is opened for editing as-is. If the path
+doesn't exist, a file with default content is created at the path
+and opened for editing. If no path is specified, a new temporary
+file with default content is created and opened for editing.
+
-Missing From or In-Reply-To headers will be prompted for.
+Upon the successful completion of send-email, all temporary files
+are automatically unlinked (deleted). However, if send-email is
+terminated by a trappable signal, then this temporary file is not
+unlinked, and the user is informed of its path.
++
+The user actually composes what will become a valid email message;
+therefore, the message must have the following form (as described in
+`RFC 822`):
++
+ <headers>
+ <blank line>
+ <body>
++
+In particular, `<headers>` must contain the "`Subject`" header. Once
+the user saves the message and quits the editor, this intermediate
+message is transformed into the final email message by removing all
+lines that begin with "`GIT:`". If the `<body>` of the final version
+is empty, then send-email aborts without sending anything.
++
+The "`From`", "`Subject`", and "`In-Reply-To`" headers are taken
+directly from the message; missing "`From`" or "`In-Reply-To`"
+headers will be prompted for.
+
See the CONFIGURATION section for 'sendemail.multiedit'.
diff --git a/git-send-email.perl b/git-send-email.perl
index 8ce9d3b..2ab76c6 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -58,10 +58,9 @@ git send-email [options] <file | directory | rev-list options >
--bcc <address> * Email Bcc:
--subject <string> * Email "Subject:"
--in-reply-to <message-id> * Email "In-Reply-To:"; include '<' and '>'.
+ --compose [<path>] * Open an editor for introduction.
--annotate * Review each patch that will be sent in
an editor.
- --compose * Open an editor for introduction.
-
Sending:
--envelope-sender <address> * Email envelope sender.
--smtp-server <host> * Outgoing SMTP server.
@@ -168,7 +167,7 @@ if ($@) {
# Behavior modification variables
my ($quiet, $dry_run) = (0, 0);
my $format_patch;
-my $compose_filename;
+my ($compose_path, $compose_final_path);
# Handle interactive edition of files.
my $multiedit;
@@ -234,16 +233,15 @@ sub signal_handler {
system "stty echo";
# tmp files from --compose
- if (defined $compose_filename) {
- if (-e $compose_filename) {
- print "'$compose_filename' contains an intermediate version of the email you were composing.\n";
- }
- if (-e ($compose_filename . ".final")) {
- print "'$compose_filename.final' contains the composed email.\n"
- }
+ if (defined $compose_path and -f $compose_path) {
+ print "'$compose_path' contains an intermediate version of the email you were composing.\n";
+ }
+
+ if (defined $compose_final_path) {
+ unlink $compose_final_path if defined $compose_final_path;
}
- exit;
+ exit 1;
};
$SIG{TERM} = \&signal_handler;
@@ -268,8 +266,8 @@ my $rc = GetOptions(
"smtp-ssl" => sub { $smtp_encryption = 'ssl' },
"smtp-encryption=s" => \$smtp_encryption,
"identity=s" => \$identity,
+ "compose:s" => \$compose,
"annotate" => \$annotate,
- "compose" => \$compose,
"quiet" => \$quiet,
"cc-cmd=s" => \$cc_cmd,
"suppress-from!" => \$suppress_from,
@@ -590,60 +588,108 @@ sub get_patch_subject($) {
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
- $compose_filename = ($repo ?
- tempfile(".gitsendemail.msg.XXXXXX", DIR => $repo->repo_path()) :
- tempfile(".gitsendemail.msg.XXXXXX", DIR => "."))[1];
- 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 <<EOT;
-From $tpl_sender # This line is ignored.
-GIT: Lines beginning in "GIT:" will be removed.
-GIT: Consider including an overall diffstat or table of contents
-GIT: for the patch you are writing.
-GIT:
-GIT: Clear the body content if you don't wish to send a summary.
-From: $tpl_sender
-Subject: $tpl_subject
-In-Reply-To: $tpl_reply_to
+if (defined $compose) {
-EOT
- for my $f (@files) {
- print C get_patch_subject($f);
+ # Some parameters for creating temporary files:
+
+ my $template = ".gitsendemail.msg.XXXXXX";
+ my @dir = (DIR => ($repo ? $repo->repo_path() : "."));
+ my @suffix = (SUFFIX => ".final");
+
+ # Figure out the file that the user should be editing:
+
+ my $compose_path_filehandle;
+
+ if ($compose eq '') { # if no path was given
+ ($compose_path_filehandle, $compose_path) = tempfile($template, @dir)
+ or die "--compose: Could not create temporary file for the user to edit: $!\n";
+ } else {
+ $compose_path = $compose;
+ unless (-f $compose_path) {
+ open $compose_path_filehandle, ">", $compose_path
+ or die "--compose: Could not open '$compose_path' for writing default content: $!\n";
+ }
}
- close(C);
+
+ # Fill in default content if necessary:
+
+ if ($compose_path_filehandle) {
+
+ # For convenience:
+
+ local *STDOUT = $compose_path_filehandle;
+
+ # Help the user out with some instruction and initial headers:
+
+ my $from = $sender || $repoauthor || $repocommitter || '';
+ my $subject = $initial_subject || '';
+ my $reply_to = $initial_reply_to || '';
+
+ print "From $from # This line is ignored.\n";
+ print "GIT:\n";
+ print "GIT: Lines beginning in 'GIT:' will be removed.\n";
+ print "GIT:\n";
+ print "GIT: Consider including an overall diffstat\n";
+ print "GIT: (git diff --stat) or table of contents\n";
+ print "GIT: (as provide below).\n";
+ print "GIT:\n";
+ print "GIT: Clear the body content if you decide not\n";
+ print "GIT: to send this message.\n";
+ print "GIT:\n";
+ print "GIT: Here are the <headers>:\n";
+ print "From: $from\n";
+ print "Subject: $subject\n";
+ print "In-Reply-To: $reply_to\n";
+ print "\n";
+ print "GIT: This is the first line of the <body>:\n";
+ print "\n";
+
+ for my $f (@files) {
+ print get_patch_subject($f);
+ }
+ }
+
+ # Do the editing:
if ($annotate) {
- do_edit($compose_filename, @files);
+ do_edit($compose_path, @files);
} else {
- do_edit($compose_filename);
+ do_edit($compose_path);
}
- open(C2,">",$compose_filename . ".final")
- or die "Failed to open $compose_filename.final : " . $!;
+ # Now transform the user-edited introduction into something
+ # suitable for sending via email; the user's editor may have
+ # unlinked the original file and replaced it with an entirely
+ # new one. If this be the case, then it wouldn't do just to seek
+ # to the beginning and start reading, because then only the
+ # original content would be retrieved. Consequently, the file
+ # must be reopened to be safe (note, the original filehandle is
+ # closed automatically):
+
+ unless (-f $compose_path) {
+ die "--compose: File '$compose_path' doesn't exist; aborting.\n";
+ }
+
+ open $compose_path_filehandle, "<", $compose_path
+ or die "--compose: Failed to open '$compose_path' for reading: $!";
- open(C,"<",$compose_filename)
- or die "Failed to open $compose_filename : " . $!;
+ # Create the final version:
- my $need_8bit_cte = file_has_nonascii($compose_filename);
+ (my $compose_final_file, $compose_final_path) = tempfile($template, @dir, @suffix)
+ or die "--compose: Could not create temporary file for final version: $!\n";
+
+ my ($subject, $reply_to, $from);
+ my $need_8bit_cte = file_has_nonascii($compose_path);
my $in_body = 0;
my $summary_empty = 1;
- while(<C>) {
+ while(<$compose_path_filehandle>) {
next if m/^GIT:/;
if ($in_body) {
$summary_empty = 0 unless (/^\n$/);
} elsif (/^\n$/) {
$in_body = 1;
if ($need_8bit_cte) {
- print C2
+ print $compose_final_file
"MIME-Version: 1.0\n",
"Content-Type: text/plain; ",
"charset=utf-8\n",
@@ -653,12 +699,7 @@ EOT
$need_8bit_cte = 0;
} elsif (/^Subject:\s*(.+)\s*$/i) {
$initial_subject = $1;
- my $subject = $initial_subject;
- $_ = "Subject: " .
- ($subject =~ /[^[:ascii:]]/ ?
- quote_rfc2047($subject) :
- $subject) .
- "\n";
+ next;
} elsif (/^In-Reply-To:\s*(.+)\s*$/i) {
$initial_reply_to = $1;
next;
@@ -669,15 +710,14 @@ EOT
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;
+ print $compose_final_file $_;
}
+
+ $summary_empty and die "Introductory email is empty; aborting.\n";
+
+ unshift(@files, $compose_final_path);
+
} elsif ($annotate) {
do_edit(@files);
}
@@ -770,10 +810,6 @@ if (defined $smtp_server && $smtp_server ne '') {
$smtp_server_is_a_command = 0;
}
-if ($compose && $compose > 0) {
- @files = ($compose_filename . ".final", @files);
-}
-
# Variables we set as part of the loop over files
our ($message_id, %mail, $subject, $reply_to, $references, $message,
$needs_confirm, $message_num, $ask_default);
@@ -918,9 +954,12 @@ sub send_message
my $sanitized_sender = sanitize_address($sender);
make_message_id() unless defined($message_id);
+ my $has_non_ascii = ($subject =~ /[^[:ascii:]]/);
+ my $sanitized_subject = $has_non_ascii ? quote_rfc2047($subject) : $subject;
+
my $header = "From: $sanitized_sender
To: $to${ccline}
-Subject: $subject
+Subject: $sanitized_subject
Date: $date
Message-Id: $message_id
X-Mailer: git-send-email $gitversion
@@ -1280,7 +1319,14 @@ for (my $index = 0; $index < @files; $index++) {
cleanup_compose_files();
sub cleanup_compose_files() {
- unlink($compose_filename, $compose_filename . ".final") if $compose;
+
+ if (defined $compose_final_path) {
+ unlink $compose_final_path;
+ }
+
+ if (defined $compose_path and not $compose) {
+ unlink $compose_path;
+ }
}
$smtp->quit if $smtp;
--
1.6.2.2.479.g2aec
next prev parent reply other threads:[~2009-04-13 18:38 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-13 18:23 [PATCH RFC3 INTRO] I hope this will do it! Michael Witten
2009-04-13 18:23 ` [PATCH RFC3 01/13] Docs: send-email: Put options back into alphabetical order Michael Witten
2009-04-13 18:23 ` [PATCH RFC3 02/13] Docs: send-email: Refer to CONFIGURATION section for sendemail.multiedit Michael Witten
2009-04-13 18:23 ` [PATCH RFC3 03/13] Docs: send-email: Remove superfluous information in CONFIGURATION Michael Witten
2009-04-13 18:23 ` [PATCH RFC3 04/13] Docs: send-email: --smtp-server-port can take symbolic ports Michael Witten
2009-04-13 18:23 ` [PATCH RFC3 05/13] send-email: Cleanup the usage text and docs a bit Michael Witten
2009-04-13 18:23 ` [PATCH RFC3 06/13] send-email: Handle "GIT:" rather than "GIT: " during --compose Michael Witten
2009-04-13 18:23 ` [PATCH RFC3 07/13] send-email: 'References:' should only reference what is sent Michael Witten
2009-04-13 18:23 ` [PATCH RFC3 08/13] send-email: Remove superfluous `my $editor = ...' Michael Witten
2009-04-13 18:23 ` [PATCH RFC3 09/13] send-email: Remove horrible mix of tabs and spaces Michael Witten
2009-04-13 18:23 ` [PATCH RFC3 10/13] send-email: Add --sleep for email throttling Michael Witten
2009-04-13 18:23 ` [PATCH RFC3 11/13] send-email: Minor cleanup of $smtp_server usage and send_message() Michael Witten
2009-04-13 18:23 ` Michael Witten [this message]
2009-04-13 18:23 ` [PATCH RFC3 13/13] send-email: --compose always includes a 'GIT: ' prefixed list of patch subjects Michael Witten
2009-04-13 20:55 ` [PATCH RFC3 09/13] send-email: Remove horrible mix of tabs and spaces Junio C Hamano
2009-04-13 22:49 ` Michael Witten
2009-04-14 5:31 ` Andreas Ericsson
2009-04-14 6:19 ` Junio C Hamano
2009-04-14 7:17 ` Andreas Ericsson
2009-04-14 7:03 ` Michael Witten
2009-04-14 7:38 ` Andreas Ericsson
2009-04-13 23:39 ` [PATCH RFC3 08/13] send-email: Remove superfluous `my $editor = ...' Stephen Boyd
2009-04-14 0:41 ` Michael Witten
2009-04-14 0:43 ` Michael Witten
2009-04-14 6:16 ` Björn Steinbrink
2009-04-14 8:51 ` Junio C Hamano
2009-04-13 20:51 ` [PATCH RFC3 05/13] send-email: Cleanup the usage text and docs a bit Junio C Hamano
2009-04-13 22:42 ` Michael Witten
2009-04-14 5:39 ` Junio C Hamano
2009-04-14 6:00 ` Michael Witten
2009-04-14 6:46 ` Junio C Hamano
2009-04-14 7:15 ` Michael Witten
2009-04-13 20:45 ` [PATCH RFC3 03/13] Docs: send-email: Remove superfluous information in CONFIGURATION Junio C Hamano
2009-04-13 22:30 ` Michael Witten
2009-04-13 18:45 ` [PATCH RFC3 INTRO] I hope this will do it! Michael Witten
2009-04-14 9:02 ` Junio C Hamano
2009-04-14 16:26 ` Michael Witten
2009-04-14 18:47 ` Junio C Hamano
2009-04-14 18:50 ` Michael Witten
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1239647037-15381-13-git-send-email-mfwitten@gmail.com \
--to=mfwitten@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).