Merge branch 'jl/maint-pull-tags-doc'
[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 &&
6426f2d2 15 test_tick &&
ece3c67f
JH
16 git commit -m Initial &&
17 git checkout -b side &&
18
19 for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
1f553918 20 test_chmod +x elif &&
6426f2d2 21 test_tick &&
816366e2 22 git commit -m "Side changes #1" &&
ece3c67f
JH
23
24 for i in D E F; do echo "$i"; done >>file &&
25 git update-index file &&
6426f2d2 26 test_tick &&
816366e2 27 git commit -m "Side changes #2" &&
982b64e4 28 git tag C2 &&
ece3c67f
JH
29
30 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
31 git update-index file &&
6426f2d2 32 test_tick &&
816366e2 33 git commit -m "Side changes #3 with \\n backslash-n in it." &&
ece3c67f
JH
34
35 git checkout master &&
982b64e4 36 git diff-tree -p C2 | git apply --index &&
6426f2d2 37 test_tick &&
982b64e4 38 git commit -m "Master accepts moral equivalent of #2"
ece3c67f
JH
39
40'
41
42test_expect_success "format-patch --ignore-if-in-upstream" '
43
44 git format-patch --stdout master..side >patch0 &&
45 cnt=`grep "^From " patch0 | wc -l` &&
8780bd8f 46 test $cnt = 3
ece3c67f
JH
47
48'
49
50test_expect_success "format-patch --ignore-if-in-upstream" '
51
52 git format-patch --stdout \
53 --ignore-if-in-upstream master..side >patch1 &&
54 cnt=`grep "^From " patch1 | wc -l` &&
8780bd8f 55 test $cnt = 2
ece3c67f
JH
56
57'
58
2c642ed8
RR
59test_expect_success "format-patch doesn't consider merge commits" '
60
61 git checkout -b slave master &&
62 echo "Another line" >>file &&
63 test_tick &&
64 git commit -am "Slave change #1" &&
65 echo "Yet another line" >>file &&
66 test_tick &&
67 git commit -am "Slave change #2" &&
68 git checkout -b merger master &&
69 test_tick &&
70 git merge --no-ff slave &&
71 cnt=`git format-patch -3 --stdout | grep "^From " | wc -l` &&
72 test $cnt = 3
73'
74
ece3c67f
JH
75test_expect_success "format-patch result applies" '
76
77 git checkout -b rebuild-0 master &&
78 git am -3 patch0 &&
79 cnt=`git rev-list master.. | wc -l` &&
8780bd8f 80 test $cnt = 2
ece3c67f
JH
81'
82
83test_expect_success "format-patch --ignore-if-in-upstream result applies" '
84
85 git checkout -b rebuild-1 master &&
86 git am -3 patch1 &&
87 cnt=`git rev-list master.. | wc -l` &&
8780bd8f 88 test $cnt = 2
ece3c67f
JH
89'
90
816366e2
JH
91test_expect_success 'commit did not screw up the log message' '
92
93 git cat-file commit side | grep "^Side .* with .* backslash-n"
94
95'
96
97test_expect_success 'format-patch did not screw up the log message' '
98
99 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
100 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
101
102'
103
104test_expect_success 'replay did not screw up the log message' '
105
106 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
107
108'
109
a8d8173e
DB
110test_expect_success 'extra headers' '
111
112 git config format.headers "To: R. E. Cipient <rcipient@example.com>
113" &&
114 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
115" &&
116 git format-patch --stdout master..side > patch2 &&
9524cf29
SB
117 sed -e "/^\$/q" patch2 > hdrs2 &&
118 grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 &&
119 grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2
3b2eb186 120
a8d8173e
DB
121'
122
7d22708b 123test_expect_success 'extra headers without newlines' '
a8d8173e
DB
124
125 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
126 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
127 git format-patch --stdout master..side >patch3 &&
9524cf29
SB
128 sed -e "/^\$/q" patch3 > hdrs3 &&
129 grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 &&
130 grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3
3b2eb186 131
a8d8173e
DB
132'
133
3ee79d9f 134test_expect_success 'extra headers with multiple To:s' '
a8d8173e
DB
135
136 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
137 git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
138 git format-patch --stdout master..side > patch4 &&
9524cf29
SB
139 sed -e "/^\$/q" patch4 > hdrs4 &&
140 grep "^To: R. E. Cipient <rcipient@example.com>,\$" hdrs4 &&
141 grep "^ *S. E. Cipient <scipient@example.com>\$" hdrs4
a8d8173e
DB
142'
143
736cc67d
DB
144test_expect_success 'additional command line cc' '
145
146 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
9524cf29
SB
147 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
148 grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch5 &&
149 grep "^ *S. E. Cipient <scipient@example.com>\$" patch5
736cc67d
DB
150'
151
d7d9c2d0
MH
152test_expect_success 'command line headers' '
153
154 git config --unset-all format.headers &&
9524cf29
SB
155 git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
156 grep "^Cc: R. E. Cipient <rcipient@example.com>\$" patch6
d7d9c2d0
MH
157'
158
159test_expect_success 'configuration headers and command line headers' '
160
161 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
9524cf29
SB
162 git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
163 grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch7 &&
164 grep "^ *S. E. Cipient <scipient@example.com>\$" patch7
d7d9c2d0
MH
165'
166
ae6c098f
SD
167test_expect_success 'command line To: header' '
168
169 git config --unset-all format.headers &&
170 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
171 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch8
172'
173
174test_expect_success 'configuration To: header' '
175
176 git config format.to "R. E. Cipient <rcipient@example.com>" &&
177 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
178 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9
179'
180
c4260034
SB
181test_expect_success '--no-to overrides config.to' '
182
183 git config --replace-all format.to \
184 "R. E. Cipient <rcipient@example.com>" &&
185 git format-patch --no-to --stdout master..side |
186 sed -e "/^\$/q" >patch10 &&
187 ! grep "^To: R. E. Cipient <rcipient@example.com>\$" patch10
188'
189
190test_expect_success '--no-to and --to replaces config.to' '
191
192 git config --replace-all format.to \
193 "Someone <someone@out.there>" &&
194 git format-patch --no-to --to="Someone Else <else@out.there>" \
195 --stdout master..side |
196 sed -e "/^\$/q" >patch11 &&
197 ! grep "^To: Someone <someone@out.there>\$" patch11 &&
198 grep "^To: Someone Else <else@out.there>\$" patch11
199'
200
201test_expect_success '--no-cc overrides config.cc' '
202
203 git config --replace-all format.cc \
204 "C. E. Cipient <rcipient@example.com>" &&
205 git format-patch --no-cc --stdout master..side |
206 sed -e "/^\$/q" >patch12 &&
207 ! grep "^Cc: C. E. Cipient <rcipient@example.com>\$" patch12
208'
209
210test_expect_success '--no-add-headers overrides config.headers' '
211
212 git config --replace-all format.headers \
213 "Header1: B. E. Cipient <rcipient@example.com>" &&
214 git format-patch --no-add-headers --stdout master..side |
215 sed -e "/^\$/q" >patch13 &&
216 ! grep "^Header1: B. E. Cipient <rcipient@example.com>\$" patch13
217'
218
7d812145
DB
219test_expect_success 'multiple files' '
220
221 rm -rf patches/ &&
222 git checkout side &&
223 git format-patch -o patches/ master &&
224 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
225'
226
484cf6c3
TR
227check_threading () {
228 expect="$1" &&
229 shift &&
230 (git format-patch --stdout "$@"; echo $? > status.out) |
231 # Prints everything between the Message-ID and In-Reply-To,
232 # and replaces all Message-ID-lookalikes by a sequence number
233 perl -ne '
234 if (/^(message-id|references|in-reply-to)/i) {
235 $printing = 1;
236 } elsif (/^\S/) {
237 $printing = 0;
238 }
239 if ($printing) {
240 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
241 for $k (keys %h) {s/$k/$h{$k}/};
242 print;
243 }
244 print "---\n" if /^From /i;
245 ' > actual &&
246 test 0 = "$(cat status.out)" &&
247 test_cmp "$expect" actual
248}
249
250cat >> expect.no-threading <<EOF
251---
252---
253---
254EOF
255
256test_expect_success 'no threading' '
7d812145 257 git checkout side &&
484cf6c3 258 check_threading expect.no-threading master
7d812145
DB
259'
260
484cf6c3
TR
261cat > expect.thread <<EOF
262---
263Message-Id: <0>
264---
265Message-Id: <1>
266In-Reply-To: <0>
267References: <0>
268---
269Message-Id: <2>
270In-Reply-To: <0>
271References: <0>
272EOF
7d812145 273
484cf6c3
TR
274test_expect_success 'thread' '
275 check_threading expect.thread --thread master
7d812145
DB
276'
277
484cf6c3
TR
278cat > expect.in-reply-to <<EOF
279---
280Message-Id: <0>
281In-Reply-To: <1>
282References: <1>
283---
284Message-Id: <2>
285In-Reply-To: <1>
286References: <1>
287---
288Message-Id: <3>
289In-Reply-To: <1>
290References: <1>
291EOF
a5a27c79 292
484cf6c3
TR
293test_expect_success 'thread in-reply-to' '
294 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
295 --thread master
a5a27c79
DB
296'
297
484cf6c3
TR
298cat > expect.cover-letter <<EOF
299---
300Message-Id: <0>
301---
302Message-Id: <1>
303In-Reply-To: <0>
304References: <0>
305---
306Message-Id: <2>
307In-Reply-To: <0>
308References: <0>
309---
310Message-Id: <3>
311In-Reply-To: <0>
312References: <0>
313EOF
a5a27c79 314
484cf6c3
TR
315test_expect_success 'thread cover-letter' '
316 check_threading expect.cover-letter --cover-letter --thread master
317'
318
319cat > expect.cl-irt <<EOF
320---
321Message-Id: <0>
322In-Reply-To: <1>
323References: <1>
324---
325Message-Id: <2>
2175c10d 326In-Reply-To: <0>
484cf6c3 327References: <1>
2175c10d 328 <0>
484cf6c3
TR
329---
330Message-Id: <3>
2175c10d 331In-Reply-To: <0>
484cf6c3 332References: <1>
2175c10d 333 <0>
484cf6c3
TR
334---
335Message-Id: <4>
2175c10d 336In-Reply-To: <0>
484cf6c3 337References: <1>
2175c10d 338 <0>
484cf6c3
TR
339EOF
340
341test_expect_success 'thread cover-letter in-reply-to' '
342 check_threading expect.cl-irt --cover-letter \
343 --in-reply-to="<test.message>" --thread master
a5a27c79
DB
344'
345
30984ed2
TR
346test_expect_success 'thread explicit shallow' '
347 check_threading expect.cl-irt --cover-letter \
348 --in-reply-to="<test.message>" --thread=shallow master
349'
350
351cat > expect.deep <<EOF
352---
353Message-Id: <0>
354---
355Message-Id: <1>
356In-Reply-To: <0>
357References: <0>
358---
359Message-Id: <2>
360In-Reply-To: <1>
361References: <0>
362 <1>
363EOF
364
365test_expect_success 'thread deep' '
366 check_threading expect.deep --thread=deep master
367'
368
369cat > expect.deep-irt <<EOF
370---
371Message-Id: <0>
372In-Reply-To: <1>
373References: <1>
374---
375Message-Id: <2>
376In-Reply-To: <0>
377References: <1>
378 <0>
379---
380Message-Id: <3>
381In-Reply-To: <2>
382References: <1>
383 <0>
384 <2>
385EOF
386
387test_expect_success 'thread deep in-reply-to' '
388 check_threading expect.deep-irt --thread=deep \
389 --in-reply-to="<test.message>" master
390'
391
392cat > expect.deep-cl <<EOF
393---
394Message-Id: <0>
395---
396Message-Id: <1>
397In-Reply-To: <0>
398References: <0>
399---
400Message-Id: <2>
401In-Reply-To: <1>
402References: <0>
403 <1>
404---
405Message-Id: <3>
406In-Reply-To: <2>
407References: <0>
408 <1>
409 <2>
410EOF
411
412test_expect_success 'thread deep cover-letter' '
413 check_threading expect.deep-cl --cover-letter --thread=deep master
414'
415
416cat > expect.deep-cl-irt <<EOF
417---
418Message-Id: <0>
419In-Reply-To: <1>
420References: <1>
421---
422Message-Id: <2>
423In-Reply-To: <0>
424References: <1>
425 <0>
426---
427Message-Id: <3>
428In-Reply-To: <2>
429References: <1>
430 <0>
431 <2>
432---
433Message-Id: <4>
434In-Reply-To: <3>
435References: <1>
436 <0>
437 <2>
438 <3>
439EOF
440
441test_expect_success 'thread deep cover-letter in-reply-to' '
442 check_threading expect.deep-cl-irt --cover-letter \
443 --in-reply-to="<test.message>" --thread=deep master
444'
445
446test_expect_success 'thread via config' '
447 git config format.thread true &&
448 check_threading expect.thread master
449'
450
451test_expect_success 'thread deep via config' '
452 git config format.thread deep &&
453 check_threading expect.deep master
454'
455
456test_expect_success 'thread config + override' '
457 git config format.thread deep &&
458 check_threading expect.thread --thread master
459'
460
461test_expect_success 'thread config + --no-thread' '
462 git config format.thread deep &&
463 check_threading expect.no-threading --no-thread master
464'
465
7d812145
DB
466test_expect_success 'excessive subject' '
467
468 rm -rf patches/ &&
469 git checkout side &&
470 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
471 git update-index file &&
472 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." &&
473 git format-patch -o patches/ master..side &&
474 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
475'
476
5d02294c
JS
477test_expect_success 'cover-letter inherits diff options' '
478
479 git mv file foo &&
480 git commit -m foo &&
481 git format-patch --cover-letter -1 &&
9524cf29 482 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
5d02294c 483 git format-patch --cover-letter -1 -M &&
9524cf29 484 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
5d02294c
JS
485
486'
859c4fbe
JS
487
488cat > expect << EOF
489 This is an excessively long subject line for a message due to the
490 habit some projects have of not having a short, one-line subject at
491 the start of the commit message, but rather sticking a whole
492 paragraph right at the start as the only thing in the commit
493 message. It had better not become the filename for the patch.
494 foo
495
496EOF
497
498test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
499
500 git format-patch --cover-letter -2 &&
9524cf29 501 sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
3af82863 502 test_cmp expect output
859c4fbe
JS
503
504'
505
68daa64d
JK
506cat > expect << EOF
507---
508 file | 16 ++++++++++++++++
509 1 files changed, 16 insertions(+), 0 deletions(-)
510
511diff --git a/file b/file
512index 40f36c6..2dc5c23 100644
513--- a/file
514+++ b/file
515@@ -13,4 +13,20 @@ C
516 10
517 D
518 E
519 F
520+5
521EOF
522
523test_expect_success 'format-patch respects -U' '
524
525 git format-patch -U4 -2 &&
9524cf29 526 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
68daa64d
JK
527 test_cmp expect output
528
529'
530
1d46f2ea
JK
531cat > expect << EOF
532
533diff --git a/file b/file
534index 40f36c6..2dc5c23 100644
535--- a/file
536+++ b/file
537@@ -14,3 +14,19 @@ C
538 D
539 E
540 F
541+5
542EOF
543
544test_expect_success 'format-patch -p suppresses stat' '
545
546 git format-patch -p -2 &&
9524cf29 547 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
1d46f2ea
JK
548 test_cmp expect output
549
550'
551
9800a754
JH
552test_expect_success 'format-patch from a subdirectory (1)' '
553 filename=$(
554 rm -rf sub &&
555 mkdir -p sub/dir &&
556 cd sub/dir &&
557 git format-patch -1
558 ) &&
559 case "$filename" in
560 0*)
561 ;; # ok
562 *)
563 echo "Oops? $filename"
564 false
565 ;;
566 esac &&
567 test -f "$filename"
568'
569
570test_expect_success 'format-patch from a subdirectory (2)' '
571 filename=$(
572 rm -rf sub &&
573 mkdir -p sub/dir &&
574 cd sub/dir &&
575 git format-patch -1 -o ..
576 ) &&
577 case "$filename" in
578 ../0*)
579 ;; # ok
580 *)
581 echo "Oops? $filename"
582 false
583 ;;
584 esac &&
585 basename=$(expr "$filename" : ".*/\(.*\)") &&
586 test -f "sub/$basename"
587'
588
589test_expect_success 'format-patch from a subdirectory (3)' '
9800a754
JH
590 rm -f 0* &&
591 filename=$(
592 rm -rf sub &&
593 mkdir -p sub/dir &&
594 cd sub/dir &&
91c8b825 595 git format-patch -1 -o "$TRASH_DIRECTORY"
9800a754
JH
596 ) &&
597 basename=$(expr "$filename" : ".*/\(.*\)") &&
598 test -f "$basename"
599'
600
f044fe2d
SB
601test_expect_success 'format-patch --in-reply-to' '
602 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
603 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
604 grep "^References: <baz@foo.bar>" patch8
605'
606
607test_expect_success 'format-patch --signoff' '
608 git format-patch -1 --signoff --stdout |
609 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
610'
611
02bc5b03
BG
612echo "fatal: --name-only does not make sense" > expect.name-only
613echo "fatal: --name-status does not make sense" > expect.name-status
614echo "fatal: --check does not make sense" > expect.check
615
616test_expect_success 'options no longer allowed for format-patch' '
617 test_must_fail git format-patch --name-only 2> output &&
618 test_cmp expect.name-only output &&
619 test_must_fail git format-patch --name-status 2> output &&
620 test_cmp expect.name-status output &&
621 test_must_fail git format-patch --check 2> output &&
622 test_cmp expect.check output'
623
624test_expect_success 'format-patch --numstat should produce a patch' '
4fa80cf0
JS
625 git format-patch --numstat --stdout master..side > output &&
626 test 6 = $(grep "^diff --git a/" output | wc -l)'
02bc5b03 627
7e93d3b9
FC
628test_expect_success 'format-patch -- <path>' '
629 git format-patch master..side -- file 2>error &&
630 ! grep "Use .--" error
631'
632
657ab61e
KB
633test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
634 git format-patch --ignore-if-in-upstream HEAD
635'
636
6622d9c7
SB
637test_expect_success 'format-patch --signature' '
638 git format-patch --stdout --signature="my sig" -1 >output &&
639 grep "my sig" output
640'
641
642test_expect_success 'format-patch with format.signature config' '
643 git config format.signature "config sig" &&
644 git format-patch --stdout -1 >output &&
645 grep "config sig" output
646'
647
648test_expect_success 'format-patch --signature overrides format.signature' '
649 git config format.signature "config sig" &&
650 git format-patch --stdout --signature="overrides" -1 >output &&
651 ! grep "config sig" output &&
652 grep "overrides" output
653'
654
655test_expect_success 'format-patch --no-signature ignores format.signature' '
656 git config format.signature "config sig" &&
657 git format-patch --stdout --signature="my sig" --no-signature \
658 -1 >output &&
659 ! grep "config sig" output &&
660 ! grep "my sig" output &&
661 ! grep "^-- \$" output
662'
663
664test_expect_success 'format-patch --signature --cover-letter' '
665 git config --unset-all format.signature &&
666 git format-patch --stdout --signature="my sig" --cover-letter \
667 -1 >output &&
668 grep "my sig" output &&
669 test 2 = $(grep "my sig" output | wc -l)
670'
671
672test_expect_success 'format.signature="" supresses signatures' '
673 git config format.signature "" &&
674 git format-patch --stdout -1 >output &&
675 ! grep "^-- \$" output
676'
677
678test_expect_success 'format-patch --no-signature supresses signatures' '
679 git config --unset-all format.signature &&
680 git format-patch --stdout --no-signature -1 >output &&
681 ! grep "^-- \$" output
682'
683
684test_expect_success 'format-patch --signature="" supresses signatures' '
685 git format-patch --signature="" -1 >output &&
686 ! grep "^-- \$" output
687'
688
ece3c67f 689test_done