t4012: Actually quote the sed script
[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 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 |
620         grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
621 '
622
623 echo "fatal: --name-only does not make sense" > expect.name-only
624 echo "fatal: --name-status does not make sense" > expect.name-status
625 echo "fatal: --check does not make sense" > expect.check
626
627 test_expect_success 'options no longer allowed for format-patch' '
628         test_must_fail git format-patch --name-only 2> output &&
629         test_i18ncmp expect.name-only output &&
630         test_must_fail git format-patch --name-status 2> output &&
631         test_i18ncmp expect.name-status output &&
632         test_must_fail git format-patch --check 2> output &&
633         test_i18ncmp expect.check output'
634
635 test_expect_success 'format-patch --numstat should produce a patch' '
636         git format-patch --numstat --stdout master..side > output &&
637         test 6 = $(grep "^diff --git a/" output | wc -l)'
638
639 test_expect_success 'format-patch -- <path>' '
640         git format-patch master..side -- file 2>error &&
641         ! grep "Use .--" error
642 '
643
644 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
645         git format-patch --ignore-if-in-upstream HEAD
646 '
647
648 test_expect_success 'format-patch --signature' '
649         git format-patch --stdout --signature="my sig" -1 >output &&
650         grep "my sig" output
651 '
652
653 test_expect_success 'format-patch with format.signature config' '
654         git config format.signature "config sig" &&
655         git format-patch --stdout -1 >output &&
656         grep "config sig" output
657 '
658
659 test_expect_success 'format-patch --signature overrides format.signature' '
660         git config format.signature "config sig" &&
661         git format-patch --stdout --signature="overrides" -1 >output &&
662         ! grep "config sig" output &&
663         grep "overrides" output
664 '
665
666 test_expect_success 'format-patch --no-signature ignores format.signature' '
667         git config format.signature "config sig" &&
668         git format-patch --stdout --signature="my sig" --no-signature \
669                 -1 >output &&
670         check_patch output &&
671         ! grep "config sig" output &&
672         ! grep "my sig" output &&
673         ! grep "^-- \$" output
674 '
675
676 test_expect_success 'format-patch --signature --cover-letter' '
677         git config --unset-all format.signature &&
678         git format-patch --stdout --signature="my sig" --cover-letter \
679                 -1 >output &&
680         grep "my sig" output &&
681         test 2 = $(grep "my sig" output | wc -l)
682 '
683
684 test_expect_success 'format.signature="" supresses signatures' '
685         git config format.signature "" &&
686         git format-patch --stdout -1 >output &&
687         check_patch output &&
688         ! grep "^-- \$" output
689 '
690
691 test_expect_success 'format-patch --no-signature supresses signatures' '
692         git config --unset-all format.signature &&
693         git format-patch --stdout --no-signature -1 >output &&
694         check_patch output &&
695         ! grep "^-- \$" output
696 '
697
698 test_expect_success 'format-patch --signature="" supresses signatures' '
699         git format-patch --stdout --signature="" -1 >output &&
700         check_patch output &&
701         ! grep "^-- \$" output
702 '
703
704 test_expect_success TTY 'format-patch --stdout paginates' '
705         rm -f pager_used &&
706         (
707                 GIT_PAGER="wc >pager_used" &&
708                 export GIT_PAGER &&
709                 test_terminal git format-patch --stdout --all
710         ) &&
711         test_path_is_file pager_used
712 '
713
714  test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
715         rm -f pager_used &&
716         (
717                 GIT_PAGER="wc >pager_used" &&
718                 export GIT_PAGER &&
719                 test_terminal git --no-pager format-patch --stdout --all &&
720                 test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
721         ) &&
722         test_path_is_missing pager_used &&
723         test_path_is_missing .git/pager_used
724 '
725
726 test_expect_success 'format-patch handles multi-line subjects' '
727         rm -rf patches/ &&
728         echo content >>file &&
729         for i in one two three; do echo $i; done >msg &&
730         git add file &&
731         git commit -F msg &&
732         git format-patch -o patches -1 &&
733         grep ^Subject: patches/0001-one.patch >actual &&
734         echo "Subject: [PATCH] one two three" >expect &&
735         test_cmp expect actual
736 '
737
738 test_expect_success 'format-patch handles multi-line encoded subjects' '
739         rm -rf patches/ &&
740         echo content >>file &&
741         for i in en två tre; do echo $i; done >msg &&
742         git add file &&
743         git commit -F msg &&
744         git format-patch -o patches -1 &&
745         grep ^Subject: patches/0001-en.patch >actual &&
746         echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
747         test_cmp expect actual
748 '
749
750 M8="foo bar "
751 M64=$M8$M8$M8$M8$M8$M8$M8$M8
752 M512=$M64$M64$M64$M64$M64$M64$M64$M64
753 cat >expect <<'EOF'
754 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
755  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
756  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
757  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
758  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
759  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
760  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
761  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
762  foo bar foo bar foo bar foo bar
763 EOF
764 test_expect_success 'format-patch wraps extremely long headers (ascii)' '
765         echo content >>file &&
766         git add file &&
767         git commit -m "$M512" &&
768         git format-patch --stdout -1 >patch &&
769         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
770         test_cmp expect subject
771 '
772
773 M8="föö bar "
774 M64=$M8$M8$M8$M8$M8$M8$M8$M8
775 M512=$M64$M64$M64$M64$M64$M64$M64$M64
776 cat >expect <<'EOF'
777 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
778  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
779  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
780  =?UTF-8?q?=C3=B6=20bar=20f=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?=
799 EOF
800 test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
801         rm -rf patches/ &&
802         echo content >>file &&
803         git add file &&
804         git commit -m "$M512" &&
805         git format-patch --stdout -1 >patch &&
806         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
807         test_cmp expect subject
808 '
809
810 M8="foo_bar_"
811 M64=$M8$M8$M8$M8$M8$M8$M8$M8
812 cat >expect <<EOF
813 From: $M64
814  <foobar@foo.bar>
815 EOF
816 test_expect_success 'format-patch wraps non-quotable headers' '
817         rm -rf patches/ &&
818         echo content >>file &&
819         git add file &&
820         git commit -mfoo --author "$M64 <foobar@foo.bar>" &&
821         git format-patch --stdout -1 >patch &&
822         sed -n "/^From: /p; /^ /p; /^$/q" <patch >from &&
823         test_cmp expect from
824 '
825
826 check_author() {
827         echo content >>file &&
828         git add file &&
829         GIT_AUTHOR_NAME=$1 git commit -m author-check &&
830         git format-patch --stdout -1 >patch &&
831         grep ^From: patch >actual &&
832         test_cmp expect actual
833 }
834
835 cat >expect <<'EOF'
836 From: "Foo B. Bar" <author@example.com>
837 EOF
838 test_expect_success 'format-patch quotes dot in headers' '
839         check_author "Foo B. Bar"
840 '
841
842 cat >expect <<'EOF'
843 From: "Foo \"The Baz\" Bar" <author@example.com>
844 EOF
845 test_expect_success 'format-patch quotes double-quote in headers' '
846         check_author "Foo \"The Baz\" Bar"
847 '
848
849 cat >expect <<'EOF'
850 From: =?UTF-8?q?"F=C3=B6o=20B.=20Bar"?= <author@example.com>
851 EOF
852 test_expect_success 'rfc2047-encoded headers also double-quote 822 specials' '
853         check_author "Föo B. Bar"
854 '
855
856 cat >expect <<'EOF'
857 Subject: header with . in it
858 EOF
859 test_expect_success 'subject lines do not have 822 atom-quoting' '
860         echo content >>file &&
861         git add file &&
862         git commit -m "header with . in it" &&
863         git format-patch -k -1 --stdout >patch &&
864         grep ^Subject: patch >actual &&
865         test_cmp expect actual
866 '
867
868 cat >expect <<'EOF'
869 Subject: [PREFIX 1/1] header with . in it
870 EOF
871 test_expect_success 'subject prefixes have space prepended' '
872         git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
873         grep ^Subject: patch >actual &&
874         test_cmp expect actual
875 '
876
877 cat >expect <<'EOF'
878 Subject: [1/1] header with . in it
879 EOF
880 test_expect_success 'empty subject prefix does not have extra space' '
881         git format-patch -n -1 --stdout --subject-prefix= >patch &&
882         grep ^Subject: patch >actual &&
883         test_cmp expect actual
884 '
885
886 test_expect_success 'format patch ignores color.ui' '
887         test_unconfig color.ui &&
888         git format-patch --stdout -1 >expect &&
889         test_config color.ui always &&
890         git format-patch --stdout -1 >actual &&
891         test_cmp expect actual
892 '
893
894 test_done