cvsimport: apply shell-quoting regex globally
[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 . "$TEST_DIRECTORY"/lib-terminal.sh
10
11 test_expect_success setup '
12
13         for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
14         cat file >elif &&
15         git add file elif &&
16         test_tick &&
17         git commit -m Initial &&
18         git checkout -b side &&
19
20         for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
21         test_chmod +x elif &&
22         test_tick &&
23         git commit -m "Side changes #1" &&
24
25         for i in D E F; do echo "$i"; done >>file &&
26         git update-index file &&
27         test_tick &&
28         git commit -m "Side changes #2" &&
29         git tag C2 &&
30
31         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
32         git update-index file &&
33         test_tick &&
34         git commit -m "Side changes #3 with \\n backslash-n in it." &&
35
36         git checkout master &&
37         git diff-tree -p C2 | git apply --index &&
38         test_tick &&
39         git commit -m "Master accepts moral equivalent of #2"
40
41 '
42
43 test_expect_success "format-patch --ignore-if-in-upstream" '
44
45         git format-patch --stdout master..side >patch0 &&
46         cnt=$(grep "^From " patch0 | wc -l) &&
47         test $cnt = 3
48
49 '
50
51 test_expect_success "format-patch --ignore-if-in-upstream" '
52
53         git format-patch --stdout \
54                 --ignore-if-in-upstream master..side >patch1 &&
55         cnt=$(grep "^From " patch1 | wc -l) &&
56         test $cnt = 2
57
58 '
59
60 test_expect_success "format-patch --ignore-if-in-upstream handles tags" '
61         git tag -a v1 -m tag side &&
62         git tag -a v2 -m tag master &&
63         git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
64         cnt=$(grep "^From " patch1 | wc -l) &&
65         test $cnt = 2
66 '
67
68 test_expect_success "format-patch doesn't consider merge commits" '
69
70         git checkout -b slave master &&
71         echo "Another line" >>file &&
72         test_tick &&
73         git commit -am "Slave change #1" &&
74         echo "Yet another line" >>file &&
75         test_tick &&
76         git commit -am "Slave change #2" &&
77         git checkout -b merger master &&
78         test_tick &&
79         git merge --no-ff slave &&
80         cnt=$(git format-patch -3 --stdout | grep "^From " | wc -l) &&
81         test $cnt = 3
82 '
83
84 test_expect_success "format-patch result applies" '
85
86         git checkout -b rebuild-0 master &&
87         git am -3 patch0 &&
88         cnt=$(git rev-list master.. | wc -l) &&
89         test $cnt = 2
90 '
91
92 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
93
94         git checkout -b rebuild-1 master &&
95         git am -3 patch1 &&
96         cnt=$(git rev-list master.. | wc -l) &&
97         test $cnt = 2
98 '
99
100 test_expect_success 'commit did not screw up the log message' '
101
102         git cat-file commit side | grep "^Side .* with .* backslash-n"
103
104 '
105
106 test_expect_success 'format-patch did not screw up the log message' '
107
108         grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
109         grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
110
111 '
112
113 test_expect_success 'replay did not screw up the log message' '
114
115         git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
116
117 '
118
119 test_expect_success 'extra headers' '
120
121         git config format.headers "To: R E Cipient <rcipient@example.com>
122 " &&
123         git config --add format.headers "Cc: S E Cipient <scipient@example.com>
124 " &&
125         git format-patch --stdout master..side > patch2 &&
126         sed -e "/^\$/q" patch2 > hdrs2 &&
127         grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
128         grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
129
130 '
131
132 test_expect_success 'extra headers without newlines' '
133
134         git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
135         git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
136         git format-patch --stdout master..side >patch3 &&
137         sed -e "/^\$/q" patch3 > hdrs3 &&
138         grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
139         grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
140
141 '
142
143 test_expect_success 'extra headers with multiple To:s' '
144
145         git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
146         git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
147         git format-patch --stdout master..side > patch4 &&
148         sed -e "/^\$/q" patch4 > hdrs4 &&
149         grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
150         grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
151 '
152
153 test_expect_success 'additional command line cc (ascii)' '
154
155         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
156         git format-patch --cc="S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
157         grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
158         grep "^ *S E Cipient <scipient@example.com>\$" patch5
159 '
160
161 test_expect_failure 'additional command line cc (rfc822)' '
162
163         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
164         git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
165         grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
166         grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" patch5
167 '
168
169 test_expect_success 'command line headers' '
170
171         git config --unset-all format.headers &&
172         git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
173         grep "^Cc: R E Cipient <rcipient@example.com>\$" patch6
174 '
175
176 test_expect_success 'configuration headers and command line headers' '
177
178         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
179         git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
180         grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch7 &&
181         grep "^ *S E Cipient <scipient@example.com>\$" patch7
182 '
183
184 test_expect_success 'command line To: header (ascii)' '
185
186         git config --unset-all format.headers &&
187         git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
188         grep "^To: R E Cipient <rcipient@example.com>\$" patch8
189 '
190
191 test_expect_failure 'command line To: header (rfc822)' '
192
193         git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
194         grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch8
195 '
196
197 test_expect_failure 'command line To: header (rfc2047)' '
198
199         git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
200         grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch8
201 '
202
203 test_expect_success 'configuration To: header (ascii)' '
204
205         git config format.to "R E Cipient <rcipient@example.com>" &&
206         git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
207         grep "^To: R E Cipient <rcipient@example.com>\$" patch9
208 '
209
210 test_expect_failure 'configuration To: header (rfc822)' '
211
212         git config format.to "R. E. Cipient <rcipient@example.com>" &&
213         git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
214         grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch9
215 '
216
217 test_expect_failure 'configuration To: header (rfc2047)' '
218
219         git config format.to "R Ä Cipient <rcipient@example.com>" &&
220         git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
221         grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch9
222 '
223
224 # check_patch <patch>: Verify that <patch> looks like a half-sane
225 # patch email to avoid a false positive with !grep
226 check_patch () {
227         grep -e "^From:" "$1" &&
228         grep -e "^Date:" "$1" &&
229         grep -e "^Subject:" "$1"
230 }
231
232 test_expect_success '--no-to overrides config.to' '
233
234         git config --replace-all format.to \
235                 "R E Cipient <rcipient@example.com>" &&
236         git format-patch --no-to --stdout master..side |
237         sed -e "/^\$/q" >patch10 &&
238         check_patch patch10 &&
239         ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10
240 '
241
242 test_expect_success '--no-to and --to replaces config.to' '
243
244         git config --replace-all format.to \
245                 "Someone <someone@out.there>" &&
246         git format-patch --no-to --to="Someone Else <else@out.there>" \
247                 --stdout master..side |
248         sed -e "/^\$/q" >patch11 &&
249         check_patch patch11 &&
250         ! grep "^To: Someone <someone@out.there>\$" patch11 &&
251         grep "^To: Someone Else <else@out.there>\$" patch11
252 '
253
254 test_expect_success '--no-cc overrides config.cc' '
255
256         git config --replace-all format.cc \
257                 "C E Cipient <rcipient@example.com>" &&
258         git format-patch --no-cc --stdout master..side |
259         sed -e "/^\$/q" >patch12 &&
260         check_patch patch12 &&
261         ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12
262 '
263
264 test_expect_success '--no-add-header overrides config.headers' '
265
266         git config --replace-all format.headers \
267                 "Header1: B E Cipient <rcipient@example.com>" &&
268         git format-patch --no-add-header --stdout master..side |
269         sed -e "/^\$/q" >patch13 &&
270         check_patch patch13 &&
271         ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13
272 '
273
274 test_expect_success 'multiple files' '
275
276         rm -rf patches/ &&
277         git checkout side &&
278         git format-patch -o patches/ master &&
279         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
280 '
281
282 test_expect_success 'reroll count' '
283         rm -fr patches &&
284         git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
285         ! grep -v "^patches/v4-000[0-3]-" list &&
286         sed -n -e "/^Subject: /p" $(cat list) >subjects &&
287         ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
288 '
289
290 test_expect_success 'reroll count (-v)' '
291         rm -fr patches &&
292         git format-patch -o patches --cover-letter -v4 master..side >list &&
293         ! grep -v "^patches/v4-000[0-3]-" list &&
294         sed -n -e "/^Subject: /p" $(cat list) >subjects &&
295         ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
296 '
297
298 check_threading () {
299         expect="$1" &&
300         shift &&
301         (git format-patch --stdout "$@"; echo $? > status.out) |
302         # Prints everything between the Message-ID and In-Reply-To,
303         # and replaces all Message-ID-lookalikes by a sequence number
304         perl -ne '
305                 if (/^(message-id|references|in-reply-to)/i) {
306                         $printing = 1;
307                 } elsif (/^\S/) {
308                         $printing = 0;
309                 }
310                 if ($printing) {
311                         $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
312                         for $k (keys %h) {s/$k/$h{$k}/};
313                         print;
314                 }
315                 print "---\n" if /^From /i;
316         ' > actual &&
317         test 0 = "$(cat status.out)" &&
318         test_cmp "$expect" actual
319 }
320
321 cat >> expect.no-threading <<EOF
322 ---
323 ---
324 ---
325 EOF
326
327 test_expect_success 'no threading' '
328         git checkout side &&
329         check_threading expect.no-threading master
330 '
331
332 cat > expect.thread <<EOF
333 ---
334 Message-Id: <0>
335 ---
336 Message-Id: <1>
337 In-Reply-To: <0>
338 References: <0>
339 ---
340 Message-Id: <2>
341 In-Reply-To: <0>
342 References: <0>
343 EOF
344
345 test_expect_success 'thread' '
346         check_threading expect.thread --thread master
347 '
348
349 cat > expect.in-reply-to <<EOF
350 ---
351 Message-Id: <0>
352 In-Reply-To: <1>
353 References: <1>
354 ---
355 Message-Id: <2>
356 In-Reply-To: <1>
357 References: <1>
358 ---
359 Message-Id: <3>
360 In-Reply-To: <1>
361 References: <1>
362 EOF
363
364 test_expect_success 'thread in-reply-to' '
365         check_threading expect.in-reply-to --in-reply-to="<test.message>" \
366                 --thread master
367 '
368
369 cat > expect.cover-letter <<EOF
370 ---
371 Message-Id: <0>
372 ---
373 Message-Id: <1>
374 In-Reply-To: <0>
375 References: <0>
376 ---
377 Message-Id: <2>
378 In-Reply-To: <0>
379 References: <0>
380 ---
381 Message-Id: <3>
382 In-Reply-To: <0>
383 References: <0>
384 EOF
385
386 test_expect_success 'thread cover-letter' '
387         check_threading expect.cover-letter --cover-letter --thread master
388 '
389
390 cat > expect.cl-irt <<EOF
391 ---
392 Message-Id: <0>
393 In-Reply-To: <1>
394 References: <1>
395 ---
396 Message-Id: <2>
397 In-Reply-To: <0>
398 References: <1>
399         <0>
400 ---
401 Message-Id: <3>
402 In-Reply-To: <0>
403 References: <1>
404         <0>
405 ---
406 Message-Id: <4>
407 In-Reply-To: <0>
408 References: <1>
409         <0>
410 EOF
411
412 test_expect_success 'thread cover-letter in-reply-to' '
413         check_threading expect.cl-irt --cover-letter \
414                 --in-reply-to="<test.message>" --thread master
415 '
416
417 test_expect_success 'thread explicit shallow' '
418         check_threading expect.cl-irt --cover-letter \
419                 --in-reply-to="<test.message>" --thread=shallow master
420 '
421
422 cat > expect.deep <<EOF
423 ---
424 Message-Id: <0>
425 ---
426 Message-Id: <1>
427 In-Reply-To: <0>
428 References: <0>
429 ---
430 Message-Id: <2>
431 In-Reply-To: <1>
432 References: <0>
433         <1>
434 EOF
435
436 test_expect_success 'thread deep' '
437         check_threading expect.deep --thread=deep master
438 '
439
440 cat > expect.deep-irt <<EOF
441 ---
442 Message-Id: <0>
443 In-Reply-To: <1>
444 References: <1>
445 ---
446 Message-Id: <2>
447 In-Reply-To: <0>
448 References: <1>
449         <0>
450 ---
451 Message-Id: <3>
452 In-Reply-To: <2>
453 References: <1>
454         <0>
455         <2>
456 EOF
457
458 test_expect_success 'thread deep in-reply-to' '
459         check_threading expect.deep-irt  --thread=deep \
460                 --in-reply-to="<test.message>" master
461 '
462
463 cat > expect.deep-cl <<EOF
464 ---
465 Message-Id: <0>
466 ---
467 Message-Id: <1>
468 In-Reply-To: <0>
469 References: <0>
470 ---
471 Message-Id: <2>
472 In-Reply-To: <1>
473 References: <0>
474         <1>
475 ---
476 Message-Id: <3>
477 In-Reply-To: <2>
478 References: <0>
479         <1>
480         <2>
481 EOF
482
483 test_expect_success 'thread deep cover-letter' '
484         check_threading expect.deep-cl --cover-letter --thread=deep master
485 '
486
487 cat > expect.deep-cl-irt <<EOF
488 ---
489 Message-Id: <0>
490 In-Reply-To: <1>
491 References: <1>
492 ---
493 Message-Id: <2>
494 In-Reply-To: <0>
495 References: <1>
496         <0>
497 ---
498 Message-Id: <3>
499 In-Reply-To: <2>
500 References: <1>
501         <0>
502         <2>
503 ---
504 Message-Id: <4>
505 In-Reply-To: <3>
506 References: <1>
507         <0>
508         <2>
509         <3>
510 EOF
511
512 test_expect_success 'thread deep cover-letter in-reply-to' '
513         check_threading expect.deep-cl-irt --cover-letter \
514                 --in-reply-to="<test.message>" --thread=deep master
515 '
516
517 test_expect_success 'thread via config' '
518         test_config format.thread true &&
519         check_threading expect.thread master
520 '
521
522 test_expect_success 'thread deep via config' '
523         test_config format.thread deep &&
524         check_threading expect.deep master
525 '
526
527 test_expect_success 'thread config + override' '
528         test_config format.thread deep &&
529         check_threading expect.thread --thread master
530 '
531
532 test_expect_success 'thread config + --no-thread' '
533         test_config format.thread deep &&
534         check_threading expect.no-threading --no-thread master
535 '
536
537 test_expect_success 'excessive subject' '
538
539         rm -rf patches/ &&
540         git checkout side &&
541         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
542         git update-index file &&
543         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." &&
544         git format-patch -o patches/ master..side &&
545         ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
546 '
547
548 test_expect_success 'cover-letter inherits diff options' '
549
550         git mv file foo &&
551         git commit -m foo &&
552         git format-patch --no-renames --cover-letter -1 &&
553         check_patch 0000-cover-letter.patch &&
554         ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
555         git format-patch --cover-letter -1 -M &&
556         grep "file => foo .* 0 *\$" 0000-cover-letter.patch
557
558 '
559
560 cat > expect << EOF
561   This is an excessively long subject line for a message due to the
562     habit some projects have of not having a short, one-line subject at
563     the start of the commit message, but rather sticking a whole
564     paragraph right at the start as the only thing in the commit
565     message. It had better not become the filename for the patch.
566   foo
567
568 EOF
569
570 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
571
572         git format-patch --cover-letter -2 &&
573         sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
574         test_cmp expect output
575
576 '
577
578 cat > expect << EOF
579 index 40f36c6..2dc5c23 100644
580 --- a/file
581 +++ b/file
582 @@ -13,4 +13,20 @@ C
583  10
584  D
585  E
586  F
587 +5
588 EOF
589
590 test_expect_success 'format-patch respects -U' '
591
592         git format-patch -U4 -2 &&
593         sed -e "1,/^diff/d" -e "/^+5/q" \
594                 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
595                 >output &&
596         test_cmp expect output
597
598 '
599
600 cat > expect << EOF
601
602 diff --git a/file b/file
603 index 40f36c6..2dc5c23 100644
604 --- a/file
605 +++ b/file
606 @@ -14,3 +14,19 @@ C
607  D
608  E
609  F
610 +5
611 EOF
612
613 test_expect_success 'format-patch -p suppresses stat' '
614
615         git format-patch -p -2 &&
616         sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
617         test_cmp expect output
618
619 '
620
621 test_expect_success 'format-patch from a subdirectory (1)' '
622         filename=$(
623                 rm -rf sub &&
624                 mkdir -p sub/dir &&
625                 cd sub/dir &&
626                 git format-patch -1
627         ) &&
628         case "$filename" in
629         0*)
630                 ;; # ok
631         *)
632                 echo "Oops? $filename"
633                 false
634                 ;;
635         esac &&
636         test -f "$filename"
637 '
638
639 test_expect_success 'format-patch from a subdirectory (2)' '
640         filename=$(
641                 rm -rf sub &&
642                 mkdir -p sub/dir &&
643                 cd sub/dir &&
644                 git format-patch -1 -o ..
645         ) &&
646         case "$filename" in
647         ../0*)
648                 ;; # ok
649         *)
650                 echo "Oops? $filename"
651                 false
652                 ;;
653         esac &&
654         basename=$(expr "$filename" : ".*/\(.*\)") &&
655         test -f "sub/$basename"
656 '
657
658 test_expect_success 'format-patch from a subdirectory (3)' '
659         rm -f 0* &&
660         filename=$(
661                 rm -rf sub &&
662                 mkdir -p sub/dir &&
663                 cd sub/dir &&
664                 git format-patch -1 -o "$TRASH_DIRECTORY"
665         ) &&
666         basename=$(expr "$filename" : ".*/\(.*\)") &&
667         test -f "$basename"
668 '
669
670 test_expect_success 'format-patch --in-reply-to' '
671         git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
672         grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
673         grep "^References: <baz@foo.bar>" patch8
674 '
675
676 test_expect_success 'format-patch --signoff' '
677         git format-patch -1 --signoff --stdout >out &&
678         grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
679 '
680
681 test_expect_success 'format-patch --notes --signoff' '
682         git notes --ref test add -m "test message" HEAD &&
683         git format-patch -1 --signoff --stdout --notes=test >out &&
684         # Three dashes must come after S-o-b
685         ! sed "/^Signed-off-by: /q" out | grep "test message" &&
686         sed "1,/^Signed-off-by: /d" out | grep "test message" &&
687         # Notes message must come after three dashes
688         ! sed "/^---$/q" out | grep "test message" &&
689         sed "1,/^---$/d" out | grep "test message"
690 '
691
692 echo "fatal: --name-only does not make sense" > expect.name-only
693 echo "fatal: --name-status does not make sense" > expect.name-status
694 echo "fatal: --check does not make sense" > expect.check
695
696 test_expect_success 'options no longer allowed for format-patch' '
697         test_must_fail git format-patch --name-only 2> output &&
698         test_i18ncmp expect.name-only output &&
699         test_must_fail git format-patch --name-status 2> output &&
700         test_i18ncmp expect.name-status output &&
701         test_must_fail git format-patch --check 2> output &&
702         test_i18ncmp expect.check output'
703
704 test_expect_success 'format-patch --numstat should produce a patch' '
705         git format-patch --numstat --stdout master..side > output &&
706         test 5 = $(grep "^diff --git a/" output | wc -l)'
707
708 test_expect_success 'format-patch -- <path>' '
709         git format-patch master..side -- file 2>error &&
710         ! grep "Use .--" error
711 '
712
713 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
714         git format-patch --ignore-if-in-upstream HEAD
715 '
716
717 test_expect_success 'format-patch --signature' '
718         git format-patch --stdout --signature="my sig" -1 >output &&
719         grep "my sig" output
720 '
721
722 test_expect_success 'format-patch with format.signature config' '
723         git config format.signature "config sig" &&
724         git format-patch --stdout -1 >output &&
725         grep "config sig" output
726 '
727
728 test_expect_success 'format-patch --signature overrides format.signature' '
729         git config format.signature "config sig" &&
730         git format-patch --stdout --signature="overrides" -1 >output &&
731         ! grep "config sig" output &&
732         grep "overrides" output
733 '
734
735 test_expect_success 'format-patch --no-signature ignores format.signature' '
736         git config format.signature "config sig" &&
737         git format-patch --stdout --signature="my sig" --no-signature \
738                 -1 >output &&
739         check_patch output &&
740         ! grep "config sig" output &&
741         ! grep "my sig" output &&
742         ! grep "^-- \$" output
743 '
744
745 test_expect_success 'format-patch --signature --cover-letter' '
746         git config --unset-all format.signature &&
747         git format-patch --stdout --signature="my sig" --cover-letter \
748                 -1 >output &&
749         grep "my sig" output &&
750         test 2 = $(grep "my sig" output | wc -l)
751 '
752
753 test_expect_success 'format.signature="" suppresses signatures' '
754         git config format.signature "" &&
755         git format-patch --stdout -1 >output &&
756         check_patch output &&
757         ! grep "^-- \$" output
758 '
759
760 test_expect_success 'format-patch --no-signature suppresses signatures' '
761         git config --unset-all format.signature &&
762         git format-patch --stdout --no-signature -1 >output &&
763         check_patch output &&
764         ! grep "^-- \$" output
765 '
766
767 test_expect_success 'format-patch --signature="" suppresses signatures' '
768         git format-patch --stdout --signature="" -1 >output &&
769         check_patch output &&
770         ! grep "^-- \$" output
771 '
772
773 test_expect_success 'prepare mail-signature input' '
774         cat >mail-signature <<-\EOF
775
776         Test User <test.email@kernel.org>
777         http://git.kernel.org/cgit/git/git.git
778
779         git.kernel.org/?p=git/git.git;a=summary
780
781         EOF
782 '
783
784 test_expect_success '--signature-file=file works' '
785         git format-patch --stdout --signature-file=mail-signature -1 >output &&
786         check_patch output &&
787         sed -e "1,/^-- \$/d" <output >actual &&
788         {
789                 cat mail-signature && echo
790         } >expect &&
791         test_cmp expect actual
792 '
793
794 test_expect_success 'format.signaturefile works' '
795         test_config format.signaturefile mail-signature &&
796         git format-patch --stdout -1 >output &&
797         check_patch output &&
798         sed -e "1,/^-- \$/d" <output >actual &&
799         {
800                 cat mail-signature && echo
801         } >expect &&
802         test_cmp expect actual
803 '
804
805 test_expect_success '--no-signature suppresses format.signaturefile ' '
806         test_config format.signaturefile mail-signature &&
807         git format-patch --stdout --no-signature -1 >output &&
808         check_patch output &&
809         ! grep "^-- \$" output
810 '
811
812 test_expect_success '--signature-file overrides format.signaturefile' '
813         cat >other-mail-signature <<-\EOF &&
814         Use this other signature instead of mail-signature.
815         EOF
816         test_config format.signaturefile mail-signature &&
817         git format-patch --stdout \
818                         --signature-file=other-mail-signature -1 >output &&
819         check_patch output &&
820         sed -e "1,/^-- \$/d" <output >actual &&
821         {
822                 cat other-mail-signature && echo
823         } >expect &&
824         test_cmp expect actual
825 '
826
827 test_expect_success '--signature overrides format.signaturefile' '
828         test_config format.signaturefile mail-signature &&
829         git format-patch --stdout --signature="my sig" -1 >output &&
830         check_patch output &&
831         grep "my sig" output
832 '
833
834 test_expect_success TTY 'format-patch --stdout paginates' '
835         rm -f pager_used &&
836         test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
837         test_path_is_file pager_used
838 '
839
840  test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
841         rm -f pager_used &&
842         test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
843         test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
844         test_path_is_missing pager_used &&
845         test_path_is_missing .git/pager_used
846 '
847
848 test_expect_success 'format-patch handles multi-line subjects' '
849         rm -rf patches/ &&
850         echo content >>file &&
851         for i in one two three; do echo $i; done >msg &&
852         git add file &&
853         git commit -F msg &&
854         git format-patch -o patches -1 &&
855         grep ^Subject: patches/0001-one.patch >actual &&
856         echo "Subject: [PATCH] one two three" >expect &&
857         test_cmp expect actual
858 '
859
860 test_expect_success 'format-patch handles multi-line encoded subjects' '
861         rm -rf patches/ &&
862         echo content >>file &&
863         for i in en två tre; do echo $i; done >msg &&
864         git add file &&
865         git commit -F msg &&
866         git format-patch -o patches -1 &&
867         grep ^Subject: patches/0001-en.patch >actual &&
868         echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
869         test_cmp expect actual
870 '
871
872 M8="foo bar "
873 M64=$M8$M8$M8$M8$M8$M8$M8$M8
874 M512=$M64$M64$M64$M64$M64$M64$M64$M64
875 cat >expect <<'EOF'
876 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
877  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
878  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
879  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
880  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
881  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
882  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
883 EOF
884 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
885         echo content >>file &&
886         git add file &&
887         git commit -m "$M512" &&
888         git format-patch --stdout -1 >patch &&
889         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
890         test_cmp expect subject
891 '
892
893 M8="föö bar "
894 M64=$M8$M8$M8$M8$M8$M8$M8$M8
895 M512=$M64$M64$M64$M64$M64$M64$M64$M64
896 cat >expect <<'EOF'
897 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
898  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
899  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
900  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
901  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
902  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
903  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
904  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
905  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
906  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
907  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
908  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
909  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
910  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
911  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
912  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
913  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
914  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
915  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
916  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
917  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
918  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
919  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
920  =?UTF-8?q?bar?=
921 EOF
922 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
923         rm -rf patches/ &&
924         echo content >>file &&
925         git add file &&
926         git commit -m "$M512" &&
927         git format-patch --stdout -1 >patch &&
928         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
929         test_cmp expect subject
930 '
931
932 check_author() {
933         echo content >>file &&
934         git add file &&
935         GIT_AUTHOR_NAME=$1 git commit -m author-check &&
936         git format-patch --stdout -1 >patch &&
937         sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
938         test_cmp expect actual
939 }
940
941 cat >expect <<'EOF'
942 From: "Foo B. Bar" <author@example.com>
943 EOF
944 test_expect_success 'format-patch quotes dot in from-headers' '
945         check_author "Foo B. Bar"
946 '
947
948 cat >expect <<'EOF'
949 From: "Foo \"The Baz\" Bar" <author@example.com>
950 EOF
951 test_expect_success 'format-patch quotes double-quote in from-headers' '
952         check_author "Foo \"The Baz\" Bar"
953 '
954
955 cat >expect <<'EOF'
956 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
957 EOF
958 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
959         check_author "Föo Bar"
960 '
961
962 cat >expect <<'EOF'
963 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
964 EOF
965 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
966         check_author "Föo B. Bar"
967 '
968
969 cat >expect <<EOF
970 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
971  <author@example.com>
972 EOF
973 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
974         check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
975 '
976
977 cat >expect <<'EOF'
978 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
979  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
980  Bar Foo Bar Foo Bar Foo Bar <author@example.com>
981 EOF
982 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
983         check_author "Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
984 '
985
986 cat >expect <<'EOF'
987 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
988  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
989  Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
990 EOF
991 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
992         check_author "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
993 '
994
995 cat >expect <<'EOF'
996 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
997  =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
998  =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
999  =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1000  =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1001 EOF
1002 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1003         check_author "Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
1004 '
1005
1006 cat >expect <<'EOF'
1007 Subject: header with . in it
1008 EOF
1009 test_expect_success 'subject lines do not have 822 atom-quoting' '
1010         echo content >>file &&
1011         git add file &&
1012         git commit -m "header with . in it" &&
1013         git format-patch -k -1 --stdout >patch &&
1014         grep ^Subject: patch >actual &&
1015         test_cmp expect actual
1016 '
1017
1018 cat >expect <<'EOF'
1019 Subject: [PREFIX 1/1] header with . in it
1020 EOF
1021 test_expect_success 'subject prefixes have space prepended' '
1022         git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1023         grep ^Subject: patch >actual &&
1024         test_cmp expect actual
1025 '
1026
1027 cat >expect <<'EOF'
1028 Subject: [1/1] header with . in it
1029 EOF
1030 test_expect_success 'empty subject prefix does not have extra space' '
1031         git format-patch -n -1 --stdout --subject-prefix= >patch &&
1032         grep ^Subject: patch >actual &&
1033         test_cmp expect actual
1034 '
1035
1036 test_expect_success '--from=ident notices bogus ident' '
1037         test_must_fail git format-patch -1 --stdout --from=foo >patch
1038 '
1039
1040 test_expect_success '--from=ident replaces author' '
1041         git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1042         cat >expect <<-\EOF &&
1043         From: Me <me@example.com>
1044
1045         From: A U Thor <author@example.com>
1046
1047         EOF
1048         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1049         test_cmp expect patch.head
1050 '
1051
1052 test_expect_success '--from uses committer ident' '
1053         git format-patch -1 --stdout --from >patch &&
1054         cat >expect <<-\EOF &&
1055         From: C O Mitter <committer@example.com>
1056
1057         From: A U Thor <author@example.com>
1058
1059         EOF
1060         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1061         test_cmp expect patch.head
1062 '
1063
1064 test_expect_success '--from omits redundant in-body header' '
1065         git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1066         cat >expect <<-\EOF &&
1067         From: A U Thor <author@example.com>
1068
1069         EOF
1070         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1071         test_cmp expect patch.head
1072 '
1073
1074 test_expect_success 'in-body headers trigger content encoding' '
1075         test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1076         test_when_finished "git reset --hard HEAD^" &&
1077         git format-patch -1 --stdout --from >patch &&
1078         cat >expect <<-\EOF &&
1079         From: C O Mitter <committer@example.com>
1080         Content-Type: text/plain; charset=UTF-8
1081
1082         From: éxötìc <author@example.com>
1083
1084         EOF
1085         sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1086         test_cmp expect patch.head
1087 '
1088
1089 append_signoff()
1090 {
1091         C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1092         git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1093         sed -n -e "1,/^---$/p" append_signoff.patch |
1094                 egrep -n "^Subject|Sign|^$"
1095 }
1096
1097 test_expect_success 'signoff: commit with no body' '
1098         append_signoff </dev/null >actual &&
1099         cat <<\EOF | sed "s/EOL$//" >expected &&
1100 4:Subject: [PATCH] EOL
1101 8:
1102 9:Signed-off-by: C O Mitter <committer@example.com>
1103 EOF
1104         test_cmp expected actual
1105 '
1106
1107 test_expect_success 'signoff: commit with only subject' '
1108         echo subject | append_signoff >actual &&
1109         cat >expected <<\EOF &&
1110 4:Subject: [PATCH] subject
1111 8:
1112 9:Signed-off-by: C O Mitter <committer@example.com>
1113 EOF
1114         test_cmp expected actual
1115 '
1116
1117 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1118         printf subject | append_signoff >actual &&
1119         cat >expected <<\EOF &&
1120 4:Subject: [PATCH] subject
1121 8:
1122 9:Signed-off-by: C O Mitter <committer@example.com>
1123 EOF
1124         test_cmp expected actual
1125 '
1126
1127 test_expect_success 'signoff: no existing signoffs' '
1128         append_signoff <<\EOF >actual &&
1129 subject
1130
1131 body
1132 EOF
1133         cat >expected <<\EOF &&
1134 4:Subject: [PATCH] subject
1135 8:
1136 10:
1137 11:Signed-off-by: C O Mitter <committer@example.com>
1138 EOF
1139         test_cmp expected actual
1140 '
1141
1142 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1143         printf "subject\n\nbody" | append_signoff >actual &&
1144         cat >expected <<\EOF &&
1145 4:Subject: [PATCH] subject
1146 8:
1147 10:
1148 11:Signed-off-by: C O Mitter <committer@example.com>
1149 EOF
1150         test_cmp expected actual
1151 '
1152
1153 test_expect_success 'signoff: some random signoff' '
1154         append_signoff <<\EOF >actual &&
1155 subject
1156
1157 body
1158
1159 Signed-off-by: my@house
1160 EOF
1161         cat >expected <<\EOF &&
1162 4:Subject: [PATCH] subject
1163 8:
1164 10:
1165 11:Signed-off-by: my@house
1166 12:Signed-off-by: C O Mitter <committer@example.com>
1167 EOF
1168         test_cmp expected actual
1169 '
1170
1171 test_expect_success 'signoff: misc conforming footer elements' '
1172         append_signoff <<\EOF >actual &&
1173 subject
1174
1175 body
1176
1177 Signed-off-by: my@house
1178 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1179 Tested-by: Some One <someone@example.com>
1180 Bug: 1234
1181 EOF
1182         cat >expected <<\EOF &&
1183 4:Subject: [PATCH] subject
1184 8:
1185 10:
1186 11:Signed-off-by: my@house
1187 15:Signed-off-by: C O Mitter <committer@example.com>
1188 EOF
1189         test_cmp expected actual
1190 '
1191
1192 test_expect_success 'signoff: some random signoff-alike' '
1193         append_signoff <<\EOF >actual &&
1194 subject
1195
1196 body
1197 Fooled-by-me: my@house
1198 EOF
1199         cat >expected <<\EOF &&
1200 4:Subject: [PATCH] subject
1201 8:
1202 11:
1203 12:Signed-off-by: C O Mitter <committer@example.com>
1204 EOF
1205         test_cmp expected actual
1206 '
1207
1208 test_expect_success 'signoff: not really a signoff' '
1209         append_signoff <<\EOF >actual &&
1210 subject
1211
1212 I want to mention about Signed-off-by: here.
1213 EOF
1214         cat >expected <<\EOF &&
1215 4:Subject: [PATCH] subject
1216 8:
1217 9:I want to mention about Signed-off-by: here.
1218 10:
1219 11:Signed-off-by: C O Mitter <committer@example.com>
1220 EOF
1221         test_cmp expected actual
1222 '
1223
1224 test_expect_success 'signoff: not really a signoff (2)' '
1225         append_signoff <<\EOF >actual &&
1226 subject
1227
1228 My unfortunate
1229 Signed-off-by: example happens to be wrapped here.
1230 EOF
1231         cat >expected <<\EOF &&
1232 4:Subject: [PATCH] subject
1233 8:
1234 10:Signed-off-by: example happens to be wrapped here.
1235 11:
1236 12:Signed-off-by: C O Mitter <committer@example.com>
1237 EOF
1238         test_cmp expected actual
1239 '
1240
1241 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1242         append_signoff <<\EOF >actual &&
1243 subject
1244
1245 Signed-off-by: my@house
1246 Signed-off-by: your@house
1247
1248 A lot of houses.
1249 EOF
1250         cat >expected <<\EOF &&
1251 4:Subject: [PATCH] subject
1252 8:
1253 9:Signed-off-by: my@house
1254 10:Signed-off-by: your@house
1255 11:
1256 13:
1257 14:Signed-off-by: C O Mitter <committer@example.com>
1258 EOF
1259         test_cmp expected actual
1260 '
1261
1262 test_expect_success 'signoff: the same signoff at the end' '
1263         append_signoff <<\EOF >actual &&
1264 subject
1265
1266 body
1267
1268 Signed-off-by: C O Mitter <committer@example.com>
1269 EOF
1270         cat >expected <<\EOF &&
1271 4:Subject: [PATCH] subject
1272 8:
1273 10:
1274 11:Signed-off-by: C O Mitter <committer@example.com>
1275 EOF
1276         test_cmp expected actual
1277 '
1278
1279 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1280         printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1281                 append_signoff >actual &&
1282         cat >expected <<\EOF &&
1283 4:Subject: [PATCH] subject
1284 8:
1285 9:Signed-off-by: C O Mitter <committer@example.com>
1286 EOF
1287         test_cmp expected actual
1288 '
1289
1290 test_expect_success 'signoff: the same signoff NOT at the end' '
1291         append_signoff <<\EOF >actual &&
1292 subject
1293
1294 body
1295
1296 Signed-off-by: C O Mitter <committer@example.com>
1297 Signed-off-by: my@house
1298 EOF
1299         cat >expected <<\EOF &&
1300 4:Subject: [PATCH] subject
1301 8:
1302 10:
1303 11:Signed-off-by: C O Mitter <committer@example.com>
1304 12:Signed-off-by: my@house
1305 EOF
1306         test_cmp expected actual
1307 '
1308
1309 test_expect_success 'signoff: detect garbage in non-conforming footer' '
1310         append_signoff <<\EOF >actual &&
1311 subject
1312
1313 body
1314
1315 Tested-by: my@house
1316 Some Trash
1317 Signed-off-by: C O Mitter <committer@example.com>
1318 EOF
1319         cat >expected <<\EOF &&
1320 4:Subject: [PATCH] subject
1321 8:
1322 10:
1323 13:Signed-off-by: C O Mitter <committer@example.com>
1324 14:
1325 15:Signed-off-by: C O Mitter <committer@example.com>
1326 EOF
1327         test_cmp expected actual
1328 '
1329
1330 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1331         append_signoff <<\EOF >actual &&
1332 subject
1333
1334 body
1335
1336 Reviewed-id: Noone
1337 Tested-by: my@house
1338 Change-id: Ideadbeef
1339 Signed-off-by: C O Mitter <committer@example.com>
1340 Bug: 1234
1341 EOF
1342         cat >expected <<\EOF &&
1343 4:Subject: [PATCH] subject
1344 8:
1345 10:
1346 14:Signed-off-by: C O Mitter <committer@example.com>
1347 EOF
1348         test_cmp expected actual
1349 '
1350
1351 test_expect_success 'format patch ignores color.ui' '
1352         test_unconfig color.ui &&
1353         git format-patch --stdout -1 >expect &&
1354         test_config color.ui always &&
1355         git format-patch --stdout -1 >actual &&
1356         test_cmp expect actual
1357 '
1358
1359 test_expect_success 'cover letter using branch description (1)' '
1360         git checkout rebuild-1 &&
1361         test_config branch.rebuild-1.description hello &&
1362         git format-patch --stdout --cover-letter master >actual &&
1363         grep hello actual >/dev/null
1364 '
1365
1366 test_expect_success 'cover letter using branch description (2)' '
1367         git checkout rebuild-1 &&
1368         test_config branch.rebuild-1.description hello &&
1369         git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1370         grep hello actual >/dev/null
1371 '
1372
1373 test_expect_success 'cover letter using branch description (3)' '
1374         git checkout rebuild-1 &&
1375         test_config branch.rebuild-1.description hello &&
1376         git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1377         grep hello actual >/dev/null
1378 '
1379
1380 test_expect_success 'cover letter using branch description (4)' '
1381         git checkout rebuild-1 &&
1382         test_config branch.rebuild-1.description hello &&
1383         git format-patch --stdout --cover-letter master.. >actual &&
1384         grep hello actual >/dev/null
1385 '
1386
1387 test_expect_success 'cover letter using branch description (5)' '
1388         git checkout rebuild-1 &&
1389         test_config branch.rebuild-1.description hello &&
1390         git format-patch --stdout --cover-letter -2 HEAD >actual &&
1391         grep hello actual >/dev/null
1392 '
1393
1394 test_expect_success 'cover letter using branch description (6)' '
1395         git checkout rebuild-1 &&
1396         test_config branch.rebuild-1.description hello &&
1397         git format-patch --stdout --cover-letter -2 >actual &&
1398         grep hello actual >/dev/null
1399 '
1400
1401 test_expect_success 'cover letter with nothing' '
1402         git format-patch --stdout --cover-letter >actual &&
1403         test_line_count = 0 actual
1404 '
1405
1406 test_expect_success 'cover letter auto' '
1407         mkdir -p tmp &&
1408         test_when_finished "rm -rf tmp;
1409                 git config --unset format.coverletter" &&
1410
1411         git config format.coverletter auto &&
1412         git format-patch -o tmp -1 >list &&
1413         test_line_count = 1 list &&
1414         git format-patch -o tmp -2 >list &&
1415         test_line_count = 3 list
1416 '
1417
1418 test_expect_success 'cover letter auto user override' '
1419         mkdir -p tmp &&
1420         test_when_finished "rm -rf tmp;
1421                 git config --unset format.coverletter" &&
1422
1423         git config format.coverletter auto &&
1424         git format-patch -o tmp --cover-letter -1 >list &&
1425         test_line_count = 2 list &&
1426         git format-patch -o tmp --cover-letter -2 >list &&
1427         test_line_count = 3 list &&
1428         git format-patch -o tmp --no-cover-letter -1 >list &&
1429         test_line_count = 1 list &&
1430         git format-patch -o tmp --no-cover-letter -2 >list &&
1431         test_line_count = 2 list
1432 '
1433
1434 test_expect_success 'format-patch --zero-commit' '
1435         git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1436         grep "^From " patch2 | sort | uniq >actual &&
1437         echo "From $_z40 Mon Sep 17 00:00:00 2001" >expect &&
1438         test_cmp expect actual
1439 '
1440
1441 test_expect_success 'From line has expected format' '
1442         git format-patch --stdout v2..v1 >patch2 &&
1443         grep "^From " patch2 >from &&
1444         grep "^From $_x40 Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1445         test_cmp from filtered
1446 '
1447
1448 test_expect_success 'format-patch format.outputDirectory option' '
1449         test_config format.outputDirectory patches &&
1450         rm -fr patches &&
1451         git format-patch master..side &&
1452         test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1453 '
1454
1455 test_expect_success 'format-patch -o overrides format.outputDirectory' '
1456         test_config format.outputDirectory patches &&
1457         rm -fr patches patchset &&
1458         git format-patch master..side -o patchset &&
1459         test_path_is_missing patches &&
1460         test_path_is_dir patchset
1461 '
1462
1463 test_expect_success 'format-patch --base' '
1464         git checkout side &&
1465         git format-patch --stdout --base=HEAD~3 -1 >patch &&
1466         grep "^base-commit:" patch >actual &&
1467         grep "^prerequisite-patch-id:" patch >>actual &&
1468         echo "base-commit: $(git rev-parse HEAD~3)" >expected &&
1469         echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1470         echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1471         test_cmp expected actual
1472 '
1473
1474 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1475         test_must_fail git format-patch --base=HEAD -2 &&
1476         test_must_fail git format-patch --base=HEAD~1 -2 &&
1477         git format-patch --stdout --base=HEAD~2 -2 >patch &&
1478         grep "^base-commit:" patch >actual &&
1479         echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1480         test_cmp expected actual
1481 '
1482
1483 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1484         # For history as below:
1485         #
1486         #    ---Q---P---Z---Y---*---X
1487         #        \             /
1488         #         ------------W
1489         #
1490         # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1491         git checkout -b topic1 master &&
1492         git rev-parse HEAD >commit-id-base &&
1493         test_commit P &&
1494         git rev-parse HEAD >commit-id-P &&
1495         test_commit Z &&
1496         git rev-parse HEAD >commit-id-Z &&
1497         test_commit Y &&
1498         git checkout -b topic2 master &&
1499         test_commit W &&
1500         git merge topic1 &&
1501         test_commit X &&
1502         test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1503         test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1504         git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1505         grep "^base-commit:" patch >actual &&
1506         echo "base-commit: $(cat commit-id-base)" >expected &&
1507         test_cmp expected actual
1508 '
1509
1510 test_expect_success 'format-patch --base=auto' '
1511         git checkout -b upstream master &&
1512         git checkout -b local upstream &&
1513         git branch --set-upstream-to=upstream &&
1514         test_commit N1 &&
1515         test_commit N2 &&
1516         git format-patch --stdout --base=auto -2 >patch &&
1517         grep "^base-commit:" patch >actual &&
1518         echo "base-commit: $(git rev-parse upstream)" >expected &&
1519         test_cmp expected actual
1520 '
1521
1522 test_expect_success 'format-patch errors out when history involves criss-cross' '
1523         # setup criss-cross history
1524         #
1525         #   B---M1---D
1526         #  / \ /
1527         # A   X
1528         #  \ / \
1529         #   C---M2---E
1530         #
1531         git checkout master &&
1532         test_commit A &&
1533         git checkout -b xb master &&
1534         test_commit B &&
1535         git checkout -b xc master &&
1536         test_commit C &&
1537         git checkout -b xbc xb -- &&
1538         git merge xc &&
1539         git checkout -b xcb xc -- &&
1540         git branch --set-upstream-to=xbc &&
1541         git merge xb &&
1542         git checkout xbc &&
1543         test_commit D &&
1544         git checkout xcb &&
1545         test_commit E &&
1546         test_must_fail  git format-patch --base=auto -1
1547 '
1548
1549 test_expect_success 'format-patch format.useAutoBaseoption' '
1550         test_when_finished "git config --unset format.useAutoBase" &&
1551         git checkout local &&
1552         git config format.useAutoBase true &&
1553         git format-patch --stdout -1 >patch &&
1554         grep "^base-commit:" patch >actual &&
1555         echo "base-commit: $(git rev-parse upstream)" >expected &&
1556         test_cmp expected actual
1557 '
1558
1559 test_expect_success 'format-patch --base overrides format.useAutoBase' '
1560         test_when_finished "git config --unset format.useAutoBase" &&
1561         git config format.useAutoBase true &&
1562         git format-patch --stdout --base=HEAD~1 -1 >patch &&
1563         grep "^base-commit:" patch >actual &&
1564         echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1565         test_cmp expected actual
1566 '
1567
1568 test_done