format-patch: append --signature after notes
[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 doesn't consider merge commits" '
61
62         git checkout -b slave master &&
63         echo "Another line" >>file &&
64         test_tick &&
65         git commit -am "Slave change #1" &&
66         echo "Yet another line" >>file &&
67         test_tick &&
68         git commit -am "Slave change #2" &&
69         git checkout -b merger master &&
70         test_tick &&
71         git merge --no-ff slave &&
72         cnt=`git format-patch -3 --stdout | grep "^From " | wc -l` &&
73         test $cnt = 3
74 '
75
76 test_expect_success "format-patch result applies" '
77
78         git checkout -b rebuild-0 master &&
79         git am -3 patch0 &&
80         cnt=`git rev-list master.. | wc -l` &&
81         test $cnt = 2
82 '
83
84 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
85
86         git checkout -b rebuild-1 master &&
87         git am -3 patch1 &&
88         cnt=`git rev-list master.. | wc -l` &&
89         test $cnt = 2
90 '
91
92 test_expect_success 'commit did not screw up the log message' '
93
94         git cat-file commit side | grep "^Side .* with .* backslash-n"
95
96 '
97
98 test_expect_success 'format-patch did not screw up the log message' '
99
100         grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
101         grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
102
103 '
104
105 test_expect_success 'replay did not screw up the log message' '
106
107         git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
108
109 '
110
111 test_expect_success 'extra headers' '
112
113         git config format.headers "To: R. E. Cipient <rcipient@example.com>
114 " &&
115         git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
116 " &&
117         git format-patch --stdout master..side > patch2 &&
118         sed -e "/^\$/q" patch2 > hdrs2 &&
119         grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 &&
120         grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2
121
122 '
123
124 test_expect_success 'extra headers without newlines' '
125
126         git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
127         git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
128         git format-patch --stdout master..side >patch3 &&
129         sed -e "/^\$/q" patch3 > hdrs3 &&
130         grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 &&
131         grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3
132
133 '
134
135 test_expect_success 'extra headers with multiple To:s' '
136
137         git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
138         git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
139         git format-patch --stdout master..side > patch4 &&
140         sed -e "/^\$/q" patch4 > hdrs4 &&
141         grep "^To: R. E. Cipient <rcipient@example.com>,\$" hdrs4 &&
142         grep "^ *S. E. Cipient <scipient@example.com>\$" hdrs4
143 '
144
145 test_expect_success 'additional command line cc' '
146
147         git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
148         git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
149         grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch5 &&
150         grep "^ *S. E. Cipient <scipient@example.com>\$" patch5
151 '
152
153 test_expect_success 'command line headers' '
154
155         git config --unset-all format.headers &&
156         git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
157         grep "^Cc: R. E. Cipient <rcipient@example.com>\$" patch6
158 '
159
160 test_expect_success 'configuration headers and command line headers' '
161
162         git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
163         git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
164         grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch7 &&
165         grep "^ *S. E. Cipient <scipient@example.com>\$" patch7
166 '
167
168 test_expect_success 'command line To: header' '
169
170         git config --unset-all format.headers &&
171         git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
172         grep "^To: R. E. Cipient <rcipient@example.com>\$" patch8
173 '
174
175 test_expect_success 'configuration To: header' '
176
177         git config format.to "R. E. Cipient <rcipient@example.com>" &&
178         git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
179         grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9
180 '
181
182 # check_patch <patch>: Verify that <patch> looks like a half-sane
183 # patch email to avoid a false positive with !grep
184 check_patch () {
185         grep -e "^From:" "$1" &&
186         grep -e "^Date:" "$1" &&
187         grep -e "^Subject:" "$1"
188 }
189
190 test_expect_success '--no-to overrides config.to' '
191
192         git config --replace-all format.to \
193                 "R. E. Cipient <rcipient@example.com>" &&
194         git format-patch --no-to --stdout master..side |
195         sed -e "/^\$/q" >patch10 &&
196         check_patch patch10 &&
197         ! grep "^To: R. E. Cipient <rcipient@example.com>\$" patch10
198 '
199
200 test_expect_success '--no-to and --to replaces config.to' '
201
202         git config --replace-all format.to \
203                 "Someone <someone@out.there>" &&
204         git format-patch --no-to --to="Someone Else <else@out.there>" \
205                 --stdout master..side |
206         sed -e "/^\$/q" >patch11 &&
207         check_patch patch11 &&
208         ! grep "^To: Someone <someone@out.there>\$" patch11 &&
209         grep "^To: Someone Else <else@out.there>\$" patch11
210 '
211
212 test_expect_success '--no-cc overrides config.cc' '
213
214         git config --replace-all format.cc \
215                 "C. E. Cipient <rcipient@example.com>" &&
216         git format-patch --no-cc --stdout master..side |
217         sed -e "/^\$/q" >patch12 &&
218         check_patch patch12 &&
219         ! grep "^Cc: C. E. Cipient <rcipient@example.com>\$" patch12
220 '
221
222 test_expect_success '--no-add-header overrides config.headers' '
223
224         git config --replace-all format.headers \
225                 "Header1: B. E. Cipient <rcipient@example.com>" &&
226         git format-patch --no-add-header --stdout master..side |
227         sed -e "/^\$/q" >patch13 &&
228         check_patch patch13 &&
229         ! grep "^Header1: B. E. Cipient <rcipient@example.com>\$" patch13
230 '
231
232 test_expect_success 'multiple files' '
233
234         rm -rf patches/ &&
235         git checkout side &&
236         git format-patch -o patches/ master &&
237         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
238 '
239
240 check_threading () {
241         expect="$1" &&
242         shift &&
243         (git format-patch --stdout "$@"; echo $? > status.out) |
244         # Prints everything between the Message-ID and In-Reply-To,
245         # and replaces all Message-ID-lookalikes by a sequence number
246         "$PERL_PATH" -ne '
247                 if (/^(message-id|references|in-reply-to)/i) {
248                         $printing = 1;
249                 } elsif (/^\S/) {
250                         $printing = 0;
251                 }
252                 if ($printing) {
253                         $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
254                         for $k (keys %h) {s/$k/$h{$k}/};
255                         print;
256                 }
257                 print "---\n" if /^From /i;
258         ' > actual &&
259         test 0 = "$(cat status.out)" &&
260         test_cmp "$expect" actual
261 }
262
263 cat >> expect.no-threading <<EOF
264 ---
265 ---
266 ---
267 EOF
268
269 test_expect_success 'no threading' '
270         git checkout side &&
271         check_threading expect.no-threading master
272 '
273
274 cat > expect.thread <<EOF
275 ---
276 Message-Id: <0>
277 ---
278 Message-Id: <1>
279 In-Reply-To: <0>
280 References: <0>
281 ---
282 Message-Id: <2>
283 In-Reply-To: <0>
284 References: <0>
285 EOF
286
287 test_expect_success 'thread' '
288         check_threading expect.thread --thread master
289 '
290
291 cat > expect.in-reply-to <<EOF
292 ---
293 Message-Id: <0>
294 In-Reply-To: <1>
295 References: <1>
296 ---
297 Message-Id: <2>
298 In-Reply-To: <1>
299 References: <1>
300 ---
301 Message-Id: <3>
302 In-Reply-To: <1>
303 References: <1>
304 EOF
305
306 test_expect_success 'thread in-reply-to' '
307         check_threading expect.in-reply-to --in-reply-to="<test.message>" \
308                 --thread master
309 '
310
311 cat > expect.cover-letter <<EOF
312 ---
313 Message-Id: <0>
314 ---
315 Message-Id: <1>
316 In-Reply-To: <0>
317 References: <0>
318 ---
319 Message-Id: <2>
320 In-Reply-To: <0>
321 References: <0>
322 ---
323 Message-Id: <3>
324 In-Reply-To: <0>
325 References: <0>
326 EOF
327
328 test_expect_success 'thread cover-letter' '
329         check_threading expect.cover-letter --cover-letter --thread master
330 '
331
332 cat > expect.cl-irt <<EOF
333 ---
334 Message-Id: <0>
335 In-Reply-To: <1>
336 References: <1>
337 ---
338 Message-Id: <2>
339 In-Reply-To: <0>
340 References: <1>
341         <0>
342 ---
343 Message-Id: <3>
344 In-Reply-To: <0>
345 References: <1>
346         <0>
347 ---
348 Message-Id: <4>
349 In-Reply-To: <0>
350 References: <1>
351         <0>
352 EOF
353
354 test_expect_success 'thread cover-letter in-reply-to' '
355         check_threading expect.cl-irt --cover-letter \
356                 --in-reply-to="<test.message>" --thread master
357 '
358
359 test_expect_success 'thread explicit shallow' '
360         check_threading expect.cl-irt --cover-letter \
361                 --in-reply-to="<test.message>" --thread=shallow master
362 '
363
364 cat > expect.deep <<EOF
365 ---
366 Message-Id: <0>
367 ---
368 Message-Id: <1>
369 In-Reply-To: <0>
370 References: <0>
371 ---
372 Message-Id: <2>
373 In-Reply-To: <1>
374 References: <0>
375         <1>
376 EOF
377
378 test_expect_success 'thread deep' '
379         check_threading expect.deep --thread=deep master
380 '
381
382 cat > expect.deep-irt <<EOF
383 ---
384 Message-Id: <0>
385 In-Reply-To: <1>
386 References: <1>
387 ---
388 Message-Id: <2>
389 In-Reply-To: <0>
390 References: <1>
391         <0>
392 ---
393 Message-Id: <3>
394 In-Reply-To: <2>
395 References: <1>
396         <0>
397         <2>
398 EOF
399
400 test_expect_success 'thread deep in-reply-to' '
401         check_threading expect.deep-irt  --thread=deep \
402                 --in-reply-to="<test.message>" master
403 '
404
405 cat > expect.deep-cl <<EOF
406 ---
407 Message-Id: <0>
408 ---
409 Message-Id: <1>
410 In-Reply-To: <0>
411 References: <0>
412 ---
413 Message-Id: <2>
414 In-Reply-To: <1>
415 References: <0>
416         <1>
417 ---
418 Message-Id: <3>
419 In-Reply-To: <2>
420 References: <0>
421         <1>
422         <2>
423 EOF
424
425 test_expect_success 'thread deep cover-letter' '
426         check_threading expect.deep-cl --cover-letter --thread=deep master
427 '
428
429 cat > expect.deep-cl-irt <<EOF
430 ---
431 Message-Id: <0>
432 In-Reply-To: <1>
433 References: <1>
434 ---
435 Message-Id: <2>
436 In-Reply-To: <0>
437 References: <1>
438         <0>
439 ---
440 Message-Id: <3>
441 In-Reply-To: <2>
442 References: <1>
443         <0>
444         <2>
445 ---
446 Message-Id: <4>
447 In-Reply-To: <3>
448 References: <1>
449         <0>
450         <2>
451         <3>
452 EOF
453
454 test_expect_success 'thread deep cover-letter in-reply-to' '
455         check_threading expect.deep-cl-irt --cover-letter \
456                 --in-reply-to="<test.message>" --thread=deep master
457 '
458
459 test_expect_success 'thread via config' '
460         test_config format.thread true &&
461         check_threading expect.thread master
462 '
463
464 test_expect_success 'thread deep via config' '
465         test_config format.thread deep &&
466         check_threading expect.deep master
467 '
468
469 test_expect_success 'thread config + override' '
470         test_config format.thread deep &&
471         check_threading expect.thread --thread master
472 '
473
474 test_expect_success 'thread config + --no-thread' '
475         test_config format.thread deep &&
476         check_threading expect.no-threading --no-thread master
477 '
478
479 test_expect_success 'excessive subject' '
480
481         rm -rf patches/ &&
482         git checkout side &&
483         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
484         git update-index file &&
485         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." &&
486         git format-patch -o patches/ master..side &&
487         ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
488 '
489
490 test_expect_success 'cover-letter inherits diff options' '
491
492         git mv file foo &&
493         git commit -m foo &&
494         git format-patch --cover-letter -1 &&
495         check_patch 0000-cover-letter.patch &&
496         ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
497         git format-patch --cover-letter -1 -M &&
498         grep "file => foo .* 0 *\$" 0000-cover-letter.patch
499
500 '
501
502 cat > expect << EOF
503   This is an excessively long subject line for a message due to the
504     habit some projects have of not having a short, one-line subject at
505     the start of the commit message, but rather sticking a whole
506     paragraph right at the start as the only thing in the commit
507     message. It had better not become the filename for the patch.
508   foo
509
510 EOF
511
512 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
513
514         git format-patch --cover-letter -2 &&
515         sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
516         test_cmp expect output
517
518 '
519
520 cat > expect << EOF
521 index 40f36c6..2dc5c23 100644
522 --- a/file
523 +++ b/file
524 @@ -13,4 +13,20 @@ C
525  10
526  D
527  E
528  F
529 +5
530 EOF
531
532 test_expect_success 'format-patch respects -U' '
533
534         git format-patch -U4 -2 &&
535         sed -e "1,/^diff/d" -e "/^+5/q" \
536                 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
537                 >output &&
538         test_cmp expect output
539
540 '
541
542 cat > expect << EOF
543
544 diff --git a/file b/file
545 index 40f36c6..2dc5c23 100644
546 --- a/file
547 +++ b/file
548 @@ -14,3 +14,19 @@ C
549  D
550  E
551  F
552 +5
553 EOF
554
555 test_expect_success 'format-patch -p suppresses stat' '
556
557         git format-patch -p -2 &&
558         sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
559         test_cmp expect output
560
561 '
562
563 test_expect_success 'format-patch from a subdirectory (1)' '
564         filename=$(
565                 rm -rf sub &&
566                 mkdir -p sub/dir &&
567                 cd sub/dir &&
568                 git format-patch -1
569         ) &&
570         case "$filename" in
571         0*)
572                 ;; # ok
573         *)
574                 echo "Oops? $filename"
575                 false
576                 ;;
577         esac &&
578         test -f "$filename"
579 '
580
581 test_expect_success 'format-patch from a subdirectory (2)' '
582         filename=$(
583                 rm -rf sub &&
584                 mkdir -p sub/dir &&
585                 cd sub/dir &&
586                 git format-patch -1 -o ..
587         ) &&
588         case "$filename" in
589         ../0*)
590                 ;; # ok
591         *)
592                 echo "Oops? $filename"
593                 false
594                 ;;
595         esac &&
596         basename=$(expr "$filename" : ".*/\(.*\)") &&
597         test -f "sub/$basename"
598 '
599
600 test_expect_success 'format-patch from a subdirectory (3)' '
601         rm -f 0* &&
602         filename=$(
603                 rm -rf sub &&
604                 mkdir -p sub/dir &&
605                 cd sub/dir &&
606                 git format-patch -1 -o "$TRASH_DIRECTORY"
607         ) &&
608         basename=$(expr "$filename" : ".*/\(.*\)") &&
609         test -f "$basename"
610 '
611
612 test_expect_success 'format-patch --in-reply-to' '
613         git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
614         grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
615         grep "^References: <baz@foo.bar>" patch8
616 '
617
618 test_expect_success 'format-patch --signoff' '
619         git format-patch -1 --signoff --stdout >out &&
620         grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
621 '
622
623 test_expect_success 'format-patch --notes --signoff' '
624         git notes --ref test add -m "test message" HEAD &&
625         git format-patch -1 --signoff --stdout --notes=test >out &&
626         # Notes message must come after S-o-b
627         ! sed "/^Signed-off-by: /q" out | grep "test message" &&
628         sed "1,/^Signed-off-by: /d" out | grep "test message"
629 '
630
631 echo "fatal: --name-only does not make sense" > expect.name-only
632 echo "fatal: --name-status does not make sense" > expect.name-status
633 echo "fatal: --check does not make sense" > expect.check
634
635 test_expect_success 'options no longer allowed for format-patch' '
636         test_must_fail git format-patch --name-only 2> output &&
637         test_i18ncmp expect.name-only output &&
638         test_must_fail git format-patch --name-status 2> output &&
639         test_i18ncmp expect.name-status output &&
640         test_must_fail git format-patch --check 2> output &&
641         test_i18ncmp expect.check output'
642
643 test_expect_success 'format-patch --numstat should produce a patch' '
644         git format-patch --numstat --stdout master..side > output &&
645         test 6 = $(grep "^diff --git a/" output | wc -l)'
646
647 test_expect_success 'format-patch -- <path>' '
648         git format-patch master..side -- file 2>error &&
649         ! grep "Use .--" error
650 '
651
652 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
653         git format-patch --ignore-if-in-upstream HEAD
654 '
655
656 test_expect_success 'format-patch --signature' '
657         git format-patch --stdout --signature="my sig" -1 >output &&
658         grep "my sig" output
659 '
660
661 test_expect_success 'format-patch with format.signature config' '
662         git config format.signature "config sig" &&
663         git format-patch --stdout -1 >output &&
664         grep "config sig" output
665 '
666
667 test_expect_success 'format-patch --signature overrides format.signature' '
668         git config format.signature "config sig" &&
669         git format-patch --stdout --signature="overrides" -1 >output &&
670         ! grep "config sig" output &&
671         grep "overrides" output
672 '
673
674 test_expect_success 'format-patch --no-signature ignores format.signature' '
675         git config format.signature "config sig" &&
676         git format-patch --stdout --signature="my sig" --no-signature \
677                 -1 >output &&
678         check_patch output &&
679         ! grep "config sig" output &&
680         ! grep "my sig" output &&
681         ! grep "^-- \$" output
682 '
683
684 test_expect_success 'format-patch --signature --cover-letter' '
685         git config --unset-all format.signature &&
686         git format-patch --stdout --signature="my sig" --cover-letter \
687                 -1 >output &&
688         grep "my sig" output &&
689         test 2 = $(grep "my sig" output | wc -l)
690 '
691
692 test_expect_success 'format.signature="" supresses signatures' '
693         git config format.signature "" &&
694         git format-patch --stdout -1 >output &&
695         check_patch output &&
696         ! grep "^-- \$" output
697 '
698
699 test_expect_success 'format-patch --no-signature supresses signatures' '
700         git config --unset-all format.signature &&
701         git format-patch --stdout --no-signature -1 >output &&
702         check_patch output &&
703         ! grep "^-- \$" output
704 '
705
706 test_expect_success 'format-patch --signature="" supresses signatures' '
707         git format-patch --stdout --signature="" -1 >output &&
708         check_patch output &&
709         ! grep "^-- \$" output
710 '
711
712 test_expect_success TTY 'format-patch --stdout paginates' '
713         rm -f pager_used &&
714         (
715                 GIT_PAGER="wc >pager_used" &&
716                 export GIT_PAGER &&
717                 test_terminal git format-patch --stdout --all
718         ) &&
719         test_path_is_file pager_used
720 '
721
722  test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
723         rm -f pager_used &&
724         (
725                 GIT_PAGER="wc >pager_used" &&
726                 export GIT_PAGER &&
727                 test_terminal git --no-pager format-patch --stdout --all &&
728                 test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
729         ) &&
730         test_path_is_missing pager_used &&
731         test_path_is_missing .git/pager_used
732 '
733
734 test_expect_success 'format-patch handles multi-line subjects' '
735         rm -rf patches/ &&
736         echo content >>file &&
737         for i in one two three; do echo $i; done >msg &&
738         git add file &&
739         git commit -F msg &&
740         git format-patch -o patches -1 &&
741         grep ^Subject: patches/0001-one.patch >actual &&
742         echo "Subject: [PATCH] one two three" >expect &&
743         test_cmp expect actual
744 '
745
746 test_expect_success 'format-patch handles multi-line encoded subjects' '
747         rm -rf patches/ &&
748         echo content >>file &&
749         for i in en två tre; do echo $i; done >msg &&
750         git add file &&
751         git commit -F msg &&
752         git format-patch -o patches -1 &&
753         grep ^Subject: patches/0001-en.patch >actual &&
754         echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
755         test_cmp expect actual
756 '
757
758 M8="foo bar "
759 M64=$M8$M8$M8$M8$M8$M8$M8$M8
760 M512=$M64$M64$M64$M64$M64$M64$M64$M64
761 cat >expect <<'EOF'
762 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
763  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
764  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
765  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
766  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
767  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
768  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
769  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
770  foo bar foo bar foo bar foo bar
771 EOF
772 test_expect_success 'format-patch wraps extremely long headers (ascii)' '
773         echo content >>file &&
774         git add file &&
775         git commit -m "$M512" &&
776         git format-patch --stdout -1 >patch &&
777         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
778         test_cmp expect subject
779 '
780
781 M8="föö bar "
782 M64=$M8$M8$M8$M8$M8$M8$M8$M8
783 M512=$M64$M64$M64$M64$M64$M64$M64$M64
784 cat >expect <<'EOF'
785 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
786  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
787  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
788  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
789  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
790  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
791  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
792  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
793  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
794  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
795  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
796  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
797  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
798  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
799  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
800  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
801  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
802  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
803  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
804  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
805  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
806  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
807 EOF
808 test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
809         rm -rf patches/ &&
810         echo content >>file &&
811         git add file &&
812         git commit -m "$M512" &&
813         git format-patch --stdout -1 >patch &&
814         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
815         test_cmp expect subject
816 '
817
818 M8="foo_bar_"
819 M64=$M8$M8$M8$M8$M8$M8$M8$M8
820 cat >expect <<EOF
821 From: $M64
822  <foobar@foo.bar>
823 EOF
824 test_expect_success 'format-patch wraps non-quotable headers' '
825         rm -rf patches/ &&
826         echo content >>file &&
827         git add file &&
828         git commit -mfoo --author "$M64 <foobar@foo.bar>" &&
829         git format-patch --stdout -1 >patch &&
830         sed -n "/^From: /p; /^ /p; /^$/q" <patch >from &&
831         test_cmp expect from
832 '
833
834 check_author() {
835         echo content >>file &&
836         git add file &&
837         GIT_AUTHOR_NAME=$1 git commit -m author-check &&
838         git format-patch --stdout -1 >patch &&
839         grep ^From: patch >actual &&
840         test_cmp expect actual
841 }
842
843 cat >expect <<'EOF'
844 From: "Foo B. Bar" <author@example.com>
845 EOF
846 test_expect_success 'format-patch quotes dot in headers' '
847         check_author "Foo B. Bar"
848 '
849
850 cat >expect <<'EOF'
851 From: "Foo \"The Baz\" Bar" <author@example.com>
852 EOF
853 test_expect_success 'format-patch quotes double-quote in headers' '
854         check_author "Foo \"The Baz\" Bar"
855 '
856
857 cat >expect <<'EOF'
858 From: =?UTF-8?q?"F=C3=B6o=20B.=20Bar"?= <author@example.com>
859 EOF
860 test_expect_success 'rfc2047-encoded headers also double-quote 822 specials' '
861         check_author "Föo B. Bar"
862 '
863
864 cat >expect <<'EOF'
865 Subject: header with . in it
866 EOF
867 test_expect_success 'subject lines do not have 822 atom-quoting' '
868         echo content >>file &&
869         git add file &&
870         git commit -m "header with . in it" &&
871         git format-patch -k -1 --stdout >patch &&
872         grep ^Subject: patch >actual &&
873         test_cmp expect actual
874 '
875
876 cat >expect <<'EOF'
877 Subject: [PREFIX 1/1] header with . in it
878 EOF
879 test_expect_success 'subject prefixes have space prepended' '
880         git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
881         grep ^Subject: patch >actual &&
882         test_cmp expect actual
883 '
884
885 cat >expect <<'EOF'
886 Subject: [1/1] header with . in it
887 EOF
888 test_expect_success 'empty subject prefix does not have extra space' '
889         git format-patch -n -1 --stdout --subject-prefix= >patch &&
890         grep ^Subject: patch >actual &&
891         test_cmp expect actual
892 '
893
894 test_expect_success 'format patch ignores color.ui' '
895         test_unconfig color.ui &&
896         git format-patch --stdout -1 >expect &&
897         test_config color.ui always &&
898         git format-patch --stdout -1 >actual &&
899         test_cmp expect actual
900 '
901
902 test_done