]> git.ipfire.org Git - thirdparty/git.git/blame - git-format-patch.sh
Use symbolic name SHORT_NAME_AMBIGUOUS as error return value
[thirdparty/git.git] / git-format-patch.sh
CommitLineData
0acfc972
JH
1#!/bin/sh
2#
3# Copyright (c) 2005 Junio C Hamano
4#
5
806f36d4
FK
6USAGE='[-n | -k] [-o <dir> | --stdout] [--signoff] [--check] [--mbox] [--diff-options] <upstream> [<our-head>]'
7LONG_USAGE='Prepare each commit with its patch since our-head forked from upstream,
0acfc972
JH
8one file per patch, for e-mail submission. Each output file is
9numbered sequentially from 1, and uses the first line of the commit
10message (massaged for pathname safety) as the filename.
11
5f815e59
YD
12There are three output modes. By default, output files are created in
13the current working directory; when -o is specified, they are created
14in that directory instead; when --stdout is specified, they are spit
15on standard output, and can be piped to git-am.
0acfc972
JH
16
17When -n is specified, instead of "[PATCH] Subject", the first line is formatted
18as "[PATCH N/M] Subject", unless you have only one patch.
5c2c972f
JH
19
20When --mbox is specified, the output is formatted to resemble
21UNIX mailbox format, and can be concatenated together for processing
806f36d4
FK
22with applymbox.'
23. git-sh-setup
24
25# Force diff to run in C locale.
26LANG=C LC_ALL=C
27export LANG LC_ALL
0acfc972
JH
28
29diff_opts=
0acfc972
JH
30LF='
31'
0acfc972 32
5c2c972f 33outdir=./
0acfc972
JH
34while case "$#" in 0) break;; esac
35do
36 case "$1" in
5c2c972f
JH
37 -c|--c|--ch|--che|--chec|--check)
38 check=t ;;
36383a3d
JH
39 -a|--a|--au|--aut|--auth|--autho|--author|\
40 -d|--d|--da|--dat|--date|\
41 -m|--m|--mb|--mbo|--mbox) # now noop
42 ;;
af5260ee
JH
43 -k|--k|--ke|--kee|--keep|--keep-|--keep-s|--keep-su|--keep-sub|\
44 --keep-subj|--keep-subje|--keep-subjec|--keep-subject)
45 keep_subject=t ;;
0acfc972
JH
46 -n|--n|--nu|--num|--numb|--numbe|--number|--numbere|--numbered)
47 numbered=t ;;
d9ac9df4 48 -s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
b097584b 49 signoff=t ;;
655c7470
JH
50 --st|--std|--stdo|--stdou|--stdout)
51 stdout=t mbox=t date=t author=t ;;
0acfc972
JH
52 -o=*|--o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*|--output-=*|\
53 --output-d=*|--output-di=*|--output-dir=*|--output-dire=*|\
54 --output-direc=*|--output-direct=*|--output-directo=*|\
55 --output-director=*|--output-directory=*)
56 outdir=`expr "$1" : '-[^=]*=\(.*\)'` ;;
57 -o|--o|--ou|--out|--outp|--outpu|--output|--output-|--output-d|\
58 --output-di|--output-dir|--output-dire|--output-direc|--output-direct|\
59 --output-directo|--output-director|--output-directory)
60 case "$#" in 1) usage ;; esac; shift
61 outdir="$1" ;;
93d69d86
JL
62 -h|--h|--he|--hel|--help)
63 usage
64 ;;
4a5b63e3
JH
65 -*' '* | -*"$LF"* | -*' '*)
66 # Ignore diff option that has whitespace for now.
67 ;;
68 -*) diff_opts="$diff_opts$1 " ;;
0acfc972
JH
69 *) break ;;
70 esac
71 shift
72done
73
af5260ee
JH
74case "$keep_subject$numbered" in
75tt)
76 die '--keep-subject and --numbered are incompatible.' ;;
77esac
78
603d8745
JH
79tmp=.tmp-series$$
80trap 'rm -f $tmp-*' 0 1 2 3 15
81
82series=$tmp-series
83commsg=$tmp-commsg
84filelist=$tmp-files
85
86# Backward compatible argument parsing hack.
87#
88# Historically, we supported:
89# 1. "rev1" is equivalent to "rev1..HEAD"
90# 2. "rev1..rev2"
91# 3. "rev1" "rev2 is equivalent to "rev1..rev2"
92#
93# We want to take a sequence of "rev1..rev2" in general.
bd7c8aab
JH
94# Also, "rev1.." should mean "rev1..HEAD"; git-diff users are
95# familiar with that syntax.
603d8745 96
88b5a748 97case "$#,$1$2" in
603d8745
JH
981,?*..?*)
99 # single "rev1..rev2"
100 ;;
bd7c8aab
JH
1011,?*..)
102 # single "rev1.." should mean "rev1..HEAD"
b748421a 103 set x "$1"HEAD
bd7c8aab
JH
104 shift
105 ;;
603d8745
JH
1061,*)
107 # single rev1
108 set x "$1..HEAD"
109 shift
110 ;;
1112,?*..?*)
112 # not traditional "rev1" "rev2"
4a5b63e3 113 ;;
603d8745
JH
1142,*)
115 set x "$1..$2"
116 shift
4a5b63e3 117 ;;
0acfc972
JH
118esac
119
603d8745
JH
120# Now we have what we want in $@
121for revpair
122do
123 case "$revpair" in
124 ?*..?*)
125 rev1=`expr "$revpair" : '\(.*\)\.\.'`
126 rev2=`expr "$revpair" : '.*\.\.\(.*\)'`
127 ;;
128 *)
88b5a748
JH
129 rev1="$revpair^"
130 rev2="$revpair"
603d8745
JH
131 ;;
132 esac
133 git-rev-parse --verify "$rev1^0" >/dev/null 2>&1 ||
134 die "Not a valid rev $rev1 ($revpair)"
135 git-rev-parse --verify "$rev2^0" >/dev/null 2>&1 ||
136 die "Not a valid rev $rev2 ($revpair)"
137 git-cherry -v "$rev1" "$rev2" |
138 while read sign rev comment
139 do
140 case "$sign" in
141 '-')
142 echo >&2 "Merged already: $comment"
143 ;;
144 *)
145 echo $rev
146 ;;
147 esac
148 done
149done >$series
150
44d2eb51
JH
151me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'`
152
0acfc972
JH
153case "$outdir" in
154*/) ;;
155*) outdir="$outdir/" ;;
156esac
157test -d "$outdir" || mkdir -p "$outdir" || exit
158
0acfc972 159titleScript='
1855c044
JH
160 /./d
161 /^$/n
162 s/^\[PATCH[^]]*\] *//
0acfc972
JH
163 s/[^-a-z.A-Z_0-9]/-/g
164 s/\.\.\.*/\./g
165 s/\.*$//
166 s/--*/-/g
167 s/^-//
168 s/-$//
169 s/$/./
1855c044 170 p
0acfc972
JH
171 q
172'
173
655c7470 174process_one () {
36383a3d
JH
175 perl -w -e '
176my ($keep_subject, $num, $signoff, $commsg) = @ARGV;
177my ($signoff_pattern, $done_header, $done_subject, $signoff_seen,
178 $last_was_signoff);
655c7470 179
36383a3d 180if ($signoff) {
fc5be4fd 181 $signoff = "Signed-off-by: " . `git-var GIT_COMMITTER_IDENT`;
36383a3d
JH
182 $signoff =~ s/>.*/>/;
183 $signoff_pattern = quotemeta($signoff);
184}
44d2eb51 185
36383a3d
JH
186my @weekday_names = qw(Sun Mon Tue Wed Thu Fri Sat);
187my @month_names = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
a5c21d6e 188
36383a3d
JH
189sub show_date {
190 my ($time, $tz) = @_;
191 my $minutes = abs($tz);
192 $minutes = ($minutes / 100) * 60 + ($minutes % 100);
193 if ($tz < 0) {
194 $minutes = -$minutes;
195 }
196 my $t = $time + $minutes * 60;
197 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime($t);
198 return sprintf("%s %s %d %02d:%02d:%02d %d %+05d",
199 $weekday_names[$wday],
200 $month_names[$mon],
201 $mday, $hour, $min, $sec,
202 $year+1900, $tz);
203}
0acfc972 204
36383a3d
JH
205print "From nobody Mon Sep 17 00:00:00 2001\n";
206open FH, "git stripspace <$commsg |" or die "open $commsg pipe";
207while (<FH>) {
208 unless ($done_header) {
209 if (/^$/) {
210 $done_header = 1;
211 }
212 elsif (/^author (.*>) (.*)$/) {
213 my ($author_ident, $author_date) = ($1, $2);
214 my ($utc, $off) = ($author_date =~ /^(\d+) ([-+]?\d+)$/);
215 $author_date = show_date($utc, $off);
b097584b 216
36383a3d
JH
217 print "From: $author_ident\n";
218 print "Date: $author_date\n";
b097584b 219 }
36383a3d
JH
220 next;
221 }
222 unless ($done_subject) {
223 unless ($keep_subject) {
224 s/^\[PATCH[^]]*\]\s*//;
225 s/^/[PATCH$num] /;
226 }
227 print "Subject: $_";
228 $done_subject = 1;
229 next;
230 }
231
232 $last_was_signoff = 0;
233 if (/Signed-off-by:/i) {
234 if ($signoff ne "" && /Signed-off-by:\s*$signoff_pattern$/i) {
235 $signoff_seen = 1;
236 }
237 }
238 print $_;
239}
240if (!$signoff_seen && $signoff ne "") {
241 if (!$last_was_signoff) {
242 print "\n";
243 }
244 print "$signoff\n";
245}
246print "\n---\n\n";
247close FH or die "close $commsg pipe";
248' "$keep_subject" "$num" "$signoff" $commsg
249
0acfc972
JH
250 git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
251 echo
b10c1a74 252 git-diff-tree -p $diff_opts "$commit"
a004d3f7 253 echo "-- "
3ff8cbed 254 echo "@@GIT_VERSION@@"
5c2c972f 255
36383a3d 256 echo
655c7470
JH
257}
258
259total=`wc -l <$series | tr -dc "[0-9]"`
7564577a
JH
260case "$total,$numbered" in
2611,*)
262 numfmt='' ;;
263*,t)
264 numfmt=`echo "$total" | wc -c`
265 numfmt=$(($numfmt-1))
266 numfmt=" %0${numfmt}d/$total"
267esac
268
655c7470
JH
269i=1
270while read commit
271do
272 git-cat-file commit "$commit" | git-stripspace >$commsg
273 title=`sed -ne "$titleScript" <$commsg`
274 case "$numbered" in
275 '') num= ;;
276 *)
7564577a 277 num=`printf "$numfmt" $i` ;;
5c2c972f 278 esac
655c7470
JH
279
280 file=`printf '%04d-%stxt' $i "$title"`
281 if test '' = "$stdout"
282 then
51b3c00e 283 echo "$file"
655c7470
JH
284 process_one >"$outdir$file"
285 if test t = "$check"
286 then
287 # This is slightly modified from Andrew Morton's Perfect Patch.
288 # Lines you introduce should not have trailing whitespace.
289 # Also check for an indentation that has SP before a TAB.
290 grep -n '^+\([ ]* .*\|.*[ ]\)$' "$outdir$file"
291 :
292 fi
293 else
51b3c00e 294 echo >&2 "$file"
655c7470
JH
295 process_one
296 fi
297 i=`expr "$i" + 1`
0acfc972 298done <$series