format-patch: give --reroll-count a short synonym -v
[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 test_expect_success 'reroll count' '
241         rm -fr patches &&
242         git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
243         ! grep -v "^patches/v4-000[0-3]-" list &&
244         sed -n -e "/^Subject: /p" $(cat list) >subjects &&
245         ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
246 '
247
248 test_expect_success 'reroll count (-v)' '
249         rm -fr patches &&
250         git format-patch -o patches --cover-letter -v4 master..side >list &&
251         ! grep -v "^patches/v4-000[0-3]-" list &&
252         sed -n -e "/^Subject: /p" $(cat list) >subjects &&
253         ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
254 '
255
256 check_threading () {
257         expect="$1" &&
258         shift &&
259         (git format-patch --stdout "$@"; echo $? > status.out) |
260         # Prints everything between the Message-ID and In-Reply-To,
261         # and replaces all Message-ID-lookalikes by a sequence number
262         "$PERL_PATH" -ne '
263                 if (/^(message-id|references|in-reply-to)/i) {
264                         $printing = 1;
265                 } elsif (/^\S/) {
266                         $printing = 0;
267                 }
268                 if ($printing) {
269                         $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
270                         for $k (keys %h) {s/$k/$h{$k}/};
271                         print;
272                 }
273                 print "---\n" if /^From /i;
274         ' > actual &&
275         test 0 = "$(cat status.out)" &&
276         test_cmp "$expect" actual
277 }
278
279 cat >> expect.no-threading <<EOF
280 ---
281 ---
282 ---
283 EOF
284
285 test_expect_success 'no threading' '
286         git checkout side &&
287         check_threading expect.no-threading master
288 '
289
290 cat > expect.thread <<EOF
291 ---
292 Message-Id: <0>
293 ---
294 Message-Id: <1>
295 In-Reply-To: <0>
296 References: <0>
297 ---
298 Message-Id: <2>
299 In-Reply-To: <0>
300 References: <0>
301 EOF
302
303 test_expect_success 'thread' '
304         check_threading expect.thread --thread master
305 '
306
307 cat > expect.in-reply-to <<EOF
308 ---
309 Message-Id: <0>
310 In-Reply-To: <1>
311 References: <1>
312 ---
313 Message-Id: <2>
314 In-Reply-To: <1>
315 References: <1>
316 ---
317 Message-Id: <3>
318 In-Reply-To: <1>
319 References: <1>
320 EOF
321
322 test_expect_success 'thread in-reply-to' '
323         check_threading expect.in-reply-to --in-reply-to="<test.message>" \
324                 --thread master
325 '
326
327 cat > expect.cover-letter <<EOF
328 ---
329 Message-Id: <0>
330 ---
331 Message-Id: <1>
332 In-Reply-To: <0>
333 References: <0>
334 ---
335 Message-Id: <2>
336 In-Reply-To: <0>
337 References: <0>
338 ---
339 Message-Id: <3>
340 In-Reply-To: <0>
341 References: <0>
342 EOF
343
344 test_expect_success 'thread cover-letter' '
345         check_threading expect.cover-letter --cover-letter --thread master
346 '
347
348 cat > expect.cl-irt <<EOF
349 ---
350 Message-Id: <0>
351 In-Reply-To: <1>
352 References: <1>
353 ---
354 Message-Id: <2>
355 In-Reply-To: <0>
356 References: <1>
357         <0>
358 ---
359 Message-Id: <3>
360 In-Reply-To: <0>
361 References: <1>
362         <0>
363 ---
364 Message-Id: <4>
365 In-Reply-To: <0>
366 References: <1>
367         <0>
368 EOF
369
370 test_expect_success 'thread cover-letter in-reply-to' '
371         check_threading expect.cl-irt --cover-letter \
372                 --in-reply-to="<test.message>" --thread master
373 '
374
375 test_expect_success 'thread explicit shallow' '
376         check_threading expect.cl-irt --cover-letter \
377                 --in-reply-to="<test.message>" --thread=shallow master
378 '
379
380 cat > expect.deep <<EOF
381 ---
382 Message-Id: <0>
383 ---
384 Message-Id: <1>
385 In-Reply-To: <0>
386 References: <0>
387 ---
388 Message-Id: <2>
389 In-Reply-To: <1>
390 References: <0>
391         <1>
392 EOF
393
394 test_expect_success 'thread deep' '
395         check_threading expect.deep --thread=deep master
396 '
397
398 cat > expect.deep-irt <<EOF
399 ---
400 Message-Id: <0>
401 In-Reply-To: <1>
402 References: <1>
403 ---
404 Message-Id: <2>
405 In-Reply-To: <0>
406 References: <1>
407         <0>
408 ---
409 Message-Id: <3>
410 In-Reply-To: <2>
411 References: <1>
412         <0>
413         <2>
414 EOF
415
416 test_expect_success 'thread deep in-reply-to' '
417         check_threading expect.deep-irt  --thread=deep \
418                 --in-reply-to="<test.message>" master
419 '
420
421 cat > expect.deep-cl <<EOF
422 ---
423 Message-Id: <0>
424 ---
425 Message-Id: <1>
426 In-Reply-To: <0>
427 References: <0>
428 ---
429 Message-Id: <2>
430 In-Reply-To: <1>
431 References: <0>
432         <1>
433 ---
434 Message-Id: <3>
435 In-Reply-To: <2>
436 References: <0>
437         <1>
438         <2>
439 EOF
440
441 test_expect_success 'thread deep cover-letter' '
442         check_threading expect.deep-cl --cover-letter --thread=deep master
443 '
444
445 cat > expect.deep-cl-irt <<EOF
446 ---
447 Message-Id: <0>
448 In-Reply-To: <1>
449 References: <1>
450 ---
451 Message-Id: <2>
452 In-Reply-To: <0>
453 References: <1>
454         <0>
455 ---
456 Message-Id: <3>
457 In-Reply-To: <2>
458 References: <1>
459         <0>
460         <2>
461 ---
462 Message-Id: <4>
463 In-Reply-To: <3>
464 References: <1>
465         <0>
466         <2>
467         <3>
468 EOF
469
470 test_expect_success 'thread deep cover-letter in-reply-to' '
471         check_threading expect.deep-cl-irt --cover-letter \
472                 --in-reply-to="<test.message>" --thread=deep master
473 '
474
475 test_expect_success 'thread via config' '
476         test_config format.thread true &&
477         check_threading expect.thread master
478 '
479
480 test_expect_success 'thread deep via config' '
481         test_config format.thread deep &&
482         check_threading expect.deep master
483 '
484
485 test_expect_success 'thread config + override' '
486         test_config format.thread deep &&
487         check_threading expect.thread --thread master
488 '
489
490 test_expect_success 'thread config + --no-thread' '
491         test_config format.thread deep &&
492         check_threading expect.no-threading --no-thread master
493 '
494
495 test_expect_success 'excessive subject' '
496
497         rm -rf patches/ &&
498         git checkout side &&
499         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
500         git update-index file &&
501         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." &&
502         git format-patch -o patches/ master..side &&
503         ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
504 '
505
506 test_expect_success 'cover-letter inherits diff options' '
507
508         git mv file foo &&
509         git commit -m foo &&
510         git format-patch --cover-letter -1 &&
511         check_patch 0000-cover-letter.patch &&
512         ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
513         git format-patch --cover-letter -1 -M &&
514         grep "file => foo .* 0 *\$" 0000-cover-letter.patch
515
516 '
517
518 cat > expect << EOF
519   This is an excessively long subject line for a message due to the
520     habit some projects have of not having a short, one-line subject at
521     the start of the commit message, but rather sticking a whole
522     paragraph right at the start as the only thing in the commit
523     message. It had better not become the filename for the patch.
524   foo
525
526 EOF
527
528 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
529
530         git format-patch --cover-letter -2 &&
531         sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
532         test_cmp expect output
533
534 '
535
536 cat > expect << EOF
537 index 40f36c6..2dc5c23 100644
538 --- a/file
539 +++ b/file
540 @@ -13,4 +13,20 @@ C
541  10
542  D
543  E
544  F
545 +5
546 EOF
547
548 test_expect_success 'format-patch respects -U' '
549
550         git format-patch -U4 -2 &&
551         sed -e "1,/^diff/d" -e "/^+5/q" \
552                 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
553                 >output &&
554         test_cmp expect output
555
556 '
557
558 cat > expect << EOF
559
560 diff --git a/file b/file
561 index 40f36c6..2dc5c23 100644
562 --- a/file
563 +++ b/file
564 @@ -14,3 +14,19 @@ C
565  D
566  E
567  F
568 +5
569 EOF
570
571 test_expect_success 'format-patch -p suppresses stat' '
572
573         git format-patch -p -2 &&
574         sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
575         test_cmp expect output
576
577 '
578
579 test_expect_success 'format-patch from a subdirectory (1)' '
580         filename=$(
581                 rm -rf sub &&
582                 mkdir -p sub/dir &&
583                 cd sub/dir &&
584                 git format-patch -1
585         ) &&
586         case "$filename" in
587         0*)
588                 ;; # ok
589         *)
590                 echo "Oops? $filename"
591                 false
592                 ;;
593         esac &&
594         test -f "$filename"
595 '
596
597 test_expect_success 'format-patch from a subdirectory (2)' '
598         filename=$(
599                 rm -rf sub &&
600                 mkdir -p sub/dir &&
601                 cd sub/dir &&
602                 git format-patch -1 -o ..
603         ) &&
604         case "$filename" in
605         ../0*)
606                 ;; # ok
607         *)
608                 echo "Oops? $filename"
609                 false
610                 ;;
611         esac &&
612         basename=$(expr "$filename" : ".*/\(.*\)") &&
613         test -f "sub/$basename"
614 '
615
616 test_expect_success 'format-patch from a subdirectory (3)' '
617         rm -f 0* &&
618         filename=$(
619                 rm -rf sub &&
620                 mkdir -p sub/dir &&
621                 cd sub/dir &&
622                 git format-patch -1 -o "$TRASH_DIRECTORY"
623         ) &&
624         basename=$(expr "$filename" : ".*/\(.*\)") &&
625         test -f "$basename"
626 '
627
628 test_expect_success 'format-patch --in-reply-to' '
629         git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
630         grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
631         grep "^References: <baz@foo.bar>" patch8
632 '
633
634 test_expect_success 'format-patch --signoff' '
635         git format-patch -1 --signoff --stdout |
636         grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
637 '
638
639 echo "fatal: --name-only does not make sense" > expect.name-only
640 echo "fatal: --name-status does not make sense" > expect.name-status
641 echo "fatal: --check does not make sense" > expect.check
642
643 test_expect_success 'options no longer allowed for format-patch' '
644         test_must_fail git format-patch --name-only 2> output &&
645         test_i18ncmp expect.name-only output &&
646         test_must_fail git format-patch --name-status 2> output &&
647         test_i18ncmp expect.name-status output &&
648         test_must_fail git format-patch --check 2> output &&
649         test_i18ncmp expect.check output'
650
651 test_expect_success 'format-patch --numstat should produce a patch' '
652         git format-patch --numstat --stdout master..side > output &&
653         test 6 = $(grep "^diff --git a/" output | wc -l)'
654
655 test_expect_success 'format-patch -- <path>' '
656         git format-patch master..side -- file 2>error &&
657         ! grep "Use .--" error
658 '
659
660 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
661         git format-patch --ignore-if-in-upstream HEAD
662 '
663
664 test_expect_success 'format-patch --signature' '
665         git format-patch --stdout --signature="my sig" -1 >output &&
666         grep "my sig" output
667 '
668
669 test_expect_success 'format-patch with format.signature config' '
670         git config format.signature "config sig" &&
671         git format-patch --stdout -1 >output &&
672         grep "config sig" output
673 '
674
675 test_expect_success 'format-patch --signature overrides format.signature' '
676         git config format.signature "config sig" &&
677         git format-patch --stdout --signature="overrides" -1 >output &&
678         ! grep "config sig" output &&
679         grep "overrides" output
680 '
681
682 test_expect_success 'format-patch --no-signature ignores format.signature' '
683         git config format.signature "config sig" &&
684         git format-patch --stdout --signature="my sig" --no-signature \
685                 -1 >output &&
686         check_patch output &&
687         ! grep "config sig" output &&
688         ! grep "my sig" output &&
689         ! grep "^-- \$" output
690 '
691
692 test_expect_success 'format-patch --signature --cover-letter' '
693         git config --unset-all format.signature &&
694         git format-patch --stdout --signature="my sig" --cover-letter \
695                 -1 >output &&
696         grep "my sig" output &&
697         test 2 = $(grep "my sig" output | wc -l)
698 '
699
700 test_expect_success 'format.signature="" supresses signatures' '
701         git config format.signature "" &&
702         git format-patch --stdout -1 >output &&
703         check_patch output &&
704         ! grep "^-- \$" output
705 '
706
707 test_expect_success 'format-patch --no-signature supresses signatures' '
708         git config --unset-all format.signature &&
709         git format-patch --stdout --no-signature -1 >output &&
710         check_patch output &&
711         ! grep "^-- \$" output
712 '
713
714 test_expect_success 'format-patch --signature="" supresses signatures' '
715         git format-patch --stdout --signature="" -1 >output &&
716         check_patch output &&
717         ! grep "^-- \$" output
718 '
719
720 test_expect_success TTY 'format-patch --stdout paginates' '
721         rm -f pager_used &&
722         (
723                 GIT_PAGER="wc >pager_used" &&
724                 export GIT_PAGER &&
725                 test_terminal git format-patch --stdout --all
726         ) &&
727         test_path_is_file pager_used
728 '
729
730  test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
731         rm -f pager_used &&
732         (
733                 GIT_PAGER="wc >pager_used" &&
734                 export GIT_PAGER &&
735                 test_terminal git --no-pager format-patch --stdout --all &&
736                 test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
737         ) &&
738         test_path_is_missing pager_used &&
739         test_path_is_missing .git/pager_used
740 '
741
742 test_expect_success 'format-patch handles multi-line subjects' '
743         rm -rf patches/ &&
744         echo content >>file &&
745         for i in one two three; do echo $i; done >msg &&
746         git add file &&
747         git commit -F msg &&
748         git format-patch -o patches -1 &&
749         grep ^Subject: patches/0001-one.patch >actual &&
750         echo "Subject: [PATCH] one two three" >expect &&
751         test_cmp expect actual
752 '
753
754 test_expect_success 'format-patch handles multi-line encoded subjects' '
755         rm -rf patches/ &&
756         echo content >>file &&
757         for i in en två tre; do echo $i; done >msg &&
758         git add file &&
759         git commit -F msg &&
760         git format-patch -o patches -1 &&
761         grep ^Subject: patches/0001-en.patch >actual &&
762         echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
763         test_cmp expect actual
764 '
765
766 M8="foo bar "
767 M64=$M8$M8$M8$M8$M8$M8$M8$M8
768 M512=$M64$M64$M64$M64$M64$M64$M64$M64
769 cat >expect <<'EOF'
770 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
771  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
772  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
773  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
774  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
775  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
776  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
777  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
778  foo bar foo bar foo bar foo bar
779 EOF
780 test_expect_success 'format-patch wraps extremely long headers (ascii)' '
781         echo content >>file &&
782         git add file &&
783         git commit -m "$M512" &&
784         git format-patch --stdout -1 >patch &&
785         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
786         test_cmp expect subject
787 '
788
789 M8="föö bar "
790 M64=$M8$M8$M8$M8$M8$M8$M8$M8
791 M512=$M64$M64$M64$M64$M64$M64$M64$M64
792 cat >expect <<'EOF'
793 Subject: [PATCH] =?UTF-8?q?f=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=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
807  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
808  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
809  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
810  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
811  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
812  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
813  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
814  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
815 EOF
816 test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
817         rm -rf patches/ &&
818         echo content >>file &&
819         git add file &&
820         git commit -m "$M512" &&
821         git format-patch --stdout -1 >patch &&
822         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
823         test_cmp expect subject
824 '
825
826 M8="foo_bar_"
827 M64=$M8$M8$M8$M8$M8$M8$M8$M8
828 cat >expect <<EOF
829 From: $M64
830  <foobar@foo.bar>
831 EOF
832 test_expect_success 'format-patch wraps non-quotable headers' '
833         rm -rf patches/ &&
834         echo content >>file &&
835         git add file &&
836         git commit -mfoo --author "$M64 <foobar@foo.bar>" &&
837         git format-patch --stdout -1 >patch &&
838         sed -n "/^From: /p; /^ /p; /^$/q" <patch >from &&
839         test_cmp expect from
840 '
841
842 check_author() {
843         echo content >>file &&
844         git add file &&
845         GIT_AUTHOR_NAME=$1 git commit -m author-check &&
846         git format-patch --stdout -1 >patch &&
847         grep ^From: patch >actual &&
848         test_cmp expect actual
849 }
850
851 cat >expect <<'EOF'
852 From: "Foo B. Bar" <author@example.com>
853 EOF
854 test_expect_success 'format-patch quotes dot in headers' '
855         check_author "Foo B. Bar"
856 '
857
858 cat >expect <<'EOF'
859 From: "Foo \"The Baz\" Bar" <author@example.com>
860 EOF
861 test_expect_success 'format-patch quotes double-quote in headers' '
862         check_author "Foo \"The Baz\" Bar"
863 '
864
865 cat >expect <<'EOF'
866 From: =?UTF-8?q?"F=C3=B6o=20B.=20Bar"?= <author@example.com>
867 EOF
868 test_expect_success 'rfc2047-encoded headers also double-quote 822 specials' '
869         check_author "Föo B. Bar"
870 '
871
872 cat >expect <<'EOF'
873 Subject: header with . in it
874 EOF
875 test_expect_success 'subject lines do not have 822 atom-quoting' '
876         echo content >>file &&
877         git add file &&
878         git commit -m "header with . in it" &&
879         git format-patch -k -1 --stdout >patch &&
880         grep ^Subject: patch >actual &&
881         test_cmp expect actual
882 '
883
884 cat >expect <<'EOF'
885 Subject: [PREFIX 1/1] header with . in it
886 EOF
887 test_expect_success 'subject prefixes have space prepended' '
888         git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
889         grep ^Subject: patch >actual &&
890         test_cmp expect actual
891 '
892
893 cat >expect <<'EOF'
894 Subject: [1/1] header with . in it
895 EOF
896 test_expect_success 'empty subject prefix does not have extra space' '
897         git format-patch -n -1 --stdout --subject-prefix= >patch &&
898         grep ^Subject: patch >actual &&
899         test_cmp expect actual
900 '
901
902 test_expect_success 'format patch ignores color.ui' '
903         test_unconfig color.ui &&
904         git format-patch --stdout -1 >expect &&
905         test_config color.ui always &&
906         git format-patch --stdout -1 >actual &&
907         test_cmp expect actual
908 '
909
910 test_done