threads / patch / 897

patchAdd script for patch submission via e-mail.

Subject: [PATCH] Add script for patch submission via e-mail.

## tl;dr

6 messages between Jun 11, 2005 and Jul 5, 2005. Diffs are folded; open one to read it.

replies: 5people: 3as markdown or json

Junio C Hamano· Jun 11, 2005, 01:32 UTC · lore

This git-format-patch-script is what I use to prepare patches for e-mail submission.

Typical usage is:
$ git-format-patch-script -B -C --find-copies-harder HEAD linus

to prepare each commit with its patch since "HEAD" forked from "linus", one file per patch for e-mail submission. Each output file is numbered sequentially from 1, and uses the first line of the commit message (massaged for pathname safety) as the filename.

$ git-format-patch-script -B -C --find-copies-harder HEAD linus .patch/
creates output files in .patch/ directory.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
*** Linus I am submitting this one because some patches on
*** read-tree I am going to send you will need this for
*** formatting into a form that is easier to review.  And this
*** in turn can use diff-tree --find-copies-harder, which I
*** indeed used to generate the patches that follow.
 Makefile                |    3 +-
 git-format-patch-script |   93 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+), 1 deletions(-)
Show changes to 2 files +95 −1

Makefile, git-format-patch-script

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,8 @@ INSTALL=install
 SCRIPTS=git git-apply-patch-script git-merge-one-file-script git-prune-script \
 	git-pull-script git-tag-script git-resolve-script git-whatchanged \
 	git-deltafy-script git-fetch-script git-status-script git-commit-script \
-	git-log-script git-shortlog git-cvsimport-script
+	git-log-script git-shortlog git-cvsimport-script \
+	git-format-patch-script
 
 PROG=   git-update-cache git-diff-files git-init-db git-write-tree \
 	git-read-tree git-commit-tree git-cat-file git-fsck-cache \
diff --git a/git-format-patch-script b/git-format-patch-script
new file mode 100755
--- /dev/null
+++ b/git-format-patch-script
@@ -0,0 +1,93 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+#
+# Typical usage is:
+#
+# $ git-format-patch-script -B -C --find-copies-harder HEAD linus
+#
+# to prepare each commit with its patch since "HEAD" forked from
+# "linus", one file per patch for e-mail submission.  Each output file is
+# numbered sequentially from 1, and uses the first line of the commit
+# message (massaged for pathname safety) as the filename.
+#
+# $ git-format-patch-script -B -C --find-copies-harder HEAD linus .patch/
+#
+# creates output files in .patch/ directory.
+
+diff_opts=
+IFS='
+'
+LF='
+'
+while case "$#" in 0) break;; esac
+do
+    case "$1" in
+    -*)	diff_opts="$diff_opts$LF$1" ;;
+    *) break ;;
+    esac
+    shift
+done
+
+junio="$1"
+linus="$2"
+outdir="${3:-./}"
+
+tmp=.tmp-series$$
+trap 'rm -f $tmp-*' 0 1 2 3 15
+
+series=$tmp-series
+
+titleScript='
+	1,/^$/d
+	: loop
+	/^$/b loop
+	s/[^-a-z.A-Z_0-9]/-/g
+	s/^--*//g
+	s/--*$//g
+	s/---*/-/g
+	s/$/.txt/
+        s/\.\.\.*/\./g
+	q
+'
+
+_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
+_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
+stripCommitHead='/^'"$_x40"' (from '"$_x40"')$/d'
+
+O=
+if test -f .git/patch-order
+then
+    O=-O.git/patch-order
+fi
+git-rev-list "$junio" "^$linus" >$series
+total=`wc -l <$series`
+i=$total
+while read commit
+do
+    title=`git-cat-file commit "$commit" | sed -e "$titleScript"`
+    num=`printf "%d/%d" $i $total`
+    file=`printf '%04d-%s' $i "$title"`
+    i=`expr "$i" - 1`
+    echo "$file"
+    {
+	mailScript='
+	1,/^$/d
+	: loop
+	/^$/b loop
+	s|^|[PATCH '"$num"'] |
+	: body
+	p
+	n
+	b body'
+
+	git-cat-file commit "$commit" | sed -ne "$mailScript"
+	echo '---'
+	echo
+	git-diff-tree -p $diff_opts $O "$commit" | git-apply --stat
+	echo
+	git-diff-tree -p $diff_opts $O "$commit" | sed -e "$stripCommitHead"
+	echo '------------'
+    } >"$outdir$file"
+done <$series
+
------------
Petr Baudis· Jul 5, 2005, 09:34 UTC · re: Junio C Hamano · lore

Re: [PATCH] Add script for patch submission via e-mail.

Dear diary, on Sat, Jun 11, 2005 at 03:32:30AM CEST, I got a letter where Junio C Hamano <junkio@cox.net> told me that...

Show 24 quoted lines
> This git-format-patch-script is what I use to prepare patches
> for e-mail submission.
> 
> Typical usage is:
> 
> $ git-format-patch-script -B -C --find-copies-harder HEAD linus
> 
> to prepare each commit with its patch since "HEAD" forked from
> "linus", one file per patch for e-mail submission.  Each output
> file is numbered sequentially from 1, and uses the first line of
> the commit message (massaged for pathname safety) as the
> filename.
> 
> $ git-format-patch-script -B -C --find-copies-harder HEAD linus .patch/
> 
> creates output files in .patch/ directory.
> 
> Signed-off-by: Junio C Hamano <junkio@cox.net>
> ---
> *** Linus I am submitting this one because some patches on
> *** read-tree I am going to send you will need this for
> *** formatting into a form that is easier to review.  And this
> *** in turn can use diff-tree --find-copies-harder, which I
> *** indeed used to generate the patches that follow.

Any reason why this was not applied? It appears kind of cool. Well, I will probably take it and extend cg-mkpatch with it so I don't need it in Git, but I'm so altruistic and want to bring at least a bit of light to the gloomy dark world of the poor core Git plumbing users. ;-)

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
<Espy> be careful, some twit might quote you out of context..
Jon Seymour· Jul 5, 2005, 09:39 UTC · re: Petr Baudis · lore

Re: [PATCH] Add script for patch submission via e-mail.

On 7/5/05, Petr Baudis <pasky@suse.cz> wrote:
Show 5 quoted lines
> 
> Any reason why this was not applied? It appears kind of cool. Well, I
> will probably take it and extend cg-mkpatch with it so I don't need it
> in Git, but I'm so altruistic and want to bring at least a bit of light
> to the gloomy dark world of the poor core Git plumbing users.  ;-)
As one who inhabits that dark world, I second that!
jon.
Junio C Hamano· Jul 5, 2005, 15:20 UTC · re: Petr Baudis · lore

Re: [PATCH] Add script for patch submission via e-mail.

>>>>> "PB" == Petr Baudis <pasky@suse.cz> writes:
PB> Any reason why this was not applied? It appears kind of cool.

FYI, the one in <7vll4s47p3.fsf_-_@assigned-by-dhcp.cox.net> is newer than what you quoted.

One thing _I_ am unhappy about what it does is that it does not try to be intelligent about merges (I haven't tried the script on a merged head myself).

When you think about "project lead" vs "individual developer" modes of operation, the latter is primarily "keep rebasing commits in my fork and re-throwing them upstream until some of them stick", so not supporting merges specially would not be so big a flaw. However, at least it should use --merge-order to get the epochs decomposed right, in order to produce anything remotely useful when dealing with a merged head.

Jon Seymour· Jul 5, 2005, 16:18 UTC · re: Junio C Hamano · lore

Re: [PATCH] Add script for patch submission via e-mail.

On 7/6/05, Junio C Hamano <junkio@cox.net> wrote:
Show 10 quoted lines
> >>>>> "PB" == Petr Baudis <pasky@suse.cz> writes:
> 
> PB> Any reason why this was not applied? It appears kind of cool.
> 
> FYI, the one in <7vll4s47p3.fsf_-_@assigned-by-dhcp.cox.net> is
> newer than what you quoted.
> 
> One thing _I_ am unhappy about what it does is that it does not
> try to be intelligent about merges (I haven't tried the script
> on a merged head myself).

I am not completely sure this is really a problem. I would presume that the project lead doesn't really need to use git-format-patch-script and the individual developer should probably rebase on the latest head which is either done by trivially reapplying the patches in sequence automatically or reapplying the patches in sequence with some edits to fix any conflicts that have arisen.

So, it is not clear to me git-format-patch-script needs to worry about merge questions. It'd be better to put such logic in a separate rebasing script, I think. If anything, you might want to add checks to git-format-patch script that refuse to generate a patch sequence for any sequence of patches that spans a merge commit.

jon.
-- 
homepage: http://www.zeta.org.au/~jon/
blog: http://orwelliantremors.blogspot.com/
Junio C Hamano· Jul 5, 2005, 20:19 UTC · re: Petr Baudis · lore
[PATCH] git-format-patch: Prepare patches for e-mail submission.
This is the script I use to prepare patches for e-mail submission.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---

*** The latest incarnation. Uses --merge-order while generating *** the list of patches to number them better.

 Makefile                |    3 +
 git-format-patch-script |  121 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+), 1 deletions(-)
 create mode 100755 git-format-patch-script
1a3c4d6335860c7bfd09b997b19c850620c6fb50
Show changes to 2 files +123 −1

Makefile, git-format-patch-script

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -31,7 +31,8 @@ SCRIPTS=git git-apply-patch-script git-m
 	git-fetch-script git-status-script git-commit-script \
 	git-log-script git-shortlog git-cvsimport-script git-diff-script \
 	git-reset-script git-add-script git-checkout-script git-clone-script \
-	gitk git-cherry git-rebase-script git-relink-script git-repack-script
+	gitk git-cherry git-rebase-script git-relink-script git-repack-script \
+	git-format-patch-script
 
 PROG=   git-update-cache git-diff-files git-init-db git-write-tree \
 	git-read-tree git-commit-tree git-cat-file git-fsck-cache \
diff --git a/git-format-patch-script b/git-format-patch-script
new file mode 100755
--- /dev/null
+++ b/git-format-patch-script
@@ -0,0 +1,121 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+#
+
+usage () {
+    echo >&2 "usage: $0"' [-n] [-o dir] [-<diff options>...] upstream [ our-head ]
+
+Prepare each commit with its patch since our-head forked from upstream,
+one file per patch, for e-mail submission.  Each output file is
+numbered sequentially from 1, and uses the first line of the commit
+message (massaged for pathname safety) as the filename.
+
+When -o is specified, output files are created in that directory; otherwise in
+the current working directory.
+
+When -n is specified, instead of "[PATCH] Subject", the first line is formatted
+as "[PATCH N/M] Subject", unless you have only one patch.
+'
+    exit 1
+}
+
+diff_opts=
+IFS='
+'
+LF='
+'
+outdir=./
+
+while case "$#" in 0) break;; esac
+do
+    case "$1" in
+    -n|--n|--nu|--num|--numb|--numbe|--number|--numbere|--numbered)
+    numbered=t ;;
+    -o=*|--o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*|--output-=*|\
+    --output-d=*|--output-di=*|--output-dir=*|--output-dire=*|\
+    --output-direc=*|--output-direct=*|--output-directo=*|\
+    --output-director=*|--output-directory=*)
+    outdir=`expr "$1" : '-[^=]*=\(.*\)'` ;;
+    -o|--o|--ou|--out|--outp|--outpu|--output|--output-|--output-d|\
+    --output-di|--output-dir|--output-dire|--output-direc|--output-direct|\
+    --output-directo|--output-director|--output-directory)
+    case "$#" in 1) usage ;; esac; shift
+    outdir="$1" ;;
+    -*)	diff_opts="$diff_opts$LF$1" ;;
+    *) break ;;
+    esac
+    shift
+done
+
+case "$#" in
+2)    linus="$1" junio="$2" ;;
+1)    linus="$1" junio=HEAD ;;
+*)    usage ;;
+esac
+
+case "$outdir" in
+*/) ;;
+*) outdir="$outdir/" ;;
+esac
+test -d "$outdir" || mkdir -p "$outdir" || exit
+
+tmp=.tmp-series$$
+trap 'rm -f $tmp-*' 0 1 2 3 15
+
+series=$tmp-series
+
+titleScript='
+	1,/^$/d
+	: loop
+	/^$/b loop
+	s/[^-a-z.A-Z_0-9]/-/g
+        s/\.\.\.*/\./g
+	s/\.*$//
+	s/--*/-/g
+	s/^-//
+	s/-$//
+	s/$/./
+	q
+'
+
+_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
+_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
+stripCommitHead='/^'"$_x40"' (from '"$_x40"')$/d'
+
+git-rev-list --merge-order "$junio" "^$linus" >$series
+total=`wc -l <$series`
+i=$total
+while read commit
+do
+    title=`git-cat-file commit "$commit" | sed -e "$titleScript"`
+    case "$numbered" in
+    '') num= ;;
+    *)
+	case $total in
+	1) num= ;;
+	*) num=' '`printf "%d/%d" $i $total` ;;
+	esac
+    esac
+    file=`printf '%04d-%stxt' $i "$title"`
+    i=`expr "$i" - 1`
+    echo "$file"
+    {
+	mailScript='
+	1,/^$/d
+	: loop
+	/^$/b loop
+	s|^|[PATCH'"$num"'] |
+	: body
+	p
+	n
+	b body'
+
+	git-cat-file commit "$commit" | sed -ne "$mailScript"
+	echo '---'
+	echo
+	git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
+	echo
+	git-diff-tree -p $diff_opts "$commit" | sed -e "$stripCommitHead"
+    } >"$outdir$file"
+done <$series

← back to recent threads