Merge branch 'bc/maint-1.6.1-branch-deleted-was'
[git] / t / t4014-format-patch.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2006 Junio C Hamano
4 #
5
6 test_description='various format-patch tests'
7
8 . ./test-lib.sh
9
10 test_expect_success setup '
11
12         for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
13         cat file >elif &&
14         git add file elif &&
15         git commit -m Initial &&
16         git checkout -b side &&
17
18         for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
19         test_chmod +x elif &&
20         git commit -m "Side changes #1" &&
21
22         for i in D E F; do echo "$i"; done >>file &&
23         git update-index file &&
24         git commit -m "Side changes #2" &&
25         git tag C2 &&
26
27         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
28         git update-index file &&
29         git commit -m "Side changes #3 with \\n backslash-n in it." &&
30
31         git checkout master &&
32         git diff-tree -p C2 | git apply --index &&
33         git commit -m "Master accepts moral equivalent of #2"
34
35 '
36
37 test_expect_success "format-patch --ignore-if-in-upstream" '
38
39         git format-patch --stdout master..side >patch0 &&
40         cnt=`grep "^From " patch0 | wc -l` &&
41         test $cnt = 3
42
43 '
44
45 test_expect_success "format-patch --ignore-if-in-upstream" '
46
47         git format-patch --stdout \
48                 --ignore-if-in-upstream master..side >patch1 &&
49         cnt=`grep "^From " patch1 | wc -l` &&
50         test $cnt = 2
51
52 '
53
54 test_expect_success "format-patch result applies" '
55
56         git checkout -b rebuild-0 master &&
57         git am -3 patch0 &&
58         cnt=`git rev-list master.. | wc -l` &&
59         test $cnt = 2
60 '
61
62 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
63
64         git checkout -b rebuild-1 master &&
65         git am -3 patch1 &&
66         cnt=`git rev-list master.. | wc -l` &&
67         test $cnt = 2
68 '
69
70 test_expect_success 'commit did not screw up the log message' '
71
72         git cat-file commit side | grep "^Side .* with .* backslash-n"
73
74 '
75
76 test_expect_success 'format-patch did not screw up the log message' '
77
78         grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
79         grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
80
81 '
82
83 test_expect_success 'replay did not screw up the log message' '
84
85         git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
86
87 '
88
89 test_expect_success 'extra headers' '
90
91         git config format.headers "To: R. E. Cipient <rcipient@example.com>
92 " &&
93         git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
94 " &&
95         git format-patch --stdout master..side > patch2 &&
96         sed -e "/^$/q" patch2 > hdrs2 &&
97         grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs2 &&
98         grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs2
99
100 '
101
102 test_expect_success 'extra headers without newlines' '
103
104         git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
105         git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
106         git format-patch --stdout master..side >patch3 &&
107         sed -e "/^$/q" patch3 > hdrs3 &&
108         grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs3 &&
109         grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs3
110
111 '
112
113 test_expect_success 'extra headers with multiple To:s' '
114
115         git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
116         git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
117         git format-patch --stdout master..side > patch4 &&
118         sed -e "/^$/q" patch4 > hdrs4 &&
119         grep "^To: R. E. Cipient <rcipient@example.com>,$" hdrs4 &&
120         grep "^ *S. E. Cipient <scipient@example.com>$" hdrs4
121 '
122
123 test_expect_success 'additional command line cc' '
124
125         git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
126         git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch5 &&
127         grep "^Cc: R. E. Cipient <rcipient@example.com>,$" patch5 &&
128         grep "^ *S. E. Cipient <scipient@example.com>$" patch5
129 '
130
131 test_expect_success 'multiple files' '
132
133         rm -rf patches/ &&
134         git checkout side &&
135         git format-patch -o patches/ master &&
136         ls patches/0001-Side-changes-1.patch patches/0002-Side-changes-2.patch patches/0003-Side-changes-3-with-n-backslash-n-in-it.patch
137 '
138
139 check_threading () {
140         expect="$1" &&
141         shift &&
142         (git format-patch --stdout "$@"; echo $? > status.out) |
143         # Prints everything between the Message-ID and In-Reply-To,
144         # and replaces all Message-ID-lookalikes by a sequence number
145         perl -ne '
146                 if (/^(message-id|references|in-reply-to)/i) {
147                         $printing = 1;
148                 } elsif (/^\S/) {
149                         $printing = 0;
150                 }
151                 if ($printing) {
152                         $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
153                         for $k (keys %h) {s/$k/$h{$k}/};
154                         print;
155                 }
156                 print "---\n" if /^From /i;
157         ' > actual &&
158         test 0 = "$(cat status.out)" &&
159         test_cmp "$expect" actual
160 }
161
162 cat >> expect.no-threading <<EOF
163 ---
164 ---
165 ---
166 EOF
167
168 test_expect_success 'no threading' '
169         git checkout side &&
170         check_threading expect.no-threading master
171 '
172
173 cat > expect.thread <<EOF
174 ---
175 Message-Id: <0>
176 ---
177 Message-Id: <1>
178 In-Reply-To: <0>
179 References: <0>
180 ---
181 Message-Id: <2>
182 In-Reply-To: <0>
183 References: <0>
184 EOF
185
186 test_expect_success 'thread' '
187         check_threading expect.thread --thread master
188 '
189
190 cat > expect.in-reply-to <<EOF
191 ---
192 Message-Id: <0>
193 In-Reply-To: <1>
194 References: <1>
195 ---
196 Message-Id: <2>
197 In-Reply-To: <1>
198 References: <1>
199 ---
200 Message-Id: <3>
201 In-Reply-To: <1>
202 References: <1>
203 EOF
204
205 test_expect_success 'thread in-reply-to' '
206         check_threading expect.in-reply-to --in-reply-to="<test.message>" \
207                 --thread master
208 '
209
210 cat > expect.cover-letter <<EOF
211 ---
212 Message-Id: <0>
213 ---
214 Message-Id: <1>
215 In-Reply-To: <0>
216 References: <0>
217 ---
218 Message-Id: <2>
219 In-Reply-To: <0>
220 References: <0>
221 ---
222 Message-Id: <3>
223 In-Reply-To: <0>
224 References: <0>
225 EOF
226
227 test_expect_success 'thread cover-letter' '
228         check_threading expect.cover-letter --cover-letter --thread master
229 '
230
231 cat > expect.cl-irt <<EOF
232 ---
233 Message-Id: <0>
234 In-Reply-To: <1>
235 References: <1>
236 ---
237 Message-Id: <2>
238 In-Reply-To: <0>
239 References: <1>
240         <0>
241 ---
242 Message-Id: <3>
243 In-Reply-To: <0>
244 References: <1>
245         <0>
246 ---
247 Message-Id: <4>
248 In-Reply-To: <0>
249 References: <1>
250         <0>
251 EOF
252
253 test_expect_success 'thread cover-letter in-reply-to' '
254         check_threading expect.cl-irt --cover-letter \
255                 --in-reply-to="<test.message>" --thread master
256 '
257
258 test_expect_success 'thread explicit shallow' '
259         check_threading expect.cl-irt --cover-letter \
260                 --in-reply-to="<test.message>" --thread=shallow master
261 '
262
263 cat > expect.deep <<EOF
264 ---
265 Message-Id: <0>
266 ---
267 Message-Id: <1>
268 In-Reply-To: <0>
269 References: <0>
270 ---
271 Message-Id: <2>
272 In-Reply-To: <1>
273 References: <0>
274         <1>
275 EOF
276
277 test_expect_success 'thread deep' '
278         check_threading expect.deep --thread=deep master
279 '
280
281 cat > expect.deep-irt <<EOF
282 ---
283 Message-Id: <0>
284 In-Reply-To: <1>
285 References: <1>
286 ---
287 Message-Id: <2>
288 In-Reply-To: <0>
289 References: <1>
290         <0>
291 ---
292 Message-Id: <3>
293 In-Reply-To: <2>
294 References: <1>
295         <0>
296         <2>
297 EOF
298
299 test_expect_success 'thread deep in-reply-to' '
300         check_threading expect.deep-irt  --thread=deep \
301                 --in-reply-to="<test.message>" master
302 '
303
304 cat > expect.deep-cl <<EOF
305 ---
306 Message-Id: <0>
307 ---
308 Message-Id: <1>
309 In-Reply-To: <0>
310 References: <0>
311 ---
312 Message-Id: <2>
313 In-Reply-To: <1>
314 References: <0>
315         <1>
316 ---
317 Message-Id: <3>
318 In-Reply-To: <2>
319 References: <0>
320         <1>
321         <2>
322 EOF
323
324 test_expect_success 'thread deep cover-letter' '
325         check_threading expect.deep-cl --cover-letter --thread=deep master
326 '
327
328 cat > expect.deep-cl-irt <<EOF
329 ---
330 Message-Id: <0>
331 In-Reply-To: <1>
332 References: <1>
333 ---
334 Message-Id: <2>
335 In-Reply-To: <0>
336 References: <1>
337         <0>
338 ---
339 Message-Id: <3>
340 In-Reply-To: <2>
341 References: <1>
342         <0>
343         <2>
344 ---
345 Message-Id: <4>
346 In-Reply-To: <3>
347 References: <1>
348         <0>
349         <2>
350         <3>
351 EOF
352
353 test_expect_success 'thread deep cover-letter in-reply-to' '
354         check_threading expect.deep-cl-irt --cover-letter \
355                 --in-reply-to="<test.message>" --thread=deep master
356 '
357
358 test_expect_success 'thread via config' '
359         git config format.thread true &&
360         check_threading expect.thread master
361 '
362
363 test_expect_success 'thread deep via config' '
364         git config format.thread deep &&
365         check_threading expect.deep master
366 '
367
368 test_expect_success 'thread config + override' '
369         git config format.thread deep &&
370         check_threading expect.thread --thread master
371 '
372
373 test_expect_success 'thread config + --no-thread' '
374         git config format.thread deep &&
375         check_threading expect.no-threading --no-thread master
376 '
377
378 test_expect_success 'excessive subject' '
379
380         rm -rf patches/ &&
381         git checkout side &&
382         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
383         git update-index file &&
384         git commit -m "This is an excessively long subject line for a message due to the habit some projects have of not having a short, one-line subject at the start of the commit message, but rather sticking a whole paragraph right at the start as the only thing in the commit message. It had better not become the filename for the patch." &&
385         git format-patch -o patches/ master..side &&
386         ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
387 '
388
389 test_expect_success 'cover-letter inherits diff options' '
390
391         git mv file foo &&
392         git commit -m foo &&
393         git format-patch --cover-letter -1 &&
394         ! grep "file => foo .* 0 *$" 0000-cover-letter.patch &&
395         git format-patch --cover-letter -1 -M &&
396         grep "file => foo .* 0 *$" 0000-cover-letter.patch
397
398 '
399
400 cat > expect << EOF
401   This is an excessively long subject line for a message due to the
402     habit some projects have of not having a short, one-line subject at
403     the start of the commit message, but rather sticking a whole
404     paragraph right at the start as the only thing in the commit
405     message. It had better not become the filename for the patch.
406   foo
407
408 EOF
409
410 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
411
412         git format-patch --cover-letter -2 &&
413         sed -e "1,/A U Thor/d" -e "/^$/q" < 0000-cover-letter.patch > output &&
414         test_cmp expect output
415
416 '
417
418 cat > expect << EOF
419 ---
420  file |   16 ++++++++++++++++
421  1 files changed, 16 insertions(+), 0 deletions(-)
422
423 diff --git a/file b/file
424 index 40f36c6..2dc5c23 100644
425 --- a/file
426 +++ b/file
427 @@ -13,4 +13,20 @@ C
428  10
429  D
430  E
431  F
432 +5
433 EOF
434
435 test_expect_success 'format-patch respects -U' '
436
437         git format-patch -U4 -2 &&
438         sed -e "1,/^$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
439         test_cmp expect output
440
441 '
442
443 test_expect_success 'format-patch from a subdirectory (1)' '
444         filename=$(
445                 rm -rf sub &&
446                 mkdir -p sub/dir &&
447                 cd sub/dir &&
448                 git format-patch -1
449         ) &&
450         case "$filename" in
451         0*)
452                 ;; # ok
453         *)
454                 echo "Oops? $filename"
455                 false
456                 ;;
457         esac &&
458         test -f "$filename"
459 '
460
461 test_expect_success 'format-patch from a subdirectory (2)' '
462         filename=$(
463                 rm -rf sub &&
464                 mkdir -p sub/dir &&
465                 cd sub/dir &&
466                 git format-patch -1 -o ..
467         ) &&
468         case "$filename" in
469         ../0*)
470                 ;; # ok
471         *)
472                 echo "Oops? $filename"
473                 false
474                 ;;
475         esac &&
476         basename=$(expr "$filename" : ".*/\(.*\)") &&
477         test -f "sub/$basename"
478 '
479
480 test_expect_success 'format-patch from a subdirectory (3)' '
481         here="$TEST_DIRECTORY/$test" &&
482         rm -f 0* &&
483         filename=$(
484                 rm -rf sub &&
485                 mkdir -p sub/dir &&
486                 cd sub/dir &&
487                 git format-patch -1 -o "$here"
488         ) &&
489         basename=$(expr "$filename" : ".*/\(.*\)") &&
490         test -f "$basename"
491 '
492
493 test_done