Add -v option to git-cherry.
[git.git] / git-format-patch-script
1 #!/bin/sh
2 #
3 # Copyright (c) 2005 Junio C Hamano
4 #
5
6 . git-sh-setup-script || die "Not a git archive."
7
8 usage () {
9     echo >&2 "usage: $0"' [-n] [-o dir] [--mbox] [--check] [-<diff options>...] upstream [ our-head ]
10
11 Prepare each commit with its patch since our-head forked from upstream,
12 one file per patch, for e-mail submission.  Each output file is
13 numbered sequentially from 1, and uses the first line of the commit
14 message (massaged for pathname safety) as the filename.
15
16 When -o is specified, output files are created in that directory; otherwise in
17 the current working directory.
18
19 When -n is specified, instead of "[PATCH] Subject", the first line is formatted
20 as "[PATCH N/M] Subject", unless you have only one patch.
21
22 When --mbox is specified, the output is formatted to resemble
23 UNIX mailbox format, and can be concatenated together for processing
24 with applymbox.
25 '
26     exit 1
27 }
28
29 diff_opts=
30 IFS='
31 '
32 LF='
33 '
34
35 outdir=./
36 while case "$#" in 0) break;; esac
37 do
38     case "$1" in
39     -a|--a|--au|--aut|--auth|--autho|--author)
40     author=t ;;
41     -c|--c|--ch|--che|--chec|--check)
42     check=t ;;
43     -d|--d|--da|--dat|--date)
44     date=t ;;
45     -m|--m|--mb|--mbo|--mbox)
46     date=t author=t mbox=t ;;
47     -n|--n|--nu|--num|--numb|--numbe|--number|--numbere|--numbered)
48     numbered=t ;;
49     -o=*|--o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*|--output-=*|\
50     --output-d=*|--output-di=*|--output-dir=*|--output-dire=*|\
51     --output-direc=*|--output-direct=*|--output-directo=*|\
52     --output-director=*|--output-directory=*)
53     outdir=`expr "$1" : '-[^=]*=\(.*\)'` ;;
54     -o|--o|--ou|--out|--outp|--outpu|--output|--output-|--output-d|\
55     --output-di|--output-dir|--output-dire|--output-direc|--output-direct|\
56     --output-directo|--output-director|--output-directory)
57     case "$#" in 1) usage ;; esac; shift
58     outdir="$1" ;;
59     -*) diff_opts="$diff_opts$LF$1" ;;
60     *) break ;;
61     esac
62     shift
63 done
64
65 revpair=
66 case "$#" in
67 2)
68     revpair="$1..$2" ;;
69 1)
70     case "$1" in
71     *..*)
72         revpair="$1";;
73     *)
74         revpair="$1..HEAD";;
75     esac ;;
76 *)
77     usage ;;
78 esac
79
80 me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'`
81
82 case "$outdir" in
83 */) ;;
84 *) outdir="$outdir/" ;;
85 esac
86 test -d "$outdir" || mkdir -p "$outdir" || exit
87
88 tmp=.tmp-series$$
89 trap 'rm -f $tmp-*' 0 1 2 3 15
90
91 series=$tmp-series
92 commsg=$tmp-commsg
93 filelist=$tmp-files
94
95 titleScript='
96         /./d
97         /^$/n
98         s/^\[PATCH[^]]*\] *//
99         s/[^-a-z.A-Z_0-9]/-/g
100         s/\.\.\.*/\./g
101         s/\.*$//
102         s/--*/-/g
103         s/^-//
104         s/-$//
105         s/$/./
106         p
107         q
108 '
109
110 whosepatchScript='
111 /^author /{
112         s/author \(.*>\) \(.*\)$/au='\''\1'\'' ad='\''\2'\''/p
113         q
114 }'
115
116 _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
117 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
118 stripCommitHead='/^'"$_x40"' (from '"$_x40"')$/d'
119
120 git-rev-list --merge-order $(git-rev-parse --revs-only "$revpair") >$series
121 total=`wc -l <$series | tr -dc "[0-9]"`
122 i=$total
123 while read commit
124 do
125     git-cat-file commit "$commit" | git-stripspace >$commsg
126     title=`sed -ne "$titleScript" <$commsg`
127     case "$numbered" in
128     '') num= ;;
129     *)
130         case $total in
131         1) num= ;;
132         *) num=' '`printf "%d/%d" $i $total` ;;
133         esac
134     esac
135
136     file=`printf '%04d-%stxt' $i "$title"`
137     i=`expr "$i" - 1`
138     echo >&2 "* $file"
139     {
140         mailScript='
141         /./d
142         /^$/n
143         s|^\[PATCH[^]]*\] *||'
144
145         case "$mbox" in
146         t)
147             echo 'From nobody Mon Sep 17 00:00:00 2001' ;# UNIX "From" line
148             mailScript="$mailScript"'
149             s|^|Subject: [PATCH'"$num"'] |'
150             ;;
151         *)
152             mailScript="$mailScript"'
153             s|^|[PATCH'"$num"'] |'
154             ;;
155         esac
156
157         eval "$(sed -ne "$whosepatchScript" $commsg)"
158         test "$author,$au" = ",$me" || {
159                 mailScript="$mailScript"'
160         a\
161 From: '"$au"
162         }
163         test "$date,$au" = ",$me" || {
164                 mailScript="$mailScript"'
165         a\
166 Date: '"$ad"
167         }
168
169         mailScript="$mailScript"'
170         : body
171         p
172         n
173         b body'
174
175         sed -ne "$mailScript" <$commsg
176         echo '---'
177         echo
178         git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
179         echo
180         git-diff-tree -p $diff_opts "$commit" | sed -e "$stripCommitHead"
181
182         case "$mbox" in
183         t)
184                 echo
185                 ;;
186         esac
187     } >"$outdir$file"
188     case "$check" in
189     t)
190         # This is slightly modified from Andrew Morton's Perfect Patch.
191         # Lines you introduce should not have trailing whitespace.
192         # Also check for an indentation that has SP before a TAB.
193         grep -n '^+\([  ]*      .*\|.*[         ]\)$' "$outdir$file"
194
195         : do not exit with non-zero because we saw no problem in the last one.
196     esac
197 done <$series