3 # Copyright (c) 2005 Junio C Hamano
6 USAGE
='[-n | -k] [-o <dir> | --stdout] [--signoff] [--check] [--mbox] [--diff-options] <upstream> [<our-head>]'
7 LONG_USAGE
='Prepare each commit with its patch since our-head forked from upstream,
8 one file per patch, for e-mail submission. Each output file is
9 numbered sequentially from 1, and uses the first line of the commit
10 message (massaged for pathname safety) as the filename.
12 There are three output modes. By default, output files are created in
13 the current working directory; when -o is specified, they are created
14 in that directory instead; when --stdout is specified, they are spit
15 on standard output, and can be piped to git-am.
17 When -n is specified, instead of "[PATCH] Subject", the first line is formatted
18 as "[PATCH N/M] Subject", unless you have only one patch.
20 When --mbox is specified, the output is formatted to resemble
21 UNIX mailbox format, and can be concatenated together for processing
25 # Force diff to run in C locale.
34 while case "$#" in 0) break;; esac
37 -a|
--a|
--au|
--aut|
--auth|
--autho|
--author)
39 -c|
--c|
--ch|
--che|
--chec|
--check)
41 -d|
--d|
--da|
--dat|
--date)
43 -m|
--m|
--mb|
--mbo|
--mbox)
44 date=t author
=t mbox
=t
;;
45 -k|
--k|
--ke|
--kee|
--keep|
--keep-|
--keep-s|
--keep-su|
--keep-sub|\
46 --keep-subj|
--keep-subje|
--keep-subjec|
--keep-subject)
48 -n|
--n|
--nu|
--num|
--numb|
--numbe|
--number|
--numbere|
--numbered)
50 -s|
--s|
--si|
--sig|
--sign|
--signo|
--signof|
--signoff)
52 --st|
--std|
--stdo|
--stdou|
--stdout)
53 stdout
=t mbox
=t
date=t author
=t
;;
54 -o=*|
--o=*|
--ou=*|
--out=*|
--outp=*|
--outpu=*|
--output=*|
--output-=*|\
55 --output-d=*|
--output-di=*|
--output-dir=*|
--output-dire=*|\
56 --output-direc=*|
--output-direct=*|
--output-directo=*|\
57 --output-director=*|
--output-directory=*)
58 outdir
=`expr "$1" : '-[^=]*=\(.*\)'` ;;
59 -o|
--o|
--ou|
--out|
--outp|
--outpu|
--output|
--output-|
--output-d|\
60 --output-di|
--output-dir|
--output-dire|
--output-direc|
--output-direct|\
61 --output-directo|
--output-director|
--output-directory)
62 case "$#" in 1) usage
;; esac; shift
64 -h|
--h|
--he|
--hel|
--help)
67 -*' '* |
-*"$LF"* |
-*' '*)
68 # Ignore diff option that has whitespace for now.
70 -*) diff_opts
="$diff_opts$1 " ;;
76 case "$keep_subject$numbered" in
78 die
'--keep-subject and --numbered are incompatible.' ;;
82 trap 'rm -f $tmp-*' 0 1 2 3 15
88 # Backward compatible argument parsing hack.
90 # Historically, we supported:
91 # 1. "rev1" is equivalent to "rev1..HEAD"
93 # 3. "rev1" "rev2 is equivalent to "rev1..rev2"
95 # We want to take a sequence of "rev1..rev2" in general.
96 # Also, "rev1.." should mean "rev1..HEAD"; git-diff users are
97 # familiar with that syntax.
101 # single "rev1..rev2"
104 # single "rev1.." should mean "rev1..HEAD"
114 # not traditional "rev1" "rev2"
122 # Now we have what we want in $@
127 rev1
=`expr "$revpair" : '\(.*\)\.\.'`
128 rev2
=`expr "$revpair" : '.*\.\.\(.*\)'`
135 git-rev-parse
--verify "$rev1^0" >/dev
/null
2>&1 ||
136 die
"Not a valid rev $rev1 ($revpair)"
137 git-rev-parse
--verify "$rev2^0" >/dev
/null
2>&1 ||
138 die
"Not a valid rev $rev2 ($revpair)"
139 git-cherry
-v "$rev1" "$rev2" |
140 while read sign
rev comment
144 echo >&2 "Merged already: $comment"
153 me
=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'`
157 *) outdir
="$outdir/" ;;
159 test -d "$outdir" || mkdir
-p "$outdir" ||
exit
164 s/^\[PATCH[^]]*\] *//
165 s/[^-a-z.A-Z_0-9]/-/g
178 s/'\''/'\''\\'\'\''/g
179 s/author \(.*>\) \(.*\)$/au='\''\1'\'' ad='\''\2'\''/p
187 case "$keep_subject" in
190 mailScript
="$mailScript"'
191 s|^\[PATCH[^]]*\] *||
192 s|^|[PATCH'"$num"'] |'
195 mailScript
="$mailScript"'
199 echo 'From nobody Mon Sep 17 00:00:00 2001' ;# UNIX "From" line
203 eval "$(sed -ne "$whosepatchScript" $commsg)"
204 test "$author,$au" = ",$me" ||
{
205 mailScript
="$mailScript"'
209 test "$date,$au" = ",$me" ||
{
210 mailScript
="$mailScript"'
215 mailScript
="$mailScript"'
223 (cat $commsg ; echo; echo) |
224 sed -ne "$mailScript" |
227 test "$signoff" = "t" && {
228 offsigner
=`git-var GIT_COMMITTER_IDENT | sed -e 's/>.*/>/'`
229 line
="Signed-off-by: $offsigner"
230 grep -q "^$line\$" $commsg ||
{
239 git-diff-tree
-p $diff_opts "$commit" | git-apply
--stat --summary
241 git-diff-tree
-p $diff_opts "$commit"
243 echo "@@GIT_VERSION@@"
252 total
=`wc -l <$series | tr -dc "[0-9]"`
253 case "$total,$numbered" in
257 numfmt
=`echo "$total" | wc -c`
258 numfmt
=$
(($numfmt-1))
259 numfmt
=" %0${numfmt}d/$total"
265 git-cat-file commit
"$commit" | git-stripspace
>$commsg
266 title
=`sed -ne "$titleScript" <$commsg`
270 num
=`printf "$numfmt" $i` ;;
273 file=`printf '%04d-%stxt' $i "$title"`
274 if test '' = "$stdout"
277 process_one
>"$outdir$file"
280 # This is slightly modified from Andrew Morton's Perfect Patch.
281 # Lines you introduce should not have trailing whitespace.
282 # Also check for an indentation that has SP before a TAB.
283 grep -n '^+\([ ]* .*\|.*[ ]\)$' "$outdir$file"