[PATCH] git-format-patch-script and mailinfo updates.
[git.git] / git-format-patch-script
1 #!/bin/sh
2 #
3 # Copyright (c) 2005 Junio C Hamano
4 #
5
6 usage () {
7     echo >&2 "usage: $0"' [-n] [-o dir] [-<diff options>...] upstream [ our-head ]
8
9 Prepare each commit with its patch since our-head forked from upstream,
10 one file per patch, for e-mail submission.  Each output file is
11 numbered sequentially from 1, and uses the first line of the commit
12 message (massaged for pathname safety) as the filename.
13
14 When -o is specified, output files are created in that directory; otherwise in
15 the current working directory.
16
17 When -n is specified, instead of "[PATCH] Subject", the first line is formatted
18 as "[PATCH N/M] Subject", unless you have only one patch.
19 '
20     exit 1
21 }
22
23 diff_opts=
24 IFS='
25 '
26 LF='
27 '
28 outdir=./
29
30 while case "$#" in 0) break;; esac
31 do
32     case "$1" in
33     -d|--d|--da|--dat|--date)
34     date=t ;;
35     -n|--n|--nu|--num|--numb|--numbe|--number|--numbere|--numbered)
36     numbered=t ;;
37     -o=*|--o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*|--output-=*|\
38     --output-d=*|--output-di=*|--output-dir=*|--output-dire=*|\
39     --output-direc=*|--output-direct=*|--output-directo=*|\
40     --output-director=*|--output-directory=*)
41     outdir=`expr "$1" : '-[^=]*=\(.*\)'` ;;
42     -o|--o|--ou|--out|--outp|--outpu|--output|--output-|--output-d|\
43     --output-di|--output-dir|--output-dire|--output-direc|--output-direct|\
44     --output-directo|--output-director|--output-directory)
45     case "$#" in 1) usage ;; esac; shift
46     outdir="$1" ;;
47     -*) diff_opts="$diff_opts$LF$1" ;;
48     *) break ;;
49     esac
50     shift
51 done
52
53 case "$#" in
54 2)    linus="$1" junio="$2" ;;
55 1)    linus="$1" junio=HEAD ;;
56 *)    usage ;;
57 esac
58 junio=`git-rev-parse --verify "$junio"`
59 linus=`git-rev-parse --verify "$linus"`
60
61 me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'`
62
63 case "$outdir" in
64 */) ;;
65 *) outdir="$outdir/" ;;
66 esac
67 test -d "$outdir" || mkdir -p "$outdir" || exit
68
69 tmp=.tmp-series$$
70 trap 'rm -f $tmp-*' 0 1 2 3 15
71
72 series=$tmp-series
73 commsg=$tmp-commsg
74
75 titleScript='
76         /./d
77         /^$/n
78         s/^\[PATCH[^]]*\] *//
79         s/[^-a-z.A-Z_0-9]/-/g
80         s/\.\.\.*/\./g
81         s/\.*$//
82         s/--*/-/g
83         s/^-//
84         s/-$//
85         s/$/./
86         p
87         q
88 '
89
90 whosepatchScript='
91 /^author /{
92         s/author \(.*>\) \(.*\)$/au='\''\1'\'' ad='\''\2'\''/p
93         q
94 }'
95
96 _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
97 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
98 stripCommitHead='/^'"$_x40"' (from '"$_x40"')$/d'
99
100 git-rev-list --merge-order "$junio" "^$linus" >$series
101 total=`wc -l <$series`
102 i=$total
103 while read commit
104 do
105     git-cat-file commit "$commit" | git-stripspace >$commsg
106     title=`sed -ne "$titleScript" <$commsg`
107     case "$numbered" in
108     '') num= ;;
109     *)
110         case $total in
111         1) num= ;;
112         *) num=' '`printf "%d/%d" $i $total` ;;
113         esac
114     esac
115
116     file=`printf '%04d-%stxt' $i "$title"`
117     i=`expr "$i" - 1`
118     echo "$file"
119     {
120         mailScript='
121         /./d
122         /^$/n
123         s|^\[PATCH[^]]*\] *||
124         s|^|[PATCH'"$num"'] |'
125
126         eval "$(sed -ne "$whosepatchScript" $commsg)"
127         test "$au" = "$me" || {
128                 mailScript="$mailScript"'
129         a\
130 From: '"$au"
131         }
132         test "$date,$au" = ",$me" || {
133                 mailScript="$mailScript"'
134         a\
135 Date: '"$ad"
136         }
137
138         mailScript="$mailScript"'
139         : body
140         p
141         n
142         b body'
143
144         sed -ne "$mailScript" <$commsg
145         echo '---'
146         echo
147         git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
148         echo
149         git-diff-tree -p $diff_opts "$commit" | sed -e "$stripCommitHead"
150     } >"$outdir$file"
151 done <$series