From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:33
The teaser
==========
This series has been sent using:
git send-email --to git@vger.kernel.org --compose --annotate HEAD~3..
The series
==========
Here is a patch series to improve git send-email following our
discussions at GitTogether'08, despite my hate for perl.
The first patch is a minor nitpick, because leaking fd's sucks.
The second patch allow git-send-email to receive revision lists as
arguments. This doesn't allow complex arguments combinations as it
proces the revision lists one by one (IOW ^$sha1 $sha2 won't work as
expected _at all_) but this shouldn't be a problem since this command is
primarily used for interactive users. People wanting to use
git-send-email with complex revision lists through scripts MUST
git-format-patch first into a safe temporary directory and use
git-send-email on this afterwards.
The last patch adds the possibility to review patches into an editor
before sending them, which allow you (thanks to patch 2) to serialize,
review, annotate, and send patches in one command.
Further discussion
==================
I think one could make git send-email better doing this:
(1) make --compose and --annotate default, do not asking for a Subject
if it's missing, neither should we ask for the in-reply-to if it's
missing.
Then spawn the editor with a first empty file that contains rougly a
template looking like this:
----8<----
GIT: Purge this buffer from any content if you don't want a series summary
GIT:
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: Please fill a Subject if missing
GIT: Leave the In-Reply-To field empty if not applicable.
Subject:
In-Reply-To:
--> <we may want to add some more headers here: To/Cc/Bcc/...>
GIT: put the content of the mail below this line
GIT: [PATCH 1/10] .... \
GIT: [PATCH 2/10] .... | this would contain all the Subject's
[...] | from the commits that are beeing sent
GIT: [PATCH 8/10] .... | as a conveniency for people not
GIT: [PATCH 9/10] .... | having to cut&paste them
GIT: [PATCH 10/10] .... /
---->8----
I suggest we don't enable --compose when the series is reduced to
one patch, as the usual way is to comment inline. This is probably
arguable.
(2) Introduce a --batch option that basically:
* turns --compose and --annotate off
* turns any interactive feature off
* complain (and fail) if it misses any information that is usually
asked interactively
What do you think ?
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:33
Instead of skipping unkown files on the command line, pass them through
git format-patch into a safe temporary directory. This allow no
complicated rev-list option lists combining "--all" "--not" and so on, but
allow to use ranges which are quite enough for most of the use cases.
Signed-off-by: Pierre Habouzit <redacted>
---
Documentation/git-send-email.txt | 2 +-
git-send-email.perl | 6 ++++--
2 files changed, 5 insertions(+), 3 deletions(-)
@@ -378,7 +379,8 @@ for my $f (@ARGV) {}elsif(-f$for-p$f){push@files,$f;}else{-printSTDERR"Skipping $f - not found.\n";+my$tempdir=tempdir(CLEANUP=>1);+push@files,$repo->command('format-patch','-o',$tempdir,$f);}}
@@ -374,10 +374,9 @@ for my $f (@ARGV) {push@files,grep{-f$_}map{+$f."/".$_}sortreaddir(DH);-+closedir(DH);}elsif(-f$for-p$f){push@files,$f;-}else{printSTDERR"Skipping $f - not found.\n";}
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:33
This allows to review every patch (and fix various aspects of them, or
comment them) in an editor just before being sent. Combined to the fact
that git send-email can now process revision lists, this makes git
send-email and efficient way to review and send patches interactively.
Signed-off-by: Pierre Habouzit <redacted>
---
Documentation/git-send-email.txt | 11 +++++++++++
git-send-email.perl | 26 ++++++++++++++++++++++++--
2 files changed, 35 insertions(+), 2 deletions(-)
@@ -37,6 +37,11 @@ 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.+--annotate::+ Review each patch you're about to send in an editor. The setting+ 'sendemail.multiedit' defines if this will spawn one editor per patch+ or one for all of them at once.+ --compose:: Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an introductory message for the patch series.
@@ -204,6 +209,12 @@ sendemail.aliasfiletype:: Format of the file(s) specified in sendemail.aliasesfile. Must be one of 'mutt', 'mailrc', 'pine', or 'gnus'.+sendemail.multiedit::+ If true (default), a single editor instance will be spawned to edit+ files you have to edit (patches when '--annotate' is used, and the+ summary when '--compose' is used). If false, files will be edited one+ after the other, spawning a new editor each time.+ Author ------
@@ -130,7 +131,8 @@ 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;
@@ -151,6 +153,17 @@ if ($@) {# Behavior modification variablesmy($quiet,$dry_run)=(0,0);+# Handle interactive edition of files.+my$multiedit;+my$editor=$ENV{GIT_EDITOR}||Git::config(@repo,"core.editor")||$ENV{VISUAL}||$ENV{EDITOR}||"vi";+subdo_edit{+if(defined($multiedit)&&!$multiedit){+map{system('sh','-c',$editor.' "$@"',$editor,$_);}@_;+}else{+system('sh','-c',$editor.' "$@"',$editor,@_);+}+}+# Variables with corresponding config settingsmy($thread,$chain_reply_to,$suppress_from,$signed_off_by_cc,$cc_cmd);my($smtp_server,$smtp_server_port,$smtp_authuser,$smtp_encryption);
@@ -222,6 +236,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,"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,
@@ -499,7 +514,12 @@ EOTclose(C);my$editor=$ENV{GIT_EDITOR}||Git::config(@repo,"core.editor")||$ENV{VISUAL}||$ENV{EDITOR}||"vi";-system('sh','-c',$editor.' "$@"',$editor,$compose_filename);++if($annotate){+do_edit($compose_filename,@files);+}else{+do_edit($compose_filename);+}open(C2,">",$compose_filename.".final")ordie"Failed to open $compose_filename.final : ".$!;
@@ -548,6 +568,8 @@ EOT}@files=($compose_filename.".final",@files);+}elsif($annotate){+do_edit(@files);}# Variables we set as part of the loop over files
@@ -127,7 +127,7 @@ sub unique_email_list(@);subcleanup_compose_files();# Constants (essentially)-my$compose_filename=".msg.$$";+my$compose_filename=".gitsendemail.msg.$$";# Variables we fill in automatically, or via prompting:my(@to,@cc,@initial_cc,@bcclist,@xh,
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:33
Here is a three patch series (again).
[PATCH 1/3] git send-email: make the message file name more specific.
-> quite independant, and should IMHO be taken.
[PATCH 2/3] git send-email: do not ask questions when --compose is used.
[PATCH 3/3] git send-email: turn --compose on when more than one patch.
Those two patches enhance git-send-email by making ask less questions
when --compose is used (as it can grab the subject, from and reply-to
from the buffer).
It also turns --compose on by default as soon as there is more than
one patch, as I believe than commenting a patch series is more often
done than not. It's is really trivial to "refuse" to comment the
series by just erasing the full buffer content, which should not
really be too anoying (or one can explicitely pass --no-compose for
the same result).
It's probable that those two changes may trigger some discussion
though, but I just used that to send this series, and I can tell with
this git-send-email is nearer what I would like it to be.
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:33
When --compose is used, we can grab the From/Subject/In-Reply-To from the
edited summary, let it be so and don't ask the user silly questions.
The summary templates gets quite revamped, and includes the list of
patches subjects that are going to be sent with this batch.
Signed-off-by: Pierre Habouzit <redacted>
---
git-send-email.perl | 174 ++++++++++++++++++++++++++++++---------------------
1 files changed, 102 insertions(+), 72 deletions(-)
@@ -417,6 +417,105 @@ if (@files) {usage();}+subget_patch_subject($){+my$fn=shift;+open(my$fh,'<',$fn);+while(my$line=<$fh>){+nextunless($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)+ordie"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||'';++printC<<EOT;+From$tpl_sender# This line is ignored.+GIT:Linesbeginningin"GIT: "willberemoved.+GIT:Considerincludinganoveralldiffstatortableofcontents+GIT:forthepatchyouarewriting.+From:$tpl_sender+Subject:$tpl_subject+In-Reply-To:$tpl_reply_to++GIT:Pleaseenteryouremailbelowthisline.++EOT+formy$f(@files){+printCget_patch_subject($f);+}+close(C);++my$editor=$ENV{GIT_EDITOR}||Git::config(@repo,"core.editor")||$ENV{VISUAL}||$ENV{EDITOR}||"vi";++if($annotate){+do_edit($compose_filename,@files);+}else{+do_edit($compose_filename);+}++open(C2,">",$compose_filename.".final")+ordie"Failed to open $compose_filename.final : ".$!;++open(C,"<",$compose_filename)+ordie"Failed to open $compose_filename : ".$!;++my$need_8bit_cte=file_has_nonascii($compose_filename);+my$in_body=0;+my$summary_empty=1;+while(<C>){+nextifm/^GIT: /;+if($in_body){+}elsif(/^\n$/){+$in_body=1;+if($need_8bit_cte){+printC2"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;+}+$summary_empty=0;+printC2$_;+}+close(C);+close(C2);++if($summary_empty){+print"Summary email is empty, skpping it\n";+$compose=-1;+}+}elsif($annotate){+do_edit(@files);+}+my$prompting=0;if(!defined$sender){$sender=$repoauthor||$repocommitter||'';
@@ -461,17 +560,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);-lastifdefined$_;-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);
@@ -498,64 +586,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)-ordie"Failed to open for writing $compose_filename: $!";-printC"From $sender # This line is ignored.\n";-printfC"Subject: %s\n\n",$initial_subject;-printfC<<EOT;-GIT:Pleaseenteryouremailbelow.-GIT:Linesbeginningin"GIT: "willberemoved.-GIT:Considerincludinganoveralldiffstatortableofcontents-GIT:forthepatchyouarewriting.--EOT-close(C);--my$editor=$ENV{GIT_EDITOR}||Git::config(@repo,"core.editor")||$ENV{VISUAL}||$ENV{EDITOR}||"vi";--if($annotate){-do_edit($compose_filename,@files);-}else{-do_edit($compose_filename);-}--open(C2,">",$compose_filename.".final")-ordie"Failed to open $compose_filename.final : ".$!;--open(C,"<",$compose_filename)-ordie"Failed to open $compose_filename : ".$!;--my$need_8bit_cte=file_has_nonascii($compose_filename);-my$in_body=0;-while(<C>){-nextifm/^GIT: /;-if(!$in_body&&/^\n$/){-$in_body=1;-if($need_8bit_cte){-printC2"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";-}-printC2$_;-}-close(C);-close(C2);-while(1){$_=$term->readline("Send this email? (y|n) ");lastifdefined$_;
@@ -567,9 +597,9 @@ EOTexit(0);}-@files=($compose_filename.".final",@files);-}elsif($annotate){-do_edit(@files);+if($compose>0){+@files=($compose_filename.".final",@files);+}}# Variables we set as part of the loop over files
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:33
Automatically turn --compose on when there is more than one patch, and
that the output is a tty.
Do not print the list of files sent anymore in that case, as the list is
shown in the summary editor.
Signed-off-by: Pierre Habouzit <redacted>
---
git-send-email.perl | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
@@ -237,7 +237,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,"smtp-encryption=s"=>\$smtp_encryption,"identity=s"=>\$identity,"annotate"=>\$annotate,-"compose"=>\$compose,+"compose!"=>\$compose,"quiet"=>\$quiet,"cc-cmd=s"=>\$cc_cmd,"suppress-from!"=>\$suppress_from,
@@ -409,7 +409,11 @@ if ($validate) {}if(@files){-unless($quiet){+if(!defined($compose)&&-tSTDOUT){+# turn $compose on if there is more than one file+$compose=$#files;+}+unless($quiet||$compose){print$_,"\n"for(@files);}}else{
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:33
Signed-off-by: Pierre Habouzit <redacted>
---
One can consider to squash that on top of
[off-list ref] to be able to pass
all non path arguments before a possible '--' to git format-patch.
The downside of this patch is that:
git send-email -C -C -M origin/next
will send the content of origin/next if it's an existing file. Of course a
disambiguation can be:
git send-email -C -C -M refs/heads/origin/next
But again if this file also exists, one is basically screwed. I see no
proper way to fix that, unless to change git-send-email behaviour at once.
Though I believe this semantics to be better than the one in the previous
patch, as it's often a good idea to pass -M -C -C to format-patch, which is
currently impossible. It also allow revision lists to work as expected (wrt
--all, --not and so on).
Comments are welcomed.
Documentation/git-send-email.txt | 2 +-
git-send-email.perl | 19 ++++++++++++++-----
2 files changed, 15 insertions(+), 6 deletions(-)
@@ -383,8 +385,12 @@ if (@alias_files and $aliasfiletype and defined $parse_alias{$aliasfiletype}) {# 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.-formy$f(@ARGV){-if(-d$f){+my@rev_list_opts;+while(my$f=pop@ARGV){+if($feq"--"){+push@rev_list_opts,"--",@ARGV;+@ARGV=();+}elsif(-d$f){opendir(DH,$f)ordie"Failed to opendir $f: $!";
@@ -394,11 +400,14 @@ for my $f (@ARGV) {}elsif(-f$for-p$f){push@files,$f;}else{-my$tempdir=tempdir(CLEANUP=>1);-push@files,$repo->command('format-patch','-o',$tempdir,$f);+push@rev_list_opts,$f;}}+if(@rev_list_opts){+push@files,$repo->command('format-patch','-o',tempdir(CLEANUP=>1),@rev_list_opts);+}+if($validate){foreachmy$f(@files){unless(-p$f){
On Fri, Oct 31, 2008 at 01:36:48PM +0100, Pierre Habouzit wrote:
+GIT: Please enter your email below this line.
At first glance I thought this meant to enter my email address here.
So, instead of "email" would "message" be better? Although on second
glance I realized this is where the body of the message went. Not sure
if this is worth changing.
Ian
On Fri, Oct 31, 2008 at 11:57:12AM +0100, Pierre Habouzit wrote:
quoted hunk
This allows to review every patch (and fix various aspects of them, or
comment them) in an editor just before being sent. Combined to the fact
that git send-email can now process revision lists, this makes git
send-email and efficient way to review and send patches interactively.
Signed-off-by: Pierre Habouzit <redacted>
---
Documentation/git-send-email.txt | 11 +++++++++++
git-send-email.perl | 26 ++++++++++++++++++++++++--
2 files changed, 35 insertions(+), 2 deletions(-)
@@ -37,6 +37,11 @@ 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.+--annotate::+ Review each patch you're about to send in an editor. The setting+ 'sendemail.multiedit' defines if this will spawn one editor per patch+ or one for all of them at once.+ --compose:: Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an introductory message for the patch series.
@@ -204,6 +209,12 @@ sendemail.aliasfiletype:: Format of the file(s) specified in sendemail.aliasesfile. Must be one of 'mutt', 'mailrc', 'pine', or 'gnus'.+sendemail.multiedit::+ If true (default), a single editor instance will be spawned to edit+ files you have to edit (patches when '--annotate' is used, and the+ summary when '--compose' is used). If false, files will be edited one+ after the other, spawning a new editor each time.+ Author ------
@@ -130,7 +131,8 @@ 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;
@@ -151,6 +153,17 @@ if ($@) {# Behavior modification variablesmy($quiet,$dry_run)=(0,0);+# Handle interactive edition of files.
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:33
On Fri, Oct 31, 2008 at 09:33:38PM +0000, Ian Hilt wrote:
On Fri, Oct 31, 2008 at 01:36:48PM +0100, Pierre Habouzit wrote:
quoted
+GIT: Please enter your email below this line.
At first glance I thought this meant to enter my email address here.
So, instead of "email" would "message" be better? Although on second
glance I realized this is where the body of the message went. Not sure
if this is worth changing.
Well, this line sounds kind of awkward actually, so I was even thinking
about removing it.
Decent editors should probably have a plugin to put the cursor here and
be done with it.
In fact what looks odd is the GIT: stuff. a line looking like:
--- write your message below this line ---
Looks 10x better, though need some code to strip it out if the user kept
it, and I'm lazy, GIT: stuff is automatically removed...
But if that's the only thing that you don't like in the series, I'm
glad, this is quite a minor issue ;)
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
On Fri, Oct 31, 2008 at 10:38:03PM +0100, Pierre Habouzit wrote:
On Fri, Oct 31, 2008 at 09:33:38PM +0000, Ian Hilt wrote:
quoted
On Fri, Oct 31, 2008 at 01:36:48PM +0100, Pierre Habouzit wrote:
quoted
+GIT: Please enter your email below this line.
At first glance I thought this meant to enter my email address here.
So, instead of "email" would "message" be better? Although on second
glance I realized this is where the body of the message went. Not sure
if this is worth changing.
Well, this line sounds kind of awkward actually, so I was even thinking
about removing it.
Decent editors should probably have a plugin to put the cursor here and
be done with it.
In fact what looks odd is the GIT: stuff. a line looking like:
--- write your message below this line ---
Looks 10x better, though need some code to strip it out if the user kept
it, and I'm lazy, GIT: stuff is automatically removed...
Or, to follow the convention of git-status and git-commit, you could do
this with "# ".
So something like,
--->8---
From: Ian Hilt <redacted>
Date: Fri, 31 Oct 2008 17:55:46 -0400
Subject: [PATCH] Use a hash instead of GIT: for line removal
Signed-off-by: Ian Hilt <redacted>
---
git-send-email.perl | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
@@ -427,7 +427,7 @@ sub get_patch_subject($) {while(my$line=<$fh>){nextunless($line=~ /^Subject: (.*)$/);close$fh;-return"GIT: $1\n";+return"# $1\n";}close$fh;die"No subject line in $fn ?";
@@ -446,14 +446,14 @@ if ($compose) {printC<<EOT;From$tpl_sender# This line is ignored.-GIT:Linesbeginningin"GIT: "willberemoved.-GIT:Considerincludinganoveralldiffstatortableofcontents-GIT:forthepatchyouarewriting.+# Lines beginning in "# " will be removed.+# Consider including an overall diffstat or table of contents+# for the patch you are writing.From:$tpl_senderSubject:$tpl_subjectIn-Reply-To:$tpl_reply_to-GIT:Pleaseenteryouremailbelowthisline.+# --- write your message below this line ---EOTformy$f(@files){
From: Jeff King <hidden> Date: 2016-06-15 22:45:34
On Fri, Oct 31, 2008 at 11:57:10AM +0100, Pierre Habouzit wrote:
+ closedir(DH);
Ugh. This is a great reason to use a scoped variable (like "my $dh),
which will close automatically. Once upon a time I think you _had_ to
use globs for this, but I think it has not been the case for some time
(and I think we only support back to perl 5.6 these days). Can any perl
gurus comment?
-Peff
From: Jeff King <hidden> Date: 2016-06-15 22:45:34
On Fri, Oct 31, 2008 at 05:52:05PM +0100, Pierre Habouzit wrote:
Signed-off-by: Pierre Habouzit <redacted>
---
One can consider to squash that on top of
[off-list ref] to be able to pass
all non path arguments before a possible '--' to git format-patch.
Personally, I think the other patch is not useful without this. I often
pull out funny subsets of patches if I know it is safe to do so (e.g., I
collect small, unrelated bugfixes directly onto a single branch, but I
send them separately).
With this patch, I might even find send-email usable. :)
-Peff
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:34
On Sun, Nov 02, 2008 at 04:35:23AM +0000, Jeff King wrote:
On Fri, Oct 31, 2008 at 05:52:05PM +0100, Pierre Habouzit wrote:
quoted
Signed-off-by: Pierre Habouzit <redacted>
---
One can consider to squash that on top of
[off-list ref] to be able to pass
all non path arguments before a possible '--' to git format-patch.
Personally, I think the other patch is not useful without this. I often
pull out funny subsets of patches if I know it is safe to do so (e.g., I
collect small, unrelated bugfixes directly onto a single branch, but I
send them separately).
With this patch, I might even find send-email usable. :)
Well it still messes the file/reference name conflict with no way to
prevent it because of the backward compatibility, and even if unlikely
it's still possible.
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
From: Jeff King <hidden> Date: 2016-06-15 22:45:34
On Sun, Nov 02, 2008 at 10:39:07AM +0100, Pierre Habouzit wrote:
Well it still messes the file/reference name conflict with no way to
prevent it because of the backward compatibility, and even if unlikely
it's still possible.
Hmm. As Junio mentioned, this is really an easier way of doing:
git format-patch -o tmp "$@"
$EDITOR tmp/*
git send-email tmp
So I guess a wrapper program would suffice, that just called send-email.
But of course then you would have to think of a new name, and explain
the confusion between it and send-email.
-Peff
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:34
On Sun, Nov 02, 2008 at 06:02:21PM +0000, Jeff King wrote:
On Sun, Nov 02, 2008 at 10:39:07AM +0100, Pierre Habouzit wrote:
quoted
Well it still messes the file/reference name conflict with no way to
prevent it because of the backward compatibility, and even if unlikely
it's still possible.
Hmm. As Junio mentioned, this is really an easier way of doing:
git format-patch -o tmp "$@"
$EDITOR tmp/*
git send-email tmp
So I guess a wrapper program would suffice, that just called send-email.
But of course then you would have to think of a new name, and explain
the confusion between it and send-email.
Well that defeats the purpose of fixing send-email to me. I really would
like to see this fixed properly like it should. I mean it makes sense to
me to use _three_ commands where one should be enough. Not to mention
that introducing a new command is just completely against the spirit of
*simplifying* the current UI ;)
Actually I see a few possibilities.
(1) The first one is to pass a --[no]-format-patch flag to
git-send-email which says that it should understand arguments as
format-patch arguments. You add to that a sendemail.format-patch
setting that would default to false for backward compatibility sake,
that would allow the user to force --format-patch as a default.
This would e.g. cleanly allow: git send-email --format-patch -3 HEAD.
I would understand if people dislike the setting: it basically
modifies the behaviour of a git command a lot, which has been
frowned upon in the past. Even though I would argue than using
git-send-email in scripting is quite bad, for something that you can
probably replace with:
while read patchname; do mail some@where.org < $patchname; done < git format-patch "$@"
But if people think it's too dangerous, replacing it with a short
switch so that it's not too painful to use would fly for me,
something like -F or whatever.
(2) Another way is to add a --pass-to-format-patch kind of option that
would take its arguments and pass it to git-format-patch. Like in:
git send-email --pass-to-format-patch "-3 HEAD". (Of course a short
switch would help ;p).
(3) Use -- for mandatory separating <format-patch> arguments like this:
git send-email [send-email options] -- -3 HEAD
or if you want to send patches that would modify only a given path:
git send-email [s-e options] -- origin/next.. -- git-gui
that would run internally:
git format-patch origin/next.. -- git-gui
I would say that I dislike (2) a LOT because it's a pain to use: needs a
lot of quoting, and it gets worse if you want to pass things with spaces
in it to format-patch.
(2) has the small drawback of not being 100% backward compatible: with
the current use of perl Getoptions, -- is used to stop options
processing, and people _may_ have used it to do `git s-e -- --my.patch`
and such a use would break. However this is highly unlikely to cause
issues in real life I think (unlike the problem of refs against filename
clashes).
In (1) people may dislike the idea of a setting, I've not strong
feelings about it, I won't mind if it gets rejected, a short switch will
do just fine then.
As a summary, I'd say that I like both (1) and (3) because those are
handy, short, and either completely or mostly backward compatible. My
way would be to go down (1) and add a alias.s-e = !git send-email -F in
my .gitconfig.
What do you think ?
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:36
[PATCH 1/5] git send-email: make the message file name more specific.
self described
[PATCH 2/5] git send-email: interpret unknown files as revision lists
All unknown arguments are passed to git-format-patch at once,
checking for possible file/rev conflicts and dying in that case,
like Junio suggested.
[PATCH 3/5] git send-email: add --annotate option
same as before.
[PATCH 4/5] git send-email: ask less questions when --compose is used.
same as before, with an update wrt empty bodies. Still doesn't grok
To/Cc/Bcc. I would be really glad if a patch to deal with it was
appended to that series, but a patch that deals with Header
continuations well.
[PATCH 5/5] git send-email: turn --compose on when more than one patch.
This patch is probably controversial. I propose it not because I'm
lazy, I now have a 'git send' alias for the task that expands to
'send-email -C -C -M -n --annotate --compose --to'. I propose it
because I believe it's a good thing to make people write about their
stuff when there is a series and not a single patch. If they still
don't want to, they just have to clear the mail buffer at once.
The drawback is that it _may_ break some scripts, those people would
have to pass --no-compose to their send-email call to fix the
scripts.
I wouldn't complain if the patch gets dropped.
--
·O· Pierre Habouzit
··O madcoder@debian.org
OOO http://www.madism.org
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:36
This helps editors choosing their syntax hilighting properly.
Also make the file live under the git directory.
Signed-off-by: Pierre Habouzit <redacted>
---
git-send-email.perl | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
@@ -124,9 +124,6 @@ my $auth;subunique_email_list(@);subcleanup_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);
@@ -149,6 +146,7 @@ if ($@) {# Behavior modification variablesmy($quiet,$dry_run)=(0,0);+my$compose_filename=$repo->repo_path()."/.gitsendemail.msg.$$";# Variables with corresponding config settingsmy($thread,$chain_reply_to,$suppress_from,$signed_off_by_cc,$cc_cmd);
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:36
Automatically turn --compose on when there is more than one patch, and
that the output is a tty.
Do not print the list of files sent anymore in that case, as the list is
shown in the summary editor.
Signed-off-by: Pierre Habouzit <redacted>
---
git-send-email.perl | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
@@ -237,7 +237,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,"smtp-encryption=s"=>\$smtp_encryption,"identity=s"=>\$identity,"annotate"=>\$annotate,-"compose"=>\$compose,+"compose!"=>\$compose,"quiet"=>\$quiet,"cc-cmd=s"=>\$cc_cmd,"suppress-from!"=>\$suppress_from,
@@ -425,7 +425,11 @@ if ($validate) {}if(@files){-unless($quiet){+if(!defined($compose)&&-tSTDOUT){+# turn $compose on if there is more than one file+$compose=$#files;+}+unless($quiet||$compose){print$_,"\n"for(@files);}}else{
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:36
This allows to review every patch (and fix various aspects of them, or
comment them) in an editor just before being sent. Combined to the fact
that git send-email can now process revision lists, this makes git
send-email and efficient way to review and send patches interactively.
Signed-off-by: Pierre Habouzit <redacted>
---
Documentation/git-send-email.txt | 11 +++++++++++
git-send-email.perl | 26 ++++++++++++++++++++++++--
2 files changed, 35 insertions(+), 2 deletions(-)
@@ -37,6 +37,11 @@ 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.+--annotate::+ Review each patch you're about to send in an editor. The setting+ 'sendemail.multiedit' defines if this will spawn one editor per patch+ or one for all of them at once.+ --compose:: Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an introductory message for the patch series.
@@ -204,6 +209,12 @@ sendemail.aliasfiletype:: Format of the file(s) specified in sendemail.aliasesfile. Must be one of 'mutt', 'mailrc', 'pine', or 'gnus'.+sendemail.multiedit::+ If true (default), a single editor instance will be spawned to edit+ files you have to edit (patches when '--annotate' is used, and the+ summary when '--compose' is used). If false, files will be edited one+ after the other, spawning a new editor each time.+ Author ------
@@ -129,7 +130,8 @@ sub cleanup_compose_files();# 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;
@@ -151,6 +153,17 @@ if ($@) {my($quiet,$dry_run)=(0,0);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";+subdo_edit{+if(defined($multiedit)&&!$multiedit){+map{system('sh','-c',$editor.' "$@"',$editor,$_);}@_;+}else{+system('sh','-c',$editor.' "$@"',$editor,@_);+}+}+# Variables with corresponding config settingsmy($thread,$chain_reply_to,$suppress_from,$signed_off_by_cc,$cc_cmd);my($smtp_server,$smtp_server_port,$smtp_authuser,$smtp_encryption);
@@ -222,6 +236,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,"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,
@@ -515,7 +530,12 @@ EOTclose(C);my$editor=$ENV{GIT_EDITOR}||Git::config(@repo,"core.editor")||$ENV{VISUAL}||$ENV{EDITOR}||"vi";-system('sh','-c',$editor.' "$@"',$editor,$compose_filename);++if($annotate){+do_edit($compose_filename,@files);+}else{+do_edit($compose_filename);+}open(C2,">",$compose_filename.".final")ordie"Failed to open $compose_filename.final : ".$!;
@@ -564,6 +584,8 @@ EOT}@files=($compose_filename.".final",@files);+}elsif($annotate){+do_edit(@files);}# Variables we set as part of the loop over files
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:36
When --compose is used, we can grab the From/Subject/In-Reply-To from the
edited summary, let it be so and don't ask the user silly questions.
The summary templates gets quite revamped, and includes the list of
patches subjects that are going to be sent with this batch.
When having a body full of empty lines, the summary isn't sent. Document
that in the git-send-email manpage fully.
Note: It doesn't deal with To/Cc/Bcc yet.
Signed-off-by: Pierre Habouzit <redacted>
---
Documentation/git-send-email.txt | 9 ++
git-send-email.perl | 177 ++++++++++++++++++++++---------------
2 files changed, 114 insertions(+), 72 deletions(-)
@@ -45,6 +45,15 @@ 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.+++When compose is in used, git send-email gets less interactive will use the+values of the headers you set there. If the body of the email (what you type+after the headers and a blank line) only contains blank (or GIT: prefixed)+lines, the summary won't be sent, but git-send-email will still use the+Headers values if you don't removed them.+++If it wasn't able to see a header in the summary it will ask you about it+interactively after quitting your editor. --from:: Specify the sender of the emails. This will default to
@@ -433,6 +433,108 @@ if (@files) {usage();}+subget_patch_subject($){+my$fn=shift;+open(my$fh,'<',$fn);+while(my$line=<$fh>){+nextunless($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)+ordie"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||'';++printC<<EOT;+From$tpl_sender# This line is ignored.+GIT:Linesbeginningin"GIT: "willberemoved.+GIT:Considerincludinganoveralldiffstatortableofcontents+GIT:forthepatchyouarewriting.+GIT:+GIT:Clearthebodycontentifyoudon'twishtosendasummary.+From:$tpl_sender+Subject:$tpl_subject+In-Reply-To:$tpl_reply_to++EOT+formy$f(@files){+printCget_patch_subject($f);+}+close(C);++my$editor=$ENV{GIT_EDITOR}||Git::config(@repo,"core.editor")||$ENV{VISUAL}||$ENV{EDITOR}||"vi";++if($annotate){+do_edit($compose_filename,@files);+}else{+do_edit($compose_filename);+}++open(C2,">",$compose_filename.".final")+ordie"Failed to open $compose_filename.final : ".$!;++open(C,"<",$compose_filename)+ordie"Failed to open $compose_filename : ".$!;++my$need_8bit_cte=file_has_nonascii($compose_filename);+my$in_body=0;+my$summary_empty=1;+while(<C>){+nextifm/^GIT: /;+if($in_body){+$summary_empty=0unless(/^\n$/);+}elsif(/^\n$/){+$in_body=1;+if($need_8bit_cte){+printC2"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;+}+printC2$_;+}+close(C);+close(C2);++if($summary_empty){+print"Summary email is empty, skpping it\n";+$compose=-1;+}+}elsif($annotate){+do_edit(@files);+}+my$prompting=0;if(!defined$sender){$sender=$repoauthor||$repocommitter||'';
@@ -477,17 +579,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);-lastifdefined$_;-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);
@@ -514,64 +605,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)-ordie"Failed to open for writing $compose_filename: $!";-printC"From $sender # This line is ignored.\n";-printfC"Subject: %s\n\n",$initial_subject;-printfC<<EOT;-GIT:Pleaseenteryouremailbelow.-GIT:Linesbeginningin"GIT: "willberemoved.-GIT:Considerincludinganoveralldiffstatortableofcontents-GIT:forthepatchyouarewriting.--EOT-close(C);--my$editor=$ENV{GIT_EDITOR}||Git::config(@repo,"core.editor")||$ENV{VISUAL}||$ENV{EDITOR}||"vi";--if($annotate){-do_edit($compose_filename,@files);-}else{-do_edit($compose_filename);-}--open(C2,">",$compose_filename.".final")-ordie"Failed to open $compose_filename.final : ".$!;--open(C,"<",$compose_filename)-ordie"Failed to open $compose_filename : ".$!;--my$need_8bit_cte=file_has_nonascii($compose_filename);-my$in_body=0;-while(<C>){-nextifm/^GIT: /;-if(!$in_body&&/^\n$/){-$in_body=1;-if($need_8bit_cte){-printC2"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";-}-printC2$_;-}-close(C);-close(C2);-while(1){$_=$term->readline("Send this email? (y|n) ");lastifdefined$_;
@@ -583,9 +616,9 @@ EOTexit(0);}-@files=($compose_filename.".final",@files);-}elsif($annotate){-do_edit(@files);+if($compose>0){+@files=($compose_filename.".final",@files);+}}# Variables we set as part of the loop over files
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:36
Filter out all the arguments git-send-email doesn't like to a
git format-patch command, that dumps its content to a safe directory.
Barf when a file/revision conflict occurs.
Signed-off-by: Pierre Habouzit <redacted>
---
Documentation/git-send-email.txt | 2 +-
git-send-email.perl | 28 ++++++++++++++++++++++++----
2 files changed, 25 insertions(+), 5 deletions(-)
@@ -363,10 +366,22 @@ if (@alias_files and $aliasfiletype and defined $parse_alias{$aliasfiletype}) {($sender)=expand_aliases($sender)ifdefined$sender;+subcheck_file_rev_conflict($){+my$f=shift;+if($repo->command('rev-parse','--verify','--quiet',$f)){+die("revision/filename conflict on `$f'");+}+}+# 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.-formy$f(@ARGV){-if(-d$f){+my@rev_list_opts;+while(my$f=pop@ARGV){+if($feq"--"){+push@rev_list_opts,"--",@ARGV;+@ARGV=();+}elsif(-d$f){+check_file_rev_conflict($f);opendir(DH,$f)ordie"Failed to opendir $f: $!";
@@ -374,12 +389,17 @@ for my $f (@ARGV) {sortreaddir(DH);closedir(DH);}elsif(-f$for-p$f){+check_file_rev_conflict($f);push@files,$f;}else{-printSTDERR"Skipping $f - not found.\n";+push@rev_list_opts,$f;}}+if(@rev_list_opts){+push@files,$repo->command('format-patch','-o',tempdir(CLEANUP=>1),@rev_list_opts);+}+if($validate){foreachmy$f(@files){unless(-p$f){
@@ -22,8 +22,11 @@ use Term::ReadLine;useGetopt::Long;useData::Dumper;useTerm::ANSIColor;+useFile::Tempqw/ tempdir /;
We seem to use File::Temp::tempdir already elsewhere, but they are in
archimport, cvsexportcommit and cvsserver, all of which are rather rarely
used ones. I think this is Perl 5.6.1 addition. Is everybody Ok with
this dependency? Just double checking.
quoted hunk
@@ -363,10 +366,22 @@ if (@alias_files and $aliasfiletype and defined $parse_alias{$aliasfiletype}) { ($sender) = expand_aliases($sender) if defined $sender;+sub check_file_rev_conflict($) {+ my $f = shift;+ if ($repo->command('rev-parse', '--verify', '--quiet', $f)) {+ die("revision/filename conflict on `$f'");
Perhaps wording this a bit more to the point? This is triggered when
'$f' can be both a filename or a revision, so...
File '$f' exists but it could also be the range of commits
to produce patches for. Please disambiguate by...
* Saying "./$f" if you mean a file; or
* Giving -F option if you mean a range.
Earlier I suggested that "origin^0" is a way for the user to disambiguate
favouring a rev, but such a filename can exist, so we cannot blindly
suggest to say "$f^0" here. I think adding -F (or --format-patch) option
to send-email to explicitly disable file/directory interpretation would be
a cleaner solution for this (and it would allow you to drive this from a
script without worrying about what garbage files you happen to have in the
working tree).
From: Junio C Hamano <hidden> Date: 2016-06-15 22:45:36
Pierre Habouzit [off-list ref] writes:
Automatically turn --compose on when there is more than one patch, and
that the output is a tty.
I do not think this is a good idea. I suspect I am not the only person
who uses "format-patch --cover-letter", edit the files to review and
prepare, and runs send-email to fire them off.
From: Junio C Hamano <hidden> Date: 2016-06-15 22:45:36
Pierre Habouzit [off-list ref] writes:
+ 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
+
Somebody already suggested this but I really think GIT: lines should be at
the end and use '# ' prefix instead.
With the ability to give --cover-letter option to underlying format-patch
do you still need this?
Don't we want to abort the whole process when the user kills the editor
instead of normal exit (iow, do_edit() which is system() reports that the
editor was killed)?
From: Jeff King <hidden> Date: 2016-06-15 22:45:36
On Tue, Nov 04, 2008 at 03:54:54PM -0800, Junio C Hamano wrote:
Pierre Habouzit [off-list ref] writes:
quoted
Automatically turn --compose on when there is more than one patch, and
that the output is a tty.
I do not think this is a good idea. I suspect I am not the only person
who uses "format-patch --cover-letter", edit the files to review and
prepare, and runs send-email to fire them off.
Maybe a config option to turn this behavior on? It seems specific to
different workflows (i.e., whether or not you are using "git send-email
$REVS" or using format-patch first).
-Peff
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:38
The last patch is dropped for now (the automatic --compose stuff)
because I'm not sure which option to add, and that I don't care enough
about it to spend more time on it.
I think I've incorporated most of the stuff people asked about in this
series.
[PATCH 1/4] git send-email: make the message file name more specific.
[PATCH 2/4] git send-email: interpret unknown files as revision lists
[PATCH 3/4] git send-email: add --annotate option
[PATCH 4/4] git send-email: ask less questions when --compose is used.
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:38
When --compose is used, we can grab the From/Subject/In-Reply-To from the
edited summary, let it be so and don't ask the user silly questions.
The summary templates gets quite revamped, and includes the list of
patches subjects that are going to be sent with this batch.
When having a body full of empty lines, the summary isn't sent. Document
that in the git-send-email manpage fully.
Note: It doesn't deal with To/Cc/Bcc yet.
Signed-off-by: Pierre Habouzit <redacted>
---
Documentation/git-send-email.txt | 9 ++
git-send-email.perl | 187 +++++++++++++++++++++++---------------
2 files changed, 123 insertions(+), 73 deletions(-)
@@ -45,6 +45,15 @@ 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.+++When compose is in used, git send-email gets less interactive will use the+values of the headers you set there. If the body of the email (what you type+after the headers and a blank line) only contains blank (or GIT: prefixed)+lines, the summary won't be sent, but git-send-email will still use the+Headers values if you don't removed them.+++If it wasn't able to see a header in the summary it will ask you about it+interactively after quitting your editor. --from:: Specify the sender of the emails. This will default to
@@ -450,6 +458,108 @@ if (@files) {usage();}+subget_patch_subject($){+my$fn=shift;+open(my$fh,'<',$fn);+while(my$line=<$fh>){+nextunless($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)+ordie"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||'';++printC<<EOT;+From$tpl_sender# This line is ignored.+GIT:Linesbeginningin"GIT: "willberemoved.+GIT:Considerincludinganoveralldiffstatortableofcontents+GIT:forthepatchyouarewriting.+GIT:+GIT:Clearthebodycontentifyoudon'twishtosendasummary.+From:$tpl_sender+Subject:$tpl_subject+In-Reply-To:$tpl_reply_to++EOT+formy$f(@files){+printCget_patch_subject($f);+}+close(C);++my$editor=$ENV{GIT_EDITOR}||Git::config(@repo,"core.editor")||$ENV{VISUAL}||$ENV{EDITOR}||"vi";++if($annotate){+do_edit($compose_filename,@files);+}else{+do_edit($compose_filename);+}++open(C2,">",$compose_filename.".final")+ordie"Failed to open $compose_filename.final : ".$!;++open(C,"<",$compose_filename)+ordie"Failed to open $compose_filename : ".$!;++my$need_8bit_cte=file_has_nonascii($compose_filename);+my$in_body=0;+my$summary_empty=1;+while(<C>){+nextifm/^GIT: /;+if($in_body){+$summary_empty=0unless(/^\n$/);+}elsif(/^\n$/){+$in_body=1;+if($need_8bit_cte){+printC2"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;+}+printC2$_;+}+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||'';
@@ -494,17 +604,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);-lastifdefined$_;-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);
@@ -531,64 +630,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)-ordie"Failed to open for writing $compose_filename: $!";-printC"From $sender # This line is ignored.\n";-printfC"Subject: %s\n\n",$initial_subject;-printfC<<EOT;-GIT:Pleaseenteryouremailbelow.-GIT:Linesbeginningin"GIT: "willberemoved.-GIT:Considerincludinganoveralldiffstatortableofcontents-GIT:forthepatchyouarewriting.--EOT-close(C);--my$editor=$ENV{GIT_EDITOR}||Git::config(@repo,"core.editor")||$ENV{VISUAL}||$ENV{EDITOR}||"vi";--if($annotate){-do_edit($compose_filename,@files);-}else{-do_edit($compose_filename);-}--open(C2,">",$compose_filename.".final")-ordie"Failed to open $compose_filename.final : ".$!;--open(C,"<",$compose_filename)-ordie"Failed to open $compose_filename : ".$!;--my$need_8bit_cte=file_has_nonascii($compose_filename);-my$in_body=0;-while(<C>){-nextifm/^GIT: /;-if(!$in_body&&/^\n$/){-$in_body=1;-if($need_8bit_cte){-printC2"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";-}-printC2$_;-}-close(C);-close(C2);-while(1){$_=$term->readline("Send this email? (y|n) ");lastifdefined$_;
@@ -600,9 +641,9 @@ EOTexit(0);}-@files=($compose_filename.".final",@files);-}elsif($annotate){-do_edit(@files);+if($compose>0){+@files=($compose_filename.".final",@files);+}}# Variables we set as part of the loop over files
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:38
This helps editors choosing their syntax hilighting properly.
Also make the file live under the git directory.
Signed-off-by: Pierre Habouzit <redacted>
---
git-send-email.perl | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
@@ -124,9 +124,6 @@ my $auth;subunique_email_list(@);subcleanup_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);
@@ -149,6 +146,7 @@ if ($@) {# Behavior modification variablesmy($quiet,$dry_run)=(0,0);+my$compose_filename=$repo->repo_path()."/.gitsendemail.msg.$$";# Variables with corresponding config settingsmy($thread,$chain_reply_to,$suppress_from,$signed_off_by_cc,$cc_cmd);
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:38
This allows to review every patch (and fix various aspects of them, or
comment them) in an editor just before being sent. Combined to the fact
that git send-email can now process revision lists, this makes git
send-email and efficient way to review and send patches interactively.
Signed-off-by: Pierre Habouzit <redacted>
---
Documentation/git-send-email.txt | 11 +++++++++++
git-send-email.perl | 26 ++++++++++++++++++++++++--
2 files changed, 35 insertions(+), 2 deletions(-)
@@ -37,6 +37,11 @@ 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.+--annotate::+ Review each patch you're about to send in an editor. The setting+ 'sendemail.multiedit' defines if this will spawn one editor per patch+ or one for all of them at once.+ --compose:: Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an introductory message for the patch series.
@@ -210,6 +215,12 @@ sendemail.aliasfiletype:: Format of the file(s) specified in sendemail.aliasesfile. Must be one of 'mutt', 'mailrc', 'pine', or 'gnus'.+sendemail.multiedit::+ If true (default), a single editor instance will be spawned to edit+ files you have to edit (patches when '--annotate' is used, and the+ summary when '--compose' is used). If false, files will be edited one+ after the other, spawning a new editor each time.+ Author ------
@@ -132,7 +133,8 @@ sub cleanup_compose_files();# 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;
@@ -155,6 +157,17 @@ 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";+subdo_edit{+if(defined($multiedit)&&!$multiedit){+map{system('sh','-c',$editor.' "$@"',$editor,$_);}@_;+}else{+system('sh','-c',$editor.' "$@"',$editor,@_);+}+}+# Variables with corresponding config settingsmy($thread,$chain_reply_to,$suppress_from,$signed_off_by_cc,$cc_cmd);my($smtp_server,$smtp_server_port,$smtp_authuser,$smtp_encryption);
@@ -226,6 +240,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,"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,
@@ -532,7 +547,12 @@ EOTclose(C);my$editor=$ENV{GIT_EDITOR}||Git::config(@repo,"core.editor")||$ENV{VISUAL}||$ENV{EDITOR}||"vi";-system('sh','-c',$editor.' "$@"',$editor,$compose_filename);++if($annotate){+do_edit($compose_filename,@files);+}else{+do_edit($compose_filename);+}open(C2,">",$compose_filename.".final")ordie"Failed to open $compose_filename.final : ".$!;
@@ -581,6 +601,8 @@ EOT}@files=($compose_filename.".final",@files);+}elsif($annotate){+do_edit(@files);}# Variables we set as part of the loop over files
From: Pierre Habouzit <hidden> Date: 2016-06-15 22:45:38
Filter out all the arguments git-send-email doesn't like to a
git format-patch command, that dumps its content to a safe directory.
Barf when a file/revision conflict occurs, allow it to be overriden
--[no-]format-patch.
Signed-off-by: Pierre Habouzit <redacted>
---
Documentation/git-send-email.txt | 8 +++++-
git-send-email.perl | 47 +++++++++++++++++++++++++++++++++----
t/t9001-send-email.sh | 8 ++++++
3 files changed, 57 insertions(+), 6 deletions(-)
@@ -8,7 +8,7 @@ git-send-email - Send a collection of patches as emails SYNOPSIS ---------'git send-email' [options] <file|directory> [... file|directory]+'git send-email' [options] <file|directory|rev-list options>... DESCRIPTION
@@ -183,6 +183,12 @@ Administering --[no-]validate:: Perform sanity checks on patches. Currently, validation means the following:++--[no-]format-patch::+ When an argument may be understood either as a reference or as a file name,+ choose to understand it as a format-patch argument ('--format-patch')+ or as a file name ('--no-format-patch'). By default, when such a conflict+ occurs, git send-email will fail. + -- * Warn of patches that contain lines longer than 998 characters; this
@@ -146,6 +152,7 @@ if ($@) {# Behavior modification variablesmy($quiet,$dry_run)=(0,0);+my$format_patch;my$compose_filename=$repo->repo_path()."/.gitsendemail.msg.$$";# Variables with corresponding config settings
@@ -229,6 +236,7 @@ my $rc = GetOptions("sender|from=s" => \$sender,"envelope-sender=s"=>\$envelope_sender,"thread!"=>\$thread,"validate!"=>\$validate,+"format-patch!"=>\$format_patch,);unless($rc){
@@ -363,23 +371,52 @@ if (@alias_files and $aliasfiletype and defined $parse_alias{$aliasfiletype}) {($sender)=expand_aliases($sender)ifdefined$sender;+# returns 1 if the conflict must be solved using it as a format-patch argument+subcheck_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(<<EOF);+File'$f'existsbutitcouldalsobetherangeofcommits+toproducepatchesfor.Pleasedisambiguateby...++*Saying"./$f"ifyoumeanafile;or+*Giving--format-patchoptionifyoumeanarange.+EOF+}catchGit::Error::Commandwith{+return0;+}+}+# 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.-formy$f(@ARGV){-if(-d$f){+my@rev_list_opts;+while(my$f=pop@ARGV){+if($feq"--"){+push@rev_list_opts,"--",@ARGV;+@ARGV=();+}elsif(-d$fand!check_file_rev_conflict($f)){opendir(DH,$f)ordie"Failed to opendir $f: $!";push@files,grep{-f$_}map{+$f."/".$_}sortreaddir(DH);closedir(DH);-}elsif(-f$for-p$f){+}elsif((-f$for-p$f)and!check_file_rev_conflict($f)){push@files,$f;}else{-printSTDERR"Skipping $f - not found.\n";+push@rev_list_opts,$f;}}+if(@rev_list_opts){+push@files,$repo->command('format-patch','-o',tempdir(CLEANUP=>1),@rev_list_opts);+}+if($validate){foreachmy$f(@files){unless(-p$f){