Merge branch 'js/maint-merge-one-file-osx-expr' into maint
[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 -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 ---
522  file |   16 ++++++++++++++++
523  1 files changed, 16 insertions(+), 0 deletions(-)
524
525 diff --git a/file b/file
526 index 40f36c6..2dc5c23 100644
527 --- a/file
528 +++ b/file
529 @@ -13,4 +13,20 @@ C
530  10
531  D
532  E
533  F
534 +5
535 EOF
536
537 test_expect_success 'format-patch respects -U' '
538
539         git format-patch -U4 -2 &&
540         sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
541         test_cmp expect output
542
543 '
544
545 cat > expect << EOF
546
547 diff --git a/file b/file
548 index 40f36c6..2dc5c23 100644
549 --- a/file
550 +++ b/file
551 @@ -14,3 +14,19 @@ C
552  D
553  E
554  F
555 +5
556 EOF
557
558 test_expect_success 'format-patch -p suppresses stat' '
559
560         git format-patch -p -2 &&
561         sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
562         test_cmp expect output
563
564 '
565
566 test_expect_success 'format-patch from a subdirectory (1)' '
567         filename=$(
568                 rm -rf sub &&
569                 mkdir -p sub/dir &&
570                 cd sub/dir &&
571                 git format-patch -1
572         ) &&
573         case "$filename" in
574         0*)
575                 ;; # ok
576         *)
577                 echo "Oops? $filename"
578                 false
579                 ;;
580         esac &&
581         test -f "$filename"
582 '
583
584 test_expect_success 'format-patch from a subdirectory (2)' '
585         filename=$(
586                 rm -rf sub &&
587                 mkdir -p sub/dir &&
588                 cd sub/dir &&
589                 git format-patch -1 -o ..
590         ) &&
591         case "$filename" in
592         ../0*)
593                 ;; # ok
594         *)
595                 echo "Oops? $filename"
596                 false
597                 ;;
598         esac &&
599         basename=$(expr "$filename" : ".*/\(.*\)") &&
600         test -f "sub/$basename"
601 '
602
603 test_expect_success 'format-patch from a subdirectory (3)' '
604         rm -f 0* &&
605         filename=$(
606                 rm -rf sub &&
607                 mkdir -p sub/dir &&
608                 cd sub/dir &&
609                 git format-patch -1 -o "$TRASH_DIRECTORY"
610         ) &&
611         basename=$(expr "$filename" : ".*/\(.*\)") &&
612         test -f "$basename"
613 '
614
615 test_expect_success 'format-patch --in-reply-to' '
616         git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
617         grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
618         grep "^References: <baz@foo.bar>" patch8
619 '
620
621 test_expect_success 'format-patch --signoff' '
622         git format-patch -1 --signoff --stdout |
623         grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
624 '
625
626 echo "fatal: --name-only does not make sense" > expect.name-only
627 echo "fatal: --name-status does not make sense" > expect.name-status
628 echo "fatal: --check does not make sense" > expect.check
629
630 test_expect_success 'options no longer allowed for format-patch' '
631         test_must_fail git format-patch --name-only 2> output &&
632         test_i18ncmp expect.name-only output &&
633         test_must_fail git format-patch --name-status 2> output &&
634         test_i18ncmp expect.name-status output &&
635         test_must_fail git format-patch --check 2> output &&
636         test_i18ncmp expect.check output'
637
638 test_expect_success 'format-patch --numstat should produce a patch' '
639         git format-patch --numstat --stdout master..side > output &&
640         test 6 = $(grep "^diff --git a/" output | wc -l)'
641
642 test_expect_success 'format-patch -- <path>' '
643         git format-patch master..side -- file 2>error &&
644         ! grep "Use .--" error
645 '
646
647 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
648         git format-patch --ignore-if-in-upstream HEAD
649 '
650
651 test_expect_success 'format-patch --signature' '
652         git format-patch --stdout --signature="my sig" -1 >output &&
653         grep "my sig" output
654 '
655
656 test_expect_success 'format-patch with format.signature config' '
657         git config format.signature "config sig" &&
658         git format-patch --stdout -1 >output &&
659         grep "config sig" output
660 '
661
662 test_expect_success 'format-patch --signature overrides format.signature' '
663         git config format.signature "config sig" &&
664         git format-patch --stdout --signature="overrides" -1 >output &&
665         ! grep "config sig" output &&
666         grep "overrides" output
667 '
668
669 test_expect_success 'format-patch --no-signature ignores format.signature' '
670         git config format.signature "config sig" &&
671         git format-patch --stdout --signature="my sig" --no-signature \
672                 -1 >output &&
673         check_patch output &&
674         ! grep "config sig" output &&
675         ! grep "my sig" output &&
676         ! grep "^-- \$" output
677 '
678
679 test_expect_success 'format-patch --signature --cover-letter' '
680         git config --unset-all format.signature &&
681         git format-patch --stdout --signature="my sig" --cover-letter \
682                 -1 >output &&
683         grep "my sig" output &&
684         test 2 = $(grep "my sig" output | wc -l)
685 '
686
687 test_expect_success 'format.signature="" supresses signatures' '
688         git config format.signature "" &&
689         git format-patch --stdout -1 >output &&
690         check_patch output &&
691         ! grep "^-- \$" output
692 '
693
694 test_expect_success 'format-patch --no-signature supresses signatures' '
695         git config --unset-all format.signature &&
696         git format-patch --stdout --no-signature -1 >output &&
697         check_patch output &&
698         ! grep "^-- \$" output
699 '
700
701 test_expect_success 'format-patch --signature="" supresses signatures' '
702         git format-patch --stdout --signature="" -1 >output &&
703         check_patch output &&
704         ! grep "^-- \$" output
705 '
706
707 test_expect_success TTY 'format-patch --stdout paginates' '
708         rm -f pager_used &&
709         (
710                 GIT_PAGER="wc >pager_used" &&
711                 export GIT_PAGER &&
712                 test_terminal git format-patch --stdout --all
713         ) &&
714         test_path_is_file pager_used
715 '
716
717  test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
718         rm -f pager_used &&
719         (
720                 GIT_PAGER="wc >pager_used" &&
721                 export GIT_PAGER &&
722                 test_terminal git --no-pager format-patch --stdout --all &&
723                 test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
724         ) &&
725         test_path_is_missing pager_used &&
726         test_path_is_missing .git/pager_used
727 '
728
729 test_expect_success 'format-patch handles multi-line subjects' '
730         rm -rf patches/ &&
731         echo content >>file &&
732         for i in one two three; do echo $i; done >msg &&
733         git add file &&
734         git commit -F msg &&
735         git format-patch -o patches -1 &&
736         grep ^Subject: patches/0001-one.patch >actual &&
737         echo "Subject: [PATCH] one two three" >expect &&
738         test_cmp expect actual
739 '
740
741 test_expect_success 'format-patch handles multi-line encoded subjects' '
742         rm -rf patches/ &&
743         echo content >>file &&
744         for i in en två tre; do echo $i; done >msg &&
745         git add file &&
746         git commit -F msg &&
747         git format-patch -o patches -1 &&
748         grep ^Subject: patches/0001-en.patch >actual &&
749         echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
750         test_cmp expect actual
751 '
752
753 M8="foo bar "
754 M64=$M8$M8$M8$M8$M8$M8$M8$M8
755 M512=$M64$M64$M64$M64$M64$M64$M64$M64
756 cat >expect <<'EOF'
757 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
758  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
759  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
760  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
761  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
762  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
763  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
764  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
765  foo bar foo bar foo bar foo bar
766 EOF
767 test_expect_success 'format-patch wraps extremely long headers (ascii)' '
768         echo content >>file &&
769         git add file &&
770         git commit -m "$M512" &&
771         git format-patch --stdout -1 >patch &&
772         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
773         test_cmp expect subject
774 '
775
776 M8="föö bar "
777 M64=$M8$M8$M8$M8$M8$M8$M8$M8
778 M512=$M64$M64$M64$M64$M64$M64$M64$M64
779 cat >expect <<'EOF'
780 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
781  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
782  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
783  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
784  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
785  =?UTF-8?q?=C3=B6=20bar=20f=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?=
802 EOF
803 test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
804         rm -rf patches/ &&
805         echo content >>file &&
806         git add file &&
807         git commit -m "$M512" &&
808         git format-patch --stdout -1 >patch &&
809         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
810         test_cmp expect subject
811 '
812
813 M8="foo_bar_"
814 M64=$M8$M8$M8$M8$M8$M8$M8$M8
815 cat >expect <<EOF
816 From: $M64
817  <foobar@foo.bar>
818 EOF
819 test_expect_success 'format-patch wraps non-quotable headers' '
820         rm -rf patches/ &&
821         echo content >>file &&
822         git add file &&
823         git commit -mfoo --author "$M64 <foobar@foo.bar>" &&
824         git format-patch --stdout -1 >patch &&
825         sed -n "/^From: /p; /^ /p; /^$/q" <patch >from &&
826         test_cmp expect from
827 '
828
829 check_author() {
830         echo content >>file &&
831         git add file &&
832         GIT_AUTHOR_NAME=$1 git commit -m author-check &&
833         git format-patch --stdout -1 >patch &&
834         grep ^From: patch >actual &&
835         test_cmp expect actual
836 }
837
838 cat >expect <<'EOF'
839 From: "Foo B. Bar" <author@example.com>
840 EOF
841 test_expect_success 'format-patch quotes dot in headers' '
842         check_author "Foo B. Bar"
843 '
844
845 cat >expect <<'EOF'
846 From: "Foo \"The Baz\" Bar" <author@example.com>
847 EOF
848 test_expect_success 'format-patch quotes double-quote in headers' '
849         check_author "Foo \"The Baz\" Bar"
850 '
851
852 cat >expect <<'EOF'
853 From: =?UTF-8?q?"F=C3=B6o=20B.=20Bar"?= <author@example.com>
854 EOF
855 test_expect_success 'rfc2047-encoded headers also double-quote 822 specials' '
856         check_author "Föo B. Bar"
857 '
858
859 cat >expect <<'EOF'
860 Subject: header with . in it
861 EOF
862 test_expect_success 'subject lines do not have 822 atom-quoting' '
863         echo content >>file &&
864         git add file &&
865         git commit -m "header with . in it" &&
866         git format-patch -k -1 --stdout >patch &&
867         grep ^Subject: patch >actual &&
868         test_cmp expect actual
869 '
870
871 cat >expect <<'EOF'
872 Subject: [PREFIX 1/1] header with . in it
873 EOF
874 test_expect_success 'subject prefixes have space prepended' '
875         git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
876         grep ^Subject: patch >actual &&
877         test_cmp expect actual
878 '
879
880 cat >expect <<'EOF'
881 Subject: [1/1] header with . in it
882 EOF
883 test_expect_success 'empty subject prefix does not have extra space' '
884         git format-patch -n -1 --stdout --subject-prefix= >patch &&
885         grep ^Subject: patch >actual &&
886         test_cmp expect actual
887 '
888
889 test_expect_success 'format patch ignores color.ui' '
890         test_unconfig color.ui &&
891         git format-patch --stdout -1 >expect &&
892         test_config color.ui always &&
893         git format-patch --stdout -1 >actual &&
894         test_cmp expect actual
895 '
896
897 test_done