My flow looks like this: 1. git format-patch -v<n> --cover-letter <params> -o <dir> 2. vi <dir>/v<n-1>-0000-cover-letter.patch <dir>/v<n>-0000-cover-letter.patch copy subject and blurb, avoiding patchset stats 3. add changelog update blurb as appropriate 4. git send-email <dir>/v<n>-* The following perl script automates step 2 above. Hacked together rather quickly, so I'm only proposing it for contrib for now. If others see the need, we can add docs, tests and move it to git proper. Signed-off-by: Michael S. Tsirkin <mst@xxxxxxxxxx> --- Fixes from v1: support multi-line To/Cc headers. Any feedback on this? Interest in taking this into contrib/ for now? contrib/git-cpcover | 84 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100755 contrib/git-cpcover diff --git a/contrib/git-cpcover b/contrib/git-cpcover new file mode 100755 index 0000000000..fe7006a56d --- /dev/null +++ b/contrib/git-cpcover @@ -0,0 +1,84 @@ +#!/usr/bin/perl -i + +use strict; + +die "Usage: ${0} <from> [<to>]" unless $#ARGV == 0 or $#ARGV == 1; + +my $ffrom = shift @ARGV; +my @extraheaders = (); + +open(FROM, "<", $ffrom) || die "Can not open $ffrom"; + +my @from = (); +while (<FROM>) { + push @from, $_; +} + +close(FROM) || die "error closing $ffrom"; + +#get subject +my $subj; +my $bodyi; +my $lastheader=""; +for (my $i = 0; $i <= $#from; $i++) { + $_ = $from[$i]; + #print STDERR "<$line>\n"; + if (not defined ($subj) and s/^Subject: \[[^]]+\] //) { + $subj = $_; + chomp $subj; + } + if (m/^([A-Za-z0-9-_]*:)/) { + $lastheader = $1; + } + if (m/^(To|Cc):/ or (m/^\s/ and $lastheader =~ m/^(To|Cc):/)) { + push @extraheaders, $from[$i]; + } + if (defined ($subj) and m/^$/) { + $bodyi = $i + 1; + last; + } +} + +die "No subject found in $ffrom" unless defined($subj); + +die "No body found in $ffrom" unless defined($bodyi); + +my $bodyl; +my $statb; +my $state; +for (my $i = $#from; $i >= $bodyi; $i--) { + $_ = $from[$i]; + $statb = $i if m/ [0-9]+ files changed, [0-9]+ insertions\(\+\), [0-9]+ deletions\(-\)/; + next unless defined($statb); + $state = $i if m/^$/; + next unless defined($state); + next if m/^$/; + next if m/^ [^ ]/; + next if m/\([0-9]+\):$/; + $bodyl = $i; + last; +} + +die "No body found in $ffrom" unless defined($bodyl); + +#print STDERR $bodyi, "-", $bodyl, "\n"; +my $blurb = join("", @from[$bodyi..$bodyl]); + +my $gotsubj = 0; +my $gotblurb = 0; +my $gotendofheaders = 0; +while (<>) { + if (not $gotsubj and + s/\*\*\* SUBJECT HERE \*\*\*/$subj/) { + $gotsubj = 1; + } + if (not $gotblurb and + s/\*\*\* BLURB HERE \*\*\*/$blurb/) { + $gotblurb = 1; + } + if (not $gotendofheaders and m/^$/) { + print join("", @extraheaders); + $gotendofheaders = 1; + } + print $_; +} -- MST