[PATCH] Unify Makefile indentation
[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] [--sign] [-<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     -s|--s|--si|--sig|--sign)
50     signoff=t ;;
51     -o=*|--o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*|--output-=*|\
52     --output-d=*|--output-di=*|--output-dir=*|--output-dire=*|\
53     --output-direc=*|--output-direct=*|--output-directo=*|\
54     --output-director=*|--output-directory=*)
55     outdir=`expr "$1" : '-[^=]*=\(.*\)'` ;;
56     -o|--o|--ou|--out|--outp|--outpu|--output|--output-|--output-d|\
57     --output-di|--output-dir|--output-dire|--output-direc|--output-direct|\
58     --output-directo|--output-director|--output-directory)
59     case "$#" in 1) usage ;; esac; shift
60     outdir="$1" ;;
61     -*) diff_opts="$diff_opts$LF$1" ;;
62     *) break ;;
63     esac
64     shift
65 done
66
67 revpair=
68 case "$#" in
69 2)
70     revpair="$1..$2" ;;
71 1)
72     case "$1" in
73     *..*)
74         revpair="$1";;
75     *)
76         revpair="$1..HEAD";;
77     esac ;;
78 *)
79     usage ;;
80 esac
81
82 me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'`
83
84 case "$outdir" in
85 */) ;;
86 *) outdir="$outdir/" ;;
87 esac
88 test -d "$outdir" || mkdir -p "$outdir" || exit
89
90 tmp=.tmp-series$$
91 trap 'rm -f $tmp-*' 0 1 2 3 15
92
93 series=$tmp-series
94 commsg=$tmp-commsg
95 filelist=$tmp-files
96
97 titleScript='
98         /./d
99         /^$/n
100         s/^\[PATCH[^]]*\] *//
101         s/[^-a-z.A-Z_0-9]/-/g
102         s/\.\.\.*/\./g
103         s/\.*$//
104         s/--*/-/g
105         s/^-//
106         s/-$//
107         s/$/./
108         p
109         q
110 '
111
112 whosepatchScript='
113 /^author /{
114         s/author \(.*>\) \(.*\)$/au='\''\1'\'' ad='\''\2'\''/p
115         q
116 }'
117
118 _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
119 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
120 stripCommitHead='/^'"$_x40"' (from '"$_x40"')$/d'
121
122 git-rev-list --no-merges --merge-order \
123         $(git-rev-parse --revs-only "$revpair") >$series
124 total=`wc -l <$series | tr -dc "[0-9]"`
125 i=$total
126 while read commit
127 do
128     git-cat-file commit "$commit" | git-stripspace >$commsg
129     title=`sed -ne "$titleScript" <$commsg`
130     case "$numbered" in
131     '') num= ;;
132     *)
133         case $total in
134         1) num= ;;
135         *) num=' '`printf "%d/%d" $i $total` ;;
136         esac
137     esac
138
139     file=`printf '%04d-%stxt' $i "$title"`
140     i=`expr "$i" - 1`
141     echo >&2 "* $file"
142     {
143         mailScript='
144         /./d
145         /^$/n
146         s|^\[PATCH[^]]*\] *||'
147
148         case "$mbox" in
149         t)
150             echo 'From nobody Mon Sep 17 00:00:00 2001' ;# UNIX "From" line
151             mailScript="$mailScript"'
152             s|^|Subject: [PATCH'"$num"'] |'
153             ;;
154         *)
155             mailScript="$mailScript"'
156             s|^|[PATCH'"$num"'] |'
157             ;;
158         esac
159
160         eval "$(sed -ne "$whosepatchScript" $commsg)"
161         test "$author,$au" = ",$me" || {
162                 mailScript="$mailScript"'
163         a\
164 From: '"$au"
165         }
166         test "$date,$au" = ",$me" || {
167                 mailScript="$mailScript"'
168         a\
169 Date: '"$ad"
170         }
171
172         mailScript="$mailScript"'
173         : body
174         p
175         n
176         b body'
177
178         sed -ne "$mailScript" <$commsg
179
180         test "$signoff" = "t" && {
181                 offsigner=`git-var GIT_COMMITTER_IDENT | sed -e 's/>.*/>/'`
182                 echo
183                 echo "Signed-off-by: $offsigner"
184                 echo
185         }
186
187         echo '---'
188         echo
189         git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
190         echo
191         git-diff-tree -p $diff_opts "$commit" | sed -e "$stripCommitHead"
192
193         case "$mbox" in
194         t)
195                 echo
196                 ;;
197         esac
198     } >"$outdir$file"
199     case "$check" in
200     t)
201         # This is slightly modified from Andrew Morton's Perfect Patch.
202         # Lines you introduce should not have trailing whitespace.
203         # Also check for an indentation that has SP before a TAB.
204         grep -n '^+\([  ]*      .*\|.*[         ]\)$' "$outdir$file"
205
206         : do not exit with non-zero because we saw no problem in the last one.
207     esac
208 done <$series