Code

Merge with gitk.
[git.git] / git-format-patch-script
1 #!/bin/sh
2 #
3 # Copyright (c) 2005 Junio C Hamano
4 #
6 . git-sh-setup-script || die "Not a git archive."
8 usage () {
9     echo >&2 "usage: $0"' [-n] [-o dir] [--mbox] [--check] [-<diff options>...] upstream [ our-head ]
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.
16 When -o is specified, output files are created in that directory; otherwise in
17 the current working directory.
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.
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 }
29 diff_opts=
30 IFS='
31 '
32 LF='
33 '
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
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
80 me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'`
82 case "$outdir" in
83 */) ;;
84 *) outdir="$outdir/" ;;
85 esac
86 test -d "$outdir" || mkdir -p "$outdir" || exit
88 tmp=.tmp-series$$
89 trap 'rm -f $tmp-*' 0 1 2 3 15
91 series=$tmp-series
92 commsg=$tmp-commsg
93 filelist=$tmp-files
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
110 whosepatchScript='
111 /^author /{
112         s/author \(.*>\) \(.*\)$/au='\''\1'\'' ad='\''\2'\''/p
113         q
114 }'
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'
120 git-rev-list --no-merges --merge-order \
121         $(git-rev-parse --revs-only "$revpair") >$series
122 total=`wc -l <$series | tr -dc "[0-9]"`
123 i=$total
124 while read commit
125 do
126     git-cat-file commit "$commit" | git-stripspace >$commsg
127     title=`sed -ne "$titleScript" <$commsg`
128     case "$numbered" in
129     '') num= ;;
130     *)
131         case $total in
132         1) num= ;;
133         *) num=' '`printf "%d/%d" $i $total` ;;
134         esac
135     esac
137     file=`printf '%04d-%stxt' $i "$title"`
138     i=`expr "$i" - 1`
139     echo >&2 "* $file"
140     {
141         mailScript='
142         /./d
143         /^$/n
144         s|^\[PATCH[^]]*\] *||'
146         case "$mbox" in
147         t)
148             echo 'From nobody Mon Sep 17 00:00:00 2001' ;# UNIX "From" line
149             mailScript="$mailScript"'
150             s|^|Subject: [PATCH'"$num"'] |'
151             ;;
152         *)
153             mailScript="$mailScript"'
154             s|^|[PATCH'"$num"'] |'
155             ;;
156         esac
158         eval "$(sed -ne "$whosepatchScript" $commsg)"
159         test "$author,$au" = ",$me" || {
160                 mailScript="$mailScript"'
161         a\
162 From: '"$au"
163         }
164         test "$date,$au" = ",$me" || {
165                 mailScript="$mailScript"'
166         a\
167 Date: '"$ad"
168         }
170         mailScript="$mailScript"'
171         : body
172         p
173         n
174         b body'
176         sed -ne "$mailScript" <$commsg
177         echo '---'
178         echo
179         git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
180         echo
181         git-diff-tree -p $diff_opts "$commit" | sed -e "$stripCommitHead"
183         case "$mbox" in
184         t)
185                 echo
186                 ;;
187         esac
188     } >"$outdir$file"
189     case "$check" in
190     t)
191         # This is slightly modified from Andrew Morton's Perfect Patch.
192         # Lines you introduce should not have trailing whitespace.
193         # Also check for an indentation that has SP before a TAB.
194         grep -n '^+\([  ]*      .*\|.*[         ]\)$' "$outdir$file"
196         : do not exit with non-zero because we saw no problem in the last one.
197     esac
198 done <$series