format-patch: use a string_list for headers
[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 &&
9524cf29
SB
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
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 &&
9524cf29
SB
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
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 &&
9524cf29
SB
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
a8d8173e
DB
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>" &&
9524cf29
SB
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
736cc67d
DB
129'
130
d7d9c2d0
MH
131test_expect_success 'command line headers' '
132
133 git config --unset-all format.headers &&
9524cf29
SB
134 git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
135 grep "^Cc: R. E. Cipient <rcipient@example.com>\$" patch6
d7d9c2d0
MH
136'
137
138test_expect_success 'configuration headers and command line headers' '
139
140 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
9524cf29
SB
141 git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
142 grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch7 &&
143 grep "^ *S. E. Cipient <scipient@example.com>\$" patch7
d7d9c2d0
MH
144'
145
ae6c098f
SD
146test_expect_success 'command line To: header' '
147
148 git config --unset-all format.headers &&
149 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
150 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch8
151'
152
153test_expect_success 'configuration To: header' '
154
155 git config format.to "R. E. Cipient <rcipient@example.com>" &&
156 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
157 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9
158'
159
7d812145
DB
160test_expect_success 'multiple files' '
161
162 rm -rf patches/ &&
163 git checkout side &&
164 git format-patch -o patches/ master &&
165 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
166'
167
484cf6c3
TR
168check_threading () {
169 expect="$1" &&
170 shift &&
171 (git format-patch --stdout "$@"; echo $? > status.out) |
172 # Prints everything between the Message-ID and In-Reply-To,
173 # and replaces all Message-ID-lookalikes by a sequence number
174 perl -ne '
175 if (/^(message-id|references|in-reply-to)/i) {
176 $printing = 1;
177 } elsif (/^\S/) {
178 $printing = 0;
179 }
180 if ($printing) {
181 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
182 for $k (keys %h) {s/$k/$h{$k}/};
183 print;
184 }
185 print "---\n" if /^From /i;
186 ' > actual &&
187 test 0 = "$(cat status.out)" &&
188 test_cmp "$expect" actual
189}
190
191cat >> expect.no-threading <<EOF
192---
193---
194---
195EOF
196
197test_expect_success 'no threading' '
7d812145 198 git checkout side &&
484cf6c3 199 check_threading expect.no-threading master
7d812145
DB
200'
201
484cf6c3
TR
202cat > expect.thread <<EOF
203---
204Message-Id: <0>
205---
206Message-Id: <1>
207In-Reply-To: <0>
208References: <0>
209---
210Message-Id: <2>
211In-Reply-To: <0>
212References: <0>
213EOF
7d812145 214
484cf6c3
TR
215test_expect_success 'thread' '
216 check_threading expect.thread --thread master
7d812145
DB
217'
218
484cf6c3
TR
219cat > expect.in-reply-to <<EOF
220---
221Message-Id: <0>
222In-Reply-To: <1>
223References: <1>
224---
225Message-Id: <2>
226In-Reply-To: <1>
227References: <1>
228---
229Message-Id: <3>
230In-Reply-To: <1>
231References: <1>
232EOF
a5a27c79 233
484cf6c3
TR
234test_expect_success 'thread in-reply-to' '
235 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
236 --thread master
a5a27c79
DB
237'
238
484cf6c3
TR
239cat > expect.cover-letter <<EOF
240---
241Message-Id: <0>
242---
243Message-Id: <1>
244In-Reply-To: <0>
245References: <0>
246---
247Message-Id: <2>
248In-Reply-To: <0>
249References: <0>
250---
251Message-Id: <3>
252In-Reply-To: <0>
253References: <0>
254EOF
a5a27c79 255
484cf6c3
TR
256test_expect_success 'thread cover-letter' '
257 check_threading expect.cover-letter --cover-letter --thread master
258'
259
260cat > expect.cl-irt <<EOF
261---
262Message-Id: <0>
263In-Reply-To: <1>
264References: <1>
265---
266Message-Id: <2>
2175c10d 267In-Reply-To: <0>
484cf6c3 268References: <1>
2175c10d 269 <0>
484cf6c3
TR
270---
271Message-Id: <3>
2175c10d 272In-Reply-To: <0>
484cf6c3 273References: <1>
2175c10d 274 <0>
484cf6c3
TR
275---
276Message-Id: <4>
2175c10d 277In-Reply-To: <0>
484cf6c3 278References: <1>
2175c10d 279 <0>
484cf6c3
TR
280EOF
281
282test_expect_success 'thread cover-letter in-reply-to' '
283 check_threading expect.cl-irt --cover-letter \
284 --in-reply-to="<test.message>" --thread master
a5a27c79
DB
285'
286
30984ed2
TR
287test_expect_success 'thread explicit shallow' '
288 check_threading expect.cl-irt --cover-letter \
289 --in-reply-to="<test.message>" --thread=shallow master
290'
291
292cat > expect.deep <<EOF
293---
294Message-Id: <0>
295---
296Message-Id: <1>
297In-Reply-To: <0>
298References: <0>
299---
300Message-Id: <2>
301In-Reply-To: <1>
302References: <0>
303 <1>
304EOF
305
306test_expect_success 'thread deep' '
307 check_threading expect.deep --thread=deep master
308'
309
310cat > expect.deep-irt <<EOF
311---
312Message-Id: <0>
313In-Reply-To: <1>
314References: <1>
315---
316Message-Id: <2>
317In-Reply-To: <0>
318References: <1>
319 <0>
320---
321Message-Id: <3>
322In-Reply-To: <2>
323References: <1>
324 <0>
325 <2>
326EOF
327
328test_expect_success 'thread deep in-reply-to' '
329 check_threading expect.deep-irt --thread=deep \
330 --in-reply-to="<test.message>" master
331'
332
333cat > expect.deep-cl <<EOF
334---
335Message-Id: <0>
336---
337Message-Id: <1>
338In-Reply-To: <0>
339References: <0>
340---
341Message-Id: <2>
342In-Reply-To: <1>
343References: <0>
344 <1>
345---
346Message-Id: <3>
347In-Reply-To: <2>
348References: <0>
349 <1>
350 <2>
351EOF
352
353test_expect_success 'thread deep cover-letter' '
354 check_threading expect.deep-cl --cover-letter --thread=deep master
355'
356
357cat > expect.deep-cl-irt <<EOF
358---
359Message-Id: <0>
360In-Reply-To: <1>
361References: <1>
362---
363Message-Id: <2>
364In-Reply-To: <0>
365References: <1>
366 <0>
367---
368Message-Id: <3>
369In-Reply-To: <2>
370References: <1>
371 <0>
372 <2>
373---
374Message-Id: <4>
375In-Reply-To: <3>
376References: <1>
377 <0>
378 <2>
379 <3>
380EOF
381
382test_expect_success 'thread deep cover-letter in-reply-to' '
383 check_threading expect.deep-cl-irt --cover-letter \
384 --in-reply-to="<test.message>" --thread=deep master
385'
386
387test_expect_success 'thread via config' '
388 git config format.thread true &&
389 check_threading expect.thread master
390'
391
392test_expect_success 'thread deep via config' '
393 git config format.thread deep &&
394 check_threading expect.deep master
395'
396
397test_expect_success 'thread config + override' '
398 git config format.thread deep &&
399 check_threading expect.thread --thread master
400'
401
402test_expect_success 'thread config + --no-thread' '
403 git config format.thread deep &&
404 check_threading expect.no-threading --no-thread master
405'
406
7d812145
DB
407test_expect_success 'excessive subject' '
408
409 rm -rf patches/ &&
410 git checkout side &&
411 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
412 git update-index file &&
413 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." &&
414 git format-patch -o patches/ master..side &&
415 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
416'
417
5d02294c
JS
418test_expect_success 'cover-letter inherits diff options' '
419
420 git mv file foo &&
421 git commit -m foo &&
422 git format-patch --cover-letter -1 &&
9524cf29 423 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
5d02294c 424 git format-patch --cover-letter -1 -M &&
9524cf29 425 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
5d02294c
JS
426
427'
859c4fbe
JS
428
429cat > expect << EOF
430 This is an excessively long subject line for a message due to the
431 habit some projects have of not having a short, one-line subject at
432 the start of the commit message, but rather sticking a whole
433 paragraph right at the start as the only thing in the commit
434 message. It had better not become the filename for the patch.
435 foo
436
437EOF
438
439test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
440
441 git format-patch --cover-letter -2 &&
9524cf29 442 sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
3af82863 443 test_cmp expect output
859c4fbe
JS
444
445'
446
68daa64d
JK
447cat > expect << EOF
448---
449 file | 16 ++++++++++++++++
450 1 files changed, 16 insertions(+), 0 deletions(-)
451
452diff --git a/file b/file
453index 40f36c6..2dc5c23 100644
454--- a/file
455+++ b/file
456@@ -13,4 +13,20 @@ C
457 10
458 D
459 E
460 F
461+5
462EOF
463
464test_expect_success 'format-patch respects -U' '
465
466 git format-patch -U4 -2 &&
9524cf29 467 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
68daa64d
JK
468 test_cmp expect output
469
470'
471
1d46f2ea
JK
472cat > expect << EOF
473
474diff --git a/file b/file
475index 40f36c6..2dc5c23 100644
476--- a/file
477+++ b/file
478@@ -14,3 +14,19 @@ C
479 D
480 E
481 F
482+5
483EOF
484
485test_expect_success 'format-patch -p suppresses stat' '
486
487 git format-patch -p -2 &&
9524cf29 488 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
1d46f2ea
JK
489 test_cmp expect output
490
491'
492
9800a754
JH
493test_expect_success 'format-patch from a subdirectory (1)' '
494 filename=$(
495 rm -rf sub &&
496 mkdir -p sub/dir &&
497 cd sub/dir &&
498 git format-patch -1
499 ) &&
500 case "$filename" in
501 0*)
502 ;; # ok
503 *)
504 echo "Oops? $filename"
505 false
506 ;;
507 esac &&
508 test -f "$filename"
509'
510
511test_expect_success 'format-patch from a subdirectory (2)' '
512 filename=$(
513 rm -rf sub &&
514 mkdir -p sub/dir &&
515 cd sub/dir &&
516 git format-patch -1 -o ..
517 ) &&
518 case "$filename" in
519 ../0*)
520 ;; # ok
521 *)
522 echo "Oops? $filename"
523 false
524 ;;
525 esac &&
526 basename=$(expr "$filename" : ".*/\(.*\)") &&
527 test -f "sub/$basename"
528'
529
530test_expect_success 'format-patch from a subdirectory (3)' '
9800a754
JH
531 rm -f 0* &&
532 filename=$(
533 rm -rf sub &&
534 mkdir -p sub/dir &&
535 cd sub/dir &&
91c8b825 536 git format-patch -1 -o "$TRASH_DIRECTORY"
9800a754
JH
537 ) &&
538 basename=$(expr "$filename" : ".*/\(.*\)") &&
539 test -f "$basename"
540'
541
f044fe2d
SB
542test_expect_success 'format-patch --in-reply-to' '
543 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
544 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
545 grep "^References: <baz@foo.bar>" patch8
546'
547
548test_expect_success 'format-patch --signoff' '
549 git format-patch -1 --signoff --stdout |
550 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
551'
552
02bc5b03
BG
553echo "fatal: --name-only does not make sense" > expect.name-only
554echo "fatal: --name-status does not make sense" > expect.name-status
555echo "fatal: --check does not make sense" > expect.check
556
557test_expect_success 'options no longer allowed for format-patch' '
558 test_must_fail git format-patch --name-only 2> output &&
559 test_cmp expect.name-only output &&
560 test_must_fail git format-patch --name-status 2> output &&
561 test_cmp expect.name-status output &&
562 test_must_fail git format-patch --check 2> output &&
563 test_cmp expect.check output'
564
565test_expect_success 'format-patch --numstat should produce a patch' '
4fa80cf0
JS
566 git format-patch --numstat --stdout master..side > output &&
567 test 6 = $(grep "^diff --git a/" output | wc -l)'
02bc5b03 568
7e93d3b9
FC
569test_expect_success 'format-patch -- <path>' '
570 git format-patch master..side -- file 2>error &&
571 ! grep "Use .--" error
572'
573
ece3c67f 574test_done