Merge branch 'maint'
[git/git.git] / t / t4014-format-patch.sh
CommitLineData
ece3c67f
JH
1#!/bin/sh
2#
3# Copyright (c) 2006 Junio C Hamano
4#
5
9800a754 6test_description='various format-patch tests'
ece3c67f
JH
7
8. ./test-lib.sh
9
10test_expect_success setup '
11
12 for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
cd894ee9
JH
13 cat file >elif &&
14 git add file elif &&
ece3c67f
JH
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 &&
1f553918 19 test_chmod +x elif &&
816366e2 20 git commit -m "Side changes #1" &&
ece3c67f
JH
21
22 for i in D E F; do echo "$i"; done >>file &&
23 git update-index file &&
816366e2 24 git commit -m "Side changes #2" &&
982b64e4 25 git tag C2 &&
ece3c67f
JH
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 &&
816366e2 29 git commit -m "Side changes #3 with \\n backslash-n in it." &&
ece3c67f
JH
30
31 git checkout master &&
982b64e4
JH
32 git diff-tree -p C2 | git apply --index &&
33 git commit -m "Master accepts moral equivalent of #2"
ece3c67f
JH
34
35'
36
37test_expect_success "format-patch --ignore-if-in-upstream" '
38
39 git format-patch --stdout master..side >patch0 &&
40 cnt=`grep "^From " patch0 | wc -l` &&
8780bd8f 41 test $cnt = 3
ece3c67f
JH
42
43'
44
45test_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` &&
8780bd8f 50 test $cnt = 2
ece3c67f
JH
51
52'
53
54test_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` &&
8780bd8f 59 test $cnt = 2
ece3c67f
JH
60'
61
62test_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` &&
8780bd8f 67 test $cnt = 2
ece3c67f
JH
68'
69
816366e2
JH
70test_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
76test_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
83test_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
a8d8173e
DB
89test_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 &&
1ba08363 96 sed -e "/^$/q" patch2 > hdrs2 &&
a8d8173e
DB
97 grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs2 &&
98 grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs2
3b2eb186 99
a8d8173e
DB
100'
101
7d22708b 102test_expect_success 'extra headers without newlines' '
a8d8173e
DB
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 &&
1ba08363 107 sed -e "/^$/q" patch3 > hdrs3 &&
a8d8173e
DB
108 grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs3 &&
109 grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs3
3b2eb186 110
a8d8173e
DB
111'
112
3ee79d9f 113test_expect_success 'extra headers with multiple To:s' '
a8d8173e
DB
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 &&
1ba08363 118 sed -e "/^$/q" patch4 > hdrs4 &&
a8d8173e
DB
119 grep "^To: R. E. Cipient <rcipient@example.com>,$" hdrs4 &&
120 grep "^ *S. E. Cipient <scipient@example.com>$" hdrs4
121'
122
736cc67d
DB
123test_expect_success 'additional command line cc' '
124
125 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
1ba08363 126 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^$/q" >patch5 &&
736cc67d
DB
127 grep "^Cc: R. E. Cipient <rcipient@example.com>,$" patch5 &&
128 grep "^ *S. E. Cipient <scipient@example.com>$" patch5
129'
130
7d812145
DB
131test_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
484cf6c3
TR
139check_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
162cat >> expect.no-threading <<EOF
163---
164---
165---
166EOF
167
168test_expect_success 'no threading' '
7d812145 169 git checkout side &&
484cf6c3 170 check_threading expect.no-threading master
7d812145
DB
171'
172
484cf6c3
TR
173cat > expect.thread <<EOF
174---
175Message-Id: <0>
176---
177Message-Id: <1>
178In-Reply-To: <0>
179References: <0>
180---
181Message-Id: <2>
182In-Reply-To: <0>
183References: <0>
184EOF
7d812145 185
484cf6c3
TR
186test_expect_success 'thread' '
187 check_threading expect.thread --thread master
7d812145
DB
188'
189
484cf6c3
TR
190cat > expect.in-reply-to <<EOF
191---
192Message-Id: <0>
193In-Reply-To: <1>
194References: <1>
195---
196Message-Id: <2>
197In-Reply-To: <1>
198References: <1>
199---
200Message-Id: <3>
201In-Reply-To: <1>
202References: <1>
203EOF
a5a27c79 204
484cf6c3
TR
205test_expect_success 'thread in-reply-to' '
206 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
207 --thread master
a5a27c79
DB
208'
209
484cf6c3
TR
210cat > expect.cover-letter <<EOF
211---
212Message-Id: <0>
213---
214Message-Id: <1>
215In-Reply-To: <0>
216References: <0>
217---
218Message-Id: <2>
219In-Reply-To: <0>
220References: <0>
221---
222Message-Id: <3>
223In-Reply-To: <0>
224References: <0>
225EOF
a5a27c79 226
484cf6c3
TR
227test_expect_success 'thread cover-letter' '
228 check_threading expect.cover-letter --cover-letter --thread master
229'
230
231cat > expect.cl-irt <<EOF
232---
233Message-Id: <0>
234In-Reply-To: <1>
235References: <1>
236---
237Message-Id: <2>
2175c10d 238In-Reply-To: <0>
484cf6c3 239References: <1>
2175c10d 240 <0>
484cf6c3
TR
241---
242Message-Id: <3>
2175c10d 243In-Reply-To: <0>
484cf6c3 244References: <1>
2175c10d 245 <0>
484cf6c3
TR
246---
247Message-Id: <4>
2175c10d 248In-Reply-To: <0>
484cf6c3 249References: <1>
2175c10d 250 <0>
484cf6c3
TR
251EOF
252
253test_expect_success 'thread cover-letter in-reply-to' '
254 check_threading expect.cl-irt --cover-letter \
255 --in-reply-to="<test.message>" --thread master
a5a27c79
DB
256'
257
30984ed2
TR
258test_expect_success 'thread explicit shallow' '
259 check_threading expect.cl-irt --cover-letter \
260 --in-reply-to="<test.message>" --thread=shallow master
261'
262
263cat > expect.deep <<EOF
264---
265Message-Id: <0>
266---
267Message-Id: <1>
268In-Reply-To: <0>
269References: <0>
270---
271Message-Id: <2>
272In-Reply-To: <1>
273References: <0>
274 <1>
275EOF
276
277test_expect_success 'thread deep' '
278 check_threading expect.deep --thread=deep master
279'
280
281cat > expect.deep-irt <<EOF
282---
283Message-Id: <0>
284In-Reply-To: <1>
285References: <1>
286---
287Message-Id: <2>
288In-Reply-To: <0>
289References: <1>
290 <0>
291---
292Message-Id: <3>
293In-Reply-To: <2>
294References: <1>
295 <0>
296 <2>
297EOF
298
299test_expect_success 'thread deep in-reply-to' '
300 check_threading expect.deep-irt --thread=deep \
301 --in-reply-to="<test.message>" master
302'
303
304cat > expect.deep-cl <<EOF
305---
306Message-Id: <0>
307---
308Message-Id: <1>
309In-Reply-To: <0>
310References: <0>
311---
312Message-Id: <2>
313In-Reply-To: <1>
314References: <0>
315 <1>
316---
317Message-Id: <3>
318In-Reply-To: <2>
319References: <0>
320 <1>
321 <2>
322EOF
323
324test_expect_success 'thread deep cover-letter' '
325 check_threading expect.deep-cl --cover-letter --thread=deep master
326'
327
328cat > expect.deep-cl-irt <<EOF
329---
330Message-Id: <0>
331In-Reply-To: <1>
332References: <1>
333---
334Message-Id: <2>
335In-Reply-To: <0>
336References: <1>
337 <0>
338---
339Message-Id: <3>
340In-Reply-To: <2>
341References: <1>
342 <0>
343 <2>
344---
345Message-Id: <4>
346In-Reply-To: <3>
347References: <1>
348 <0>
349 <2>
350 <3>
351EOF
352
353test_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
358test_expect_success 'thread via config' '
359 git config format.thread true &&
360 check_threading expect.thread master
361'
362
363test_expect_success 'thread deep via config' '
364 git config format.thread deep &&
365 check_threading expect.deep master
366'
367
368test_expect_success 'thread config + override' '
369 git config format.thread deep &&
370 check_threading expect.thread --thread master
371'
372
373test_expect_success 'thread config + --no-thread' '
374 git config format.thread deep &&
375 check_threading expect.no-threading --no-thread master
376'
377
7d812145
DB
378test_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
5d02294c
JS
389test_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'
859c4fbe
JS
399
400cat > 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
408EOF
409
410test_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 &&
3af82863 414 test_cmp expect output
859c4fbe
JS
415
416'
417
68daa64d
JK
418cat > expect << EOF
419---
420 file | 16 ++++++++++++++++
421 1 files changed, 16 insertions(+), 0 deletions(-)
422
423diff --git a/file b/file
424index 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
433EOF
434
435test_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
9800a754
JH
443test_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
461test_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
480test_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
ece3c67f 493test_done