]>
Commit | Line | Data |
---|---|---|
0acfc972 JH |
1 | #!/bin/sh |
2 | # | |
3 | # Copyright (c) 2005 Junio C Hamano | |
4 | # | |
5 | ||
215a7ad1 | 6 | . git-sh-setup || die "Not a git archive." |
4282c4fb | 7 | |
0acfc972 | 8 | usage () { |
655c7470 | 9 | echo >&2 "usage: $0"' [-n] [-o dir | --stdout] [--keep-subject] [--mbox] [--check] [--signoff] [-<diff options>...] upstream [ our-head ] |
0acfc972 JH |
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. | |
5c2c972f JH |
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. | |
0acfc972 JH |
25 | ' |
26 | exit 1 | |
27 | } | |
28 | ||
29 | diff_opts= | |
0acfc972 JH |
30 | LF=' |
31 | ' | |
0acfc972 | 32 | |
5c2c972f | 33 | outdir=./ |
0acfc972 JH |
34 | while case "$#" in 0) break;; esac |
35 | do | |
36 | case "$1" in | |
5c2c972f JH |
37 | -a|--a|--au|--aut|--auth|--autho|--author) |
38 | author=t ;; | |
39 | -c|--c|--ch|--che|--chec|--check) | |
40 | check=t ;; | |
44d2eb51 JH |
41 | -d|--d|--da|--dat|--date) |
42 | date=t ;; | |
5c2c972f JH |
43 | -m|--m|--mb|--mbo|--mbox) |
44 | date=t author=t mbox=t ;; | |
af5260ee JH |
45 | -k|--k|--ke|--kee|--keep|--keep-|--keep-s|--keep-su|--keep-sub|\ |
46 | --keep-subj|--keep-subje|--keep-subjec|--keep-subject) | |
47 | keep_subject=t ;; | |
0acfc972 JH |
48 | -n|--n|--nu|--num|--numb|--numbe|--number|--numbere|--numbered) |
49 | numbered=t ;; | |
d9ac9df4 | 50 | -s|--s|--si|--sig|--sign|--signo|--signof|--signoff) |
b097584b | 51 | signoff=t ;; |
655c7470 JH |
52 | --st|--std|--stdo|--stdou|--stdout) |
53 | stdout=t mbox=t date=t author=t ;; | |
0acfc972 JH |
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 | |
63 | outdir="$1" ;; | |
4a5b63e3 JH |
64 | -*' '* | -*"$LF"* | -*' '*) |
65 | # Ignore diff option that has whitespace for now. | |
66 | ;; | |
67 | -*) diff_opts="$diff_opts$1 " ;; | |
0acfc972 JH |
68 | *) break ;; |
69 | esac | |
70 | shift | |
71 | done | |
72 | ||
af5260ee JH |
73 | case "$keep_subject$numbered" in |
74 | tt) | |
75 | die '--keep-subject and --numbered are incompatible.' ;; | |
76 | esac | |
77 | ||
4a5b63e3 | 78 | rev1= rev2= |
0acfc972 | 79 | case "$#" in |
4282c4fb | 80 | 2) |
4a5b63e3 | 81 | rev1="$1" rev2="$2" ;; |
4282c4fb JH |
82 | 1) |
83 | case "$1" in | |
84 | *..*) | |
4a5b63e3 JH |
85 | rev1=`expr "$1" : '\(.*\)\.\.'` |
86 | rev2=`expr "$1" : '.*\.\.\(.*\)'` | |
87 | ;; | |
4282c4fb | 88 | *) |
4a5b63e3 JH |
89 | rev1="$1" |
90 | rev2="HEAD" | |
91 | ;; | |
4282c4fb JH |
92 | esac ;; |
93 | *) | |
94 | usage ;; | |
0acfc972 JH |
95 | esac |
96 | ||
44d2eb51 JH |
97 | me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'` |
98 | ||
0acfc972 JH |
99 | case "$outdir" in |
100 | */) ;; | |
101 | *) outdir="$outdir/" ;; | |
102 | esac | |
103 | test -d "$outdir" || mkdir -p "$outdir" || exit | |
104 | ||
105 | tmp=.tmp-series$$ | |
106 | trap 'rm -f $tmp-*' 0 1 2 3 15 | |
107 | ||
108 | series=$tmp-series | |
44d2eb51 | 109 | commsg=$tmp-commsg |
5c2c972f | 110 | filelist=$tmp-files |
0acfc972 JH |
111 | |
112 | titleScript=' | |
1855c044 JH |
113 | /./d |
114 | /^$/n | |
115 | s/^\[PATCH[^]]*\] *// | |
0acfc972 JH |
116 | s/[^-a-z.A-Z_0-9]/-/g |
117 | s/\.\.\.*/\./g | |
118 | s/\.*$// | |
119 | s/--*/-/g | |
120 | s/^-// | |
121 | s/-$// | |
122 | s/$/./ | |
1855c044 | 123 | p |
0acfc972 JH |
124 | q |
125 | ' | |
126 | ||
44d2eb51 JH |
127 | whosepatchScript=' |
128 | /^author /{ | |
129 | s/author \(.*>\) \(.*\)$/au='\''\1'\'' ad='\''\2'\''/p | |
130 | q | |
131 | }' | |
132 | ||
4a5b63e3 JH |
133 | git-cherry -v "$rev1" "$rev2" | |
134 | while read sign rev comment | |
135 | do | |
136 | case "$sign" in | |
137 | '-') | |
138 | echo >&2 "Merged already: $comment" | |
139 | ;; | |
140 | *) | |
141 | echo $rev | |
142 | ;; | |
143 | esac | |
144 | done >$series | |
145 | ||
655c7470 | 146 | process_one () { |
0acfc972 | 147 | mailScript=' |
1855c044 | 148 | /./d |
af5260ee JH |
149 | /^$/n' |
150 | case "$keep_subject" in | |
151 | t) ;; | |
5c2c972f JH |
152 | *) |
153 | mailScript="$mailScript"' | |
af5260ee | 154 | s|^\[PATCH[^]]*\] *|| |
5c2c972f JH |
155 | s|^|[PATCH'"$num"'] |' |
156 | ;; | |
157 | esac | |
af5260ee JH |
158 | mailScript="$mailScript"' |
159 | s|^|Subject: |' | |
160 | case "$mbox" in | |
161 | t) | |
162 | echo 'From nobody Mon Sep 17 00:00:00 2001' ;# UNIX "From" line | |
163 | ;; | |
164 | esac | |
655c7470 | 165 | |
44d2eb51 | 166 | eval "$(sed -ne "$whosepatchScript" $commsg)" |
5c2c972f | 167 | test "$author,$au" = ",$me" || { |
44d2eb51 JH |
168 | mailScript="$mailScript"' |
169 | a\ | |
170 | From: '"$au" | |
171 | } | |
172 | test "$date,$au" = ",$me" || { | |
173 | mailScript="$mailScript"' | |
174 | a\ | |
175 | Date: '"$ad" | |
176 | } | |
177 | ||
178 | mailScript="$mailScript"' | |
0acfc972 JH |
179 | : body |
180 | p | |
181 | n | |
182 | b body' | |
183 | ||
655c7470 JH |
184 | (cat $commsg ; echo; echo) | |
185 | sed -ne "$mailScript" | | |
186 | git-stripspace | |
b097584b JS |
187 | |
188 | test "$signoff" = "t" && { | |
189 | offsigner=`git-var GIT_COMMITTER_IDENT | sed -e 's/>.*/>/'` | |
d9ac9df4 JS |
190 | line="Signed-off-by: $offsigner" |
191 | grep -q "^$line\$" $commsg || { | |
192 | echo | |
193 | echo "$line" | |
194 | echo | |
195 | } | |
b097584b | 196 | } |
cc5625a5 | 197 | echo |
0acfc972 JH |
198 | echo '---' |
199 | echo | |
200 | git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary | |
201 | echo | |
3ff8cbed | 202 | git-cat-file commit "$commit^" | sed -e 's/^tree /applies-to: /' -e q |
b10c1a74 | 203 | git-diff-tree -p $diff_opts "$commit" |
3ff8cbed JH |
204 | echo "---" |
205 | echo "@@GIT_VERSION@@" | |
5c2c972f JH |
206 | |
207 | case "$mbox" in | |
208 | t) | |
209 | echo | |
210 | ;; | |
211 | esac | |
655c7470 JH |
212 | } |
213 | ||
214 | total=`wc -l <$series | tr -dc "[0-9]"` | |
215 | i=1 | |
216 | while read commit | |
217 | do | |
218 | git-cat-file commit "$commit" | git-stripspace >$commsg | |
219 | title=`sed -ne "$titleScript" <$commsg` | |
220 | case "$numbered" in | |
221 | '') num= ;; | |
222 | *) | |
223 | case $total in | |
224 | 1) num= ;; | |
225 | *) num=' '`printf "%d/%d" $i $total` ;; | |
226 | esac | |
5c2c972f | 227 | esac |
655c7470 JH |
228 | |
229 | file=`printf '%04d-%stxt' $i "$title"` | |
230 | if test '' = "$stdout" | |
231 | then | |
232 | echo "* $file" | |
233 | process_one >"$outdir$file" | |
234 | if test t = "$check" | |
235 | then | |
236 | # This is slightly modified from Andrew Morton's Perfect Patch. | |
237 | # Lines you introduce should not have trailing whitespace. | |
238 | # Also check for an indentation that has SP before a TAB. | |
239 | grep -n '^+\([ ]* .*\|.*[ ]\)$' "$outdir$file" | |
240 | : | |
241 | fi | |
242 | else | |
243 | echo >&2 "* $file" | |
244 | process_one | |
245 | fi | |
246 | i=`expr "$i" + 1` | |
0acfc972 | 247 | done <$series |