Merge branch 'fc/random-cleanup'
[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         for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
13         cat file >elif &&
14         git add file elif &&
15         test_tick &&
16         git commit -m Initial &&
17         git checkout -b side &&
18
19         for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
20         test_chmod +x elif &&
21         test_tick &&
22         git commit -m "Side changes #1" &&
23
24         for i in D E F; do echo "$i"; done >>file &&
25         git update-index file &&
26         test_tick &&
27         git commit -m "Side changes #2" &&
28         git tag C2 &&
29
30         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
31         git update-index file &&
32         test_tick &&
33         git commit -m "Side changes #3 with \\n backslash-n in it." &&
34
35         git checkout master &&
36         git diff-tree -p C2 >patch &&
37         git apply --index <patch &&
38         test_tick &&
39         git commit -m "Master accepts moral equivalent of #2" &&
40
41         git checkout side &&
42         git checkout -b patchid &&
43         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file2 &&
44         for i in 1 2 3 A 4 B C 7 8 9 10 D E F 5 6; do echo "$i"; done >file3 &&
45         for i in 8 9 10; do echo "$i"; done >file &&
46         git add file file2 file3 &&
47         test_tick &&
48         git commit -m "patchid 1" &&
49         for i in 4 A B 7 8 9 10; do echo "$i"; done >file2 &&
50         for i in 8 9 10 5 6; do echo "$i"; done >file3 &&
51         git add file2 file3 &&
52         test_tick &&
53         git commit -m "patchid 2" &&
54         for i in 10 5 6; do echo "$i"; done >file &&
55         git add file &&
56         test_tick &&
57         git commit -m "patchid 3" &&
58
59         git checkout master
60 '
61
62 test_expect_success 'format-patch --ignore-if-in-upstream' '
63         git format-patch --stdout master..side >patch0 &&
64         grep "^From " patch0 >from0 &&
65         test_line_count = 3 from0
66 '
67
68 test_expect_success 'format-patch --ignore-if-in-upstream' '
69         git format-patch --stdout \
70                 --ignore-if-in-upstream master..side >patch1 &&
71         grep "^From " patch1 >from1 &&
72         test_line_count = 2 from1
73 '
74
75 test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '
76         git tag -a v1 -m tag side &&
77         git tag -a v2 -m tag master &&
78         git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
79         grep "^From " patch1 >from1 &&
80         test_line_count = 2 from1
81 '
82
83 test_expect_success "format-patch doesn't consider merge commits" '
84         git checkout -b feature master &&
85         echo "Another line" >>file &&
86         test_tick &&
87         git commit -am "Feature branch change #1" &&
88         echo "Yet another line" >>file &&
89         test_tick &&
90         git commit -am "Feature branch change #2" &&
91         git checkout -b merger master &&
92         test_tick &&
93         git merge --no-ff feature &&
94         git format-patch -3 --stdout >patch &&
95         grep "^From " patch >from &&
96         test_line_count = 3 from
97 '
98
99 test_expect_success 'format-patch result applies' '
100         git checkout -b rebuild-0 master &&
101         git am -3 patch0 &&
102         git rev-list master.. >list &&
103         test_line_count = 2 list
104 '
105
106 test_expect_success 'format-patch --ignore-if-in-upstream result applies' '
107         git checkout -b rebuild-1 master &&
108         git am -3 patch1 &&
109         git rev-list master.. >list &&
110         test_line_count = 2 list
111 '
112
113 test_expect_success 'commit did not screw up the log message' '
114         git cat-file commit side >actual &&
115         grep "^Side .* with .* backslash-n" actual
116 '
117
118 test_expect_success 'format-patch did not screw up the log message' '
119         grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
120         grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
121 '
122
123 test_expect_success 'replay did not screw up the log message' '
124         git cat-file commit rebuild-1 >actual &&
125         grep "^Side .* with .* backslash-n" actual
126 '
127
128 test_expect_success 'extra headers' '
129         git config format.headers "To: R E Cipient <rcipient@example.com>
130 " &&
131         git config --add format.headers "Cc: S E Cipient <scipient@example.com>
132 " &&
133         git format-patch --stdout master..side >patch2 &&
134         sed -e "/^\$/q" patch2 >hdrs2 &&
135         grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
136         grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
137 '
138
139 test_expect_success 'extra headers without newlines' '
140         git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
141         git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
142         git format-patch --stdout master..side >patch3 &&
143         sed -e "/^\$/q" patch3 >hdrs3 &&
144         grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
145         grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
146 '
147
148 test_expect_success 'extra headers with multiple To:s' '
149         git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
150         git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
151         git format-patch --stdout master..side >patch4 &&
152         sed -e "/^\$/q" patch4 >hdrs4 &&
153         grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
154         grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
155 '
156
157 test_expect_success 'additional command line cc (ascii)' '
158         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
159         git format-patch --cc="S E Cipient <scipient@example.com>" --stdout master..side >patch5 &&
160         sed -e "/^\$/q" patch5 >hdrs5 &&
161         grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
162         grep "^ *S E Cipient <scipient@example.com>\$" hdrs5
163 '
164
165 test_expect_failure 'additional command line cc (rfc822)' '
166         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
167         git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side >patch5 &&
168         sed -e "/^\$/q" patch5 >hdrs5 &&
169         grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 &&
170         grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" hdrs5
171 '
172
173 test_expect_success 'command line headers' '
174         git config --unset-all format.headers &&
175         git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side >patch6 &&
176         sed -e "/^\$/q" patch6 >hdrs6 &&
177         grep "^Cc: R E Cipient <rcipient@example.com>\$" hdrs6
178 '
179
180 test_expect_success 'configuration headers and command line headers' '
181         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
182         git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side >patch7 &&
183         sed -e "/^\$/q" patch7 >hdrs7 &&
184         grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs7 &&
185         grep "^ *S E Cipient <scipient@example.com>\$" hdrs7
186 '
187
188 test_expect_success 'command line To: header (ascii)' '
189         git config --unset-all format.headers &&
190         git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side >patch8 &&
191         sed -e "/^\$/q" patch8 >hdrs8 &&
192         grep "^To: R E Cipient <rcipient@example.com>\$" hdrs8
193 '
194
195 test_expect_failure 'command line To: header (rfc822)' '
196         git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side >patch8 &&
197         sed -e "/^\$/q" patch8 >hdrs8 &&
198         grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs8
199 '
200
201 test_expect_failure 'command line To: header (rfc2047)' '
202         git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side >patch8 &&
203         sed -e "/^\$/q" patch8 >hdrs8 &&
204         grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs8
205 '
206
207 test_expect_success 'configuration To: header (ascii)' '
208         git config format.to "R E Cipient <rcipient@example.com>" &&
209         git format-patch --stdout master..side >patch9 &&
210         sed -e "/^\$/q" patch9 >hdrs9 &&
211         grep "^To: R E Cipient <rcipient@example.com>\$" hdrs9
212 '
213
214 test_expect_failure 'configuration To: header (rfc822)' '
215         git config format.to "R. E. Cipient <rcipient@example.com>" &&
216         git format-patch --stdout master..side >patch9 &&
217         sed -e "/^\$/q" patch9 >hdrs9 &&
218         grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs9
219 '
220
221 test_expect_failure 'configuration To: header (rfc2047)' '
222         git config format.to "R Ä Cipient <rcipient@example.com>" &&
223         git format-patch --stdout master..side >patch9 &&
224         sed -e "/^\$/q" patch9 >hdrs9 &&
225         grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs9
226 '
227
228 # check_patch <patch>: Verify that <patch> looks like a half-sane
229 # patch email to avoid a false positive with !grep
230 check_patch () {
231         grep -e "^From:" "$1" &&
232         grep -e "^Date:" "$1" &&
233         grep -e "^Subject:" "$1"
234 }
235
236 test_expect_success 'format.from=false' '
237         git -c format.from=false format-patch --stdout master..side >patch &&
238         sed -e "/^\$/q" patch >hdrs &&
239         check_patch patch &&
240         ! grep "^From: C O Mitter <committer@example.com>\$" hdrs
241 '
242
243 test_expect_success 'format.from=true' '
244         git -c format.from=true format-patch --stdout master..side >patch &&
245         sed -e "/^\$/q" patch >hdrs &&
246         check_patch hdrs &&
247         grep "^From: C O Mitter <committer@example.com>\$" hdrs
248 '
249
250 test_expect_success 'format.from with address' '
251         git -c format.from="F R Om <from@example.com>" format-patch --stdout master..side >patch &&
252         sed -e "/^\$/q" patch >hdrs &&
253         check_patch hdrs &&
254         grep "^From: F R Om <from@example.com>\$" hdrs
255 '
256
257 test_expect_success '--no-from overrides format.from' '
258         git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout master..side >patch &&
259         sed -e "/^\$/q" patch >hdrs &&
260         check_patch hdrs &&
261         ! grep "^From: F R Om <from@example.com>\$" hdrs
262 '
263
264 test_expect_success '--from overrides format.from' '
265         git -c format.from="F R Om <from@example.com>" format-patch --from --stdout master..side >patch &&
266         sed -e "/^\$/q" patch >hdrs &&
267         check_patch hdrs &&
268         ! grep "^From: F R Om <from@example.com>\$" hdrs
269 '
270
271 test_expect_success '--no-to overrides config.to' '
272         git config --replace-all format.to \
273                 "R E Cipient <rcipient@example.com>" &&
274         git format-patch --no-to --stdout master..side >patch10 &&
275         sed -e "/^\$/q" patch10 >hdrs10 &&
276         check_patch hdrs10 &&
277         ! grep "^To: R E Cipient <rcipient@example.com>\$" hdrs10
278 '
279
280 test_expect_success '--no-to and --to replaces config.to' '
281         git config --replace-all format.to \
282                 "Someone <someone@out.there>" &&
283         git format-patch --no-to --to="Someone Else <else@out.there>" \
284                 --stdout master..side >patch11 &&
285         sed -e "/^\$/q" patch11 >hdrs11 &&
286         check_patch hdrs11 &&
287         ! grep "^To: Someone <someone@out.there>\$" hdrs11 &&
288         grep "^To: Someone Else <else@out.there>\$" hdrs11
289 '
290
291 test_expect_success '--no-cc overrides config.cc' '
292         git config --replace-all format.cc \
293                 "C E Cipient <rcipient@example.com>" &&
294         git format-patch --no-cc --stdout master..side >patch12 &&
295         sed -e "/^\$/q" patch12 >hdrs12 &&
296         check_patch hdrs12 &&
297         ! grep "^Cc: C E Cipient <rcipient@example.com>\$" hdrs12
298 '
299
300 test_expect_success '--no-add-header overrides config.headers' '
301         git config --replace-all format.headers \
302                 "Header1: B E Cipient <rcipient@example.com>" &&
303         git format-patch --no-add-header --stdout master..side >patch13 &&
304         sed -e "/^\$/q" patch13 >hdrs13 &&
305         check_patch hdrs13 &&
306         ! grep "^Header1: B E Cipient <rcipient@example.com>\$" hdrs13
307 '
308
309 test_expect_success 'multiple files' '
310         rm -rf patches/ &&
311         git checkout side &&
312         git format-patch -o patches/ master &&
313         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
314 '
315
316 test_expect_success 'filename length limit' '
317         test_when_finished "rm -f 000*" &&
318         rm -rf 000[1-9]-*.patch &&
319         for len in 15 25 35
320         do
321                 git format-patch --filename-max-length=$len -3 side &&
322                 max=$(
323                         for patch in 000[1-9]-*.patch
324                         do
325                                 echo "$patch" | wc -c
326                         done |
327                         sort -nr |
328                         head -n 1
329                 ) &&
330                 test $max -le $len || return 1
331         done
332 '
333
334 test_expect_success 'filename length limit from config' '
335         test_when_finished "rm -f 000*" &&
336         rm -rf 000[1-9]-*.patch &&
337         for len in 15 25 35
338         do
339                 git -c format.filenameMaxLength=$len format-patch -3 side &&
340                 max=$(
341                         for patch in 000[1-9]-*.patch
342                         do
343                                 echo "$patch" | wc -c
344                         done |
345                         sort -nr |
346                         head -n 1
347                 ) &&
348                 test $max -le $len || return 1
349         done
350 '
351
352 test_expect_success 'filename limit applies only to basename' '
353         test_when_finished "rm -rf patches/" &&
354         rm -rf patches/ &&
355         for len in 15 25 35
356         do
357                 git format-patch -o patches --filename-max-length=$len -3 side &&
358                 max=$(
359                         for patch in patches/000[1-9]-*.patch
360                         do
361                                 echo "${patch#patches/}" | wc -c
362                         done |
363                         sort -nr |
364                         head -n 1
365                 ) &&
366                 test $max -le $len || return 1
367         done
368 '
369
370 test_expect_success 'reroll count' '
371         rm -fr patches &&
372         git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
373         ! grep -v "^patches/v4-000[0-3]-" list &&
374         sed -n -e "/^Subject: /p" $(cat list) >subjects &&
375         ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
376 '
377
378 test_expect_success 'reroll count (-v)' '
379         rm -fr patches &&
380         git format-patch -o patches --cover-letter -v4 master..side >list &&
381         ! grep -v "^patches/v4-000[0-3]-" list &&
382         sed -n -e "/^Subject: /p" $(cat list) >subjects &&
383         ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
384 '
385
386 check_threading () {
387         expect="$1" &&
388         shift &&
389         git format-patch --stdout "$@" >patch &&
390         # Prints everything between the Message-ID and In-Reply-To,
391         # and replaces all Message-ID-lookalikes by a sequence number
392         perl -ne '
393                 if (/^(message-id|references|in-reply-to)/i) {
394                         $printing = 1;
395                 } elsif (/^\S/) {
396                         $printing = 0;
397                 }
398                 if ($printing) {
399                         $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
400                         for $k (keys %h) {s/$k/$h{$k}/};
401                         print;
402                 }
403                 print "---\n" if /^From /i;
404         ' <patch >actual &&
405         test_cmp "$expect" actual
406 }
407
408 cat >>expect.no-threading <<EOF
409 ---
410 ---
411 ---
412 EOF
413
414 test_expect_success 'no threading' '
415         git checkout side &&
416         check_threading expect.no-threading master
417 '
418
419 cat >expect.thread <<EOF
420 ---
421 Message-Id: <0>
422 ---
423 Message-Id: <1>
424 In-Reply-To: <0>
425 References: <0>
426 ---
427 Message-Id: <2>
428 In-Reply-To: <0>
429 References: <0>
430 EOF
431
432 test_expect_success 'thread' '
433         check_threading expect.thread --thread master
434 '
435
436 cat >expect.in-reply-to <<EOF
437 ---
438 Message-Id: <0>
439 In-Reply-To: <1>
440 References: <1>
441 ---
442 Message-Id: <2>
443 In-Reply-To: <1>
444 References: <1>
445 ---
446 Message-Id: <3>
447 In-Reply-To: <1>
448 References: <1>
449 EOF
450
451 test_expect_success 'thread in-reply-to' '
452         check_threading expect.in-reply-to --in-reply-to="<test.message>" \
453                 --thread master
454 '
455
456 cat >expect.cover-letter <<EOF
457 ---
458 Message-Id: <0>
459 ---
460 Message-Id: <1>
461 In-Reply-To: <0>
462 References: <0>
463 ---
464 Message-Id: <2>
465 In-Reply-To: <0>
466 References: <0>
467 ---
468 Message-Id: <3>
469 In-Reply-To: <0>
470 References: <0>
471 EOF
472
473 test_expect_success 'thread cover-letter' '
474         check_threading expect.cover-letter --cover-letter --thread master
475 '
476
477 cat >expect.cl-irt <<EOF
478 ---
479 Message-Id: <0>
480 In-Reply-To: <1>
481 References: <1>
482 ---
483 Message-Id: <2>
484 In-Reply-To: <0>
485 References: <1>
486         <0>
487 ---
488 Message-Id: <3>
489 In-Reply-To: <0>
490 References: <1>
491         <0>
492 ---
493 Message-Id: <4>
494 In-Reply-To: <0>
495 References: <1>
496         <0>
497 EOF
498
499 test_expect_success 'thread cover-letter in-reply-to' '
500         check_threading expect.cl-irt --cover-letter \
501                 --in-reply-to="<test.message>" --thread master
502 '
503
504 test_expect_success 'thread explicit shallow' '
505         check_threading expect.cl-irt --cover-letter \
506                 --in-reply-to="<test.message>" --thread=shallow master
507 '
508
509 cat >expect.deep <<EOF
510 ---
511 Message-Id: <0>
512 ---
513 Message-Id: <1>
514 In-Reply-To: <0>
515 References: <0>
516 ---
517 Message-Id: <2>
518 In-Reply-To: <1>
519 References: <0>
520         <1>
521 EOF
522
523 test_expect_success 'thread deep' '
524         check_threading expect.deep --thread=deep master
525 '
526
527 cat >expect.deep-irt <<EOF
528 ---
529 Message-Id: <0>
530 In-Reply-To: <1>
531 References: <1>
532 ---
533 Message-Id: <2>
534 In-Reply-To: <0>
535 References: <1>
536         <0>
537 ---
538 Message-Id: <3>
539 In-Reply-To: <2>
540 References: <1>
541         <0>
542         <2>
543 EOF
544
545 test_expect_success 'thread deep in-reply-to' '
546         check_threading expect.deep-irt  --thread=deep \
547                 --in-reply-to="<test.message>" master
548 '
549
550 cat >expect.deep-cl <<EOF
551 ---
552 Message-Id: <0>
553 ---
554 Message-Id: <1>
555 In-Reply-To: <0>
556 References: <0>
557 ---
558 Message-Id: <2>
559 In-Reply-To: <1>
560 References: <0>
561         <1>
562 ---
563 Message-Id: <3>
564 In-Reply-To: <2>
565 References: <0>
566         <1>
567         <2>
568 EOF
569
570 test_expect_success 'thread deep cover-letter' '
571         check_threading expect.deep-cl --cover-letter --thread=deep master
572 '
573
574 cat >expect.deep-cl-irt <<EOF
575 ---
576 Message-Id: <0>
577 In-Reply-To: <1>
578 References: <1>
579 ---
580 Message-Id: <2>
581 In-Reply-To: <0>
582 References: <1>
583         <0>
584 ---
585 Message-Id: <3>
586 In-Reply-To: <2>
587 References: <1>
588         <0>
589         <2>
590 ---
591 Message-Id: <4>
592 In-Reply-To: <3>
593 References: <1>
594         <0>
595         <2>
596         <3>
597 EOF
598
599 test_expect_success 'thread deep cover-letter in-reply-to' '
600         check_threading expect.deep-cl-irt --cover-letter \
601                 --in-reply-to="<test.message>" --thread=deep master
602 '
603
604 test_expect_success 'thread via config' '
605         test_config format.thread true &&
606         check_threading expect.thread master
607 '
608
609 test_expect_success 'thread deep via config' '
610         test_config format.thread deep &&
611         check_threading expect.deep master
612 '
613
614 test_expect_success 'thread config + override' '
615         test_config format.thread deep &&
616         check_threading expect.thread --thread master
617 '
618
619 test_expect_success 'thread config + --no-thread' '
620         test_config format.thread deep &&
621         check_threading expect.no-threading --no-thread master
622 '
623
624 test_expect_success 'excessive subject' '
625         rm -rf patches/ &&
626         git checkout side &&
627         before=$(git hash-object file) &&
628         before=$(git rev-parse --short $before) &&
629         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
630         after=$(git hash-object file) &&
631         after=$(git rev-parse --short $after) &&
632         git update-index file &&
633         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." &&
634         git format-patch -o patches/ master..side &&
635         ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
636 '
637
638 test_expect_success 'failure to write cover-letter aborts gracefully' '
639         test_when_finished "rmdir 0000-cover-letter.patch" &&
640         mkdir 0000-cover-letter.patch &&
641         test_must_fail git format-patch --no-renames --cover-letter -1
642 '
643
644 test_expect_success 'cover-letter inherits diff options' '
645         git mv file foo &&
646         git commit -m foo &&
647         git format-patch --no-renames --cover-letter -1 &&
648         check_patch 0000-cover-letter.patch &&
649         ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
650         git format-patch --cover-letter -1 -M &&
651         grep "file => foo .* 0 *\$" 0000-cover-letter.patch
652 '
653
654 cat >expect <<EOF
655   This is an excessively long subject line for a message due to the
656     habit some projects have of not having a short, one-line subject at
657     the start of the commit message, but rather sticking a whole
658     paragraph right at the start as the only thing in the commit
659     message. It had better not become the filename for the patch.
660   foo
661
662 EOF
663
664 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
665         git format-patch --cover-letter -2 &&
666         sed -e "1,/A U Thor/d" -e "/^\$/q" 0000-cover-letter.patch >output &&
667         test_cmp expect output
668 '
669
670 cat >expect <<EOF
671 index $before..$after 100644
672 --- a/file
673 +++ b/file
674 @@ -13,4 +13,20 @@ C
675  10
676  D
677  E
678  F
679 +5
680 EOF
681
682 test_expect_success 'format-patch respects -U' '
683         git format-patch -U4 -2 &&
684         sed -e "1,/^diff/d" -e "/^+5/q" \
685                 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
686                 >output &&
687         test_cmp expect output
688 '
689
690 cat >expect <<EOF
691
692 diff --git a/file b/file
693 index $before..$after 100644
694 --- a/file
695 +++ b/file
696 @@ -14,3 +14,19 @@ C
697  D
698  E
699  F
700 +5
701 EOF
702
703 test_expect_success 'format-patch -p suppresses stat' '
704         git format-patch -p -2 &&
705         sed -e "1,/^\$/d" -e "/^+5/q" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&
706         test_cmp expect output
707 '
708
709 test_expect_success 'format-patch from a subdirectory (1)' '
710         filename=$(
711                 rm -rf sub &&
712                 mkdir -p sub/dir &&
713                 cd sub/dir &&
714                 git format-patch -1
715         ) &&
716         case "$filename" in
717         0*)
718                 ;; # ok
719         *)
720                 echo "Oops? $filename"
721                 false
722                 ;;
723         esac &&
724         test -f "$filename"
725 '
726
727 test_expect_success 'format-patch from a subdirectory (2)' '
728         filename=$(
729                 rm -rf sub &&
730                 mkdir -p sub/dir &&
731                 cd sub/dir &&
732                 git format-patch -1 -o ..
733         ) &&
734         case "$filename" in
735         ../0*)
736                 ;; # ok
737         *)
738                 echo "Oops? $filename"
739                 false
740                 ;;
741         esac &&
742         basename=$(expr "$filename" : ".*/\(.*\)") &&
743         test -f "sub/$basename"
744 '
745
746 test_expect_success 'format-patch from a subdirectory (3)' '
747         rm -f 0* &&
748         filename=$(
749                 rm -rf sub &&
750                 mkdir -p sub/dir &&
751                 cd sub/dir &&
752                 git format-patch -1 -o "$TRASH_DIRECTORY"
753         ) &&
754         basename=$(expr "$filename" : ".*/\(.*\)") &&
755         test -f "$basename"
756 '
757
758 test_expect_success 'format-patch --in-reply-to' '
759         git format-patch -1 --stdout --in-reply-to "baz@foo.bar" >patch8 &&
760         grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
761         grep "^References: <baz@foo.bar>" patch8
762 '
763
764 test_expect_success 'format-patch --signoff' '
765         git format-patch -1 --signoff --stdout >out &&
766         grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
767 '
768
769 test_expect_success 'format-patch --notes --signoff' '
770         git notes --ref test add -m "test message" HEAD &&
771         git format-patch -1 --signoff --stdout --notes=test >out &&
772         # Three dashes must come after S-o-b
773         ! sed "/^Signed-off-by: /q" out | grep "test message" &&
774         sed "1,/^Signed-off-by: /d" out | grep "test message" &&
775         # Notes message must come after three dashes
776         ! sed "/^---$/q" out | grep "test message" &&
777         sed "1,/^---$/d" out | grep "test message"
778 '
779
780 test_expect_success 'format-patch notes output control' '
781         git notes add -m "notes config message" HEAD &&
782         test_when_finished git notes remove HEAD &&
783
784         git format-patch -1 --stdout >out &&
785         ! grep "notes config message" out &&
786         git format-patch -1 --stdout --notes >out &&
787         grep "notes config message" out &&
788         git format-patch -1 --stdout --no-notes >out &&
789         ! grep "notes config message" out &&
790         git format-patch -1 --stdout --notes --no-notes >out &&
791         ! grep "notes config message" out &&
792         git format-patch -1 --stdout --no-notes --notes >out &&
793         grep "notes config message" out &&
794
795         test_config format.notes true &&
796         git format-patch -1 --stdout >out &&
797         grep "notes config message" out &&
798         git format-patch -1 --stdout --notes >out &&
799         grep "notes config message" out &&
800         git format-patch -1 --stdout --no-notes >out &&
801         ! grep "notes config message" out &&
802         git format-patch -1 --stdout --notes --no-notes >out &&
803         ! grep "notes config message" out &&
804         git format-patch -1 --stdout --no-notes --notes >out &&
805         grep "notes config message" out
806 '
807
808 test_expect_success 'format-patch with multiple notes refs' '
809         git notes --ref note1 add -m "this is note 1" HEAD &&
810         test_when_finished git notes --ref note1 remove HEAD &&
811         git notes --ref note2 add -m "this is note 2" HEAD &&
812         test_when_finished git notes --ref note2 remove HEAD &&
813
814         git format-patch -1 --stdout >out &&
815         ! grep "this is note 1" out &&
816         ! grep "this is note 2" out &&
817         git format-patch -1 --stdout --notes=note1 >out &&
818         grep "this is note 1" out &&
819         ! grep "this is note 2" out &&
820         git format-patch -1 --stdout --notes=note2 >out &&
821         ! grep "this is note 1" out &&
822         grep "this is note 2" out &&
823         git format-patch -1 --stdout --notes=note1 --notes=note2 >out &&
824         grep "this is note 1" out &&
825         grep "this is note 2" out &&
826
827         test_config format.notes note1 &&
828         git format-patch -1 --stdout >out &&
829         grep "this is note 1" out &&
830         ! grep "this is note 2" out &&
831         git format-patch -1 --stdout --no-notes >out &&
832         ! grep "this is note 1" out &&
833         ! grep "this is note 2" out &&
834         git format-patch -1 --stdout --notes=note2 >out &&
835         grep "this is note 1" out &&
836         grep "this is note 2" out &&
837         git format-patch -1 --stdout --no-notes --notes=note2 >out &&
838         ! grep "this is note 1" out &&
839         grep "this is note 2" out &&
840
841         git config --add format.notes note2 &&
842         git format-patch -1 --stdout >out &&
843         grep "this is note 1" out &&
844         grep "this is note 2" out &&
845         git format-patch -1 --stdout --no-notes >out &&
846         ! grep "this is note 1" out &&
847         ! grep "this is note 2" out
848 '
849
850 test_expect_success 'format-patch with multiple notes refs in config' '
851         test_when_finished "test_unconfig format.notes" &&
852
853         git notes --ref note1 add -m "this is note 1" HEAD &&
854         test_when_finished git notes --ref note1 remove HEAD &&
855         git notes --ref note2 add -m "this is note 2" HEAD &&
856         test_when_finished git notes --ref note2 remove HEAD &&
857
858         git config format.notes note1 &&
859         git format-patch -1 --stdout >out &&
860         grep "this is note 1" out &&
861         ! grep "this is note 2" out &&
862         git config format.notes note2 &&
863         git format-patch -1 --stdout >out &&
864         ! grep "this is note 1" out &&
865         grep "this is note 2" out &&
866         git config --add format.notes note1 &&
867         git format-patch -1 --stdout >out &&
868         grep "this is note 1" out &&
869         grep "this is note 2" out &&
870
871         git config --replace-all format.notes note1 &&
872         git config --add format.notes false &&
873         git format-patch -1 --stdout >out &&
874         ! grep "this is note 1" out &&
875         ! grep "this is note 2" out &&
876         git config --add format.notes note2 &&
877         git format-patch -1 --stdout >out &&
878         ! grep "this is note 1" out &&
879         grep "this is note 2" out
880 '
881
882 echo "fatal: --name-only does not make sense" >expect.name-only
883 echo "fatal: --name-status does not make sense" >expect.name-status
884 echo "fatal: --check does not make sense" >expect.check
885
886 test_expect_success 'options no longer allowed for format-patch' '
887         test_must_fail git format-patch --name-only 2>output &&
888         test_i18ncmp expect.name-only output &&
889         test_must_fail git format-patch --name-status 2>output &&
890         test_i18ncmp expect.name-status output &&
891         test_must_fail git format-patch --check 2>output &&
892         test_i18ncmp expect.check output
893 '
894
895 test_expect_success 'format-patch --numstat should produce a patch' '
896         git format-patch --numstat --stdout master..side >output &&
897         grep "^diff --git a/" output >diff &&
898         test_line_count = 5 diff
899 '
900
901 test_expect_success 'format-patch -- <path>' '
902         git format-patch master..side -- file 2>error &&
903         ! grep "Use .--" error
904 '
905
906 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
907         git format-patch --ignore-if-in-upstream HEAD
908 '
909
910 test_expect_success 'get git version' '
911         git_version=$(git --version) &&
912         git_version=${git_version##* }
913 '
914
915 signature() {
916         printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
917 }
918
919 test_expect_success 'format-patch default signature' '
920         git format-patch --stdout -1 >patch &&
921         tail -n 3 patch >output &&
922         signature >expect &&
923         test_cmp expect output
924 '
925
926 test_expect_success 'format-patch --signature' '
927         git format-patch --stdout --signature="my sig" -1 >patch &&
928         tail -n 3 patch >output &&
929         signature "my sig" >expect &&
930         test_cmp expect output
931 '
932
933 test_expect_success 'format-patch with format.signature config' '
934         git config format.signature "config sig" &&
935         git format-patch --stdout -1 >output &&
936         grep "config sig" output
937 '
938
939 test_expect_success 'format-patch --signature overrides format.signature' '
940         git config format.signature "config sig" &&
941         git format-patch --stdout --signature="overrides" -1 >output &&
942         ! grep "config sig" output &&
943         grep "overrides" output
944 '
945
946 test_expect_success 'format-patch --no-signature ignores format.signature' '
947         git config format.signature "config sig" &&
948         git format-patch --stdout --signature="my sig" --no-signature \
949                 -1 >output &&
950         check_patch output &&
951         ! grep "config sig" output &&
952         ! grep "my sig" output &&
953         ! grep "^-- \$" output
954 '
955
956 test_expect_success 'format-patch --signature --cover-letter' '
957         git config --unset-all format.signature &&
958         git format-patch --stdout --signature="my sig" --cover-letter \
959                 -1 >output &&
960         grep "my sig" output >sig &&
961         test_line_count = 2 sig
962 '
963
964 test_expect_success 'format.signature="" suppresses signatures' '
965         git config format.signature "" &&
966         git format-patch --stdout -1 >output &&
967         check_patch output &&
968         ! grep "^-- \$" output
969 '
970
971 test_expect_success 'format-patch --no-signature suppresses signatures' '
972         git config --unset-all format.signature &&
973         git format-patch --stdout --no-signature -1 >output &&
974         check_patch output &&
975         ! grep "^-- \$" output
976 '
977
978 test_expect_success 'format-patch --signature="" suppresses signatures' '
979         git format-patch --stdout --signature="" -1 >output &&
980         check_patch output &&
981         ! grep "^-- \$" output
982 '
983
984 test_expect_success 'prepare mail-signature input' '
985         cat >mail-signature <<-\EOF
986
987         Test User <test.email@kernel.org>
988         http://git.kernel.org/cgit/git/git.git
989
990         git.kernel.org/?p=git/git.git;a=summary
991
992         EOF
993 '
994
995 test_expect_success '--signature-file=file works' '
996         git format-patch --stdout --signature-file=mail-signature -1 >output &&
997         check_patch output &&
998         sed -e "1,/^-- \$/d" output >actual &&
999         {
1000                 cat mail-signature && echo
1001         } >expect &&
1002         test_cmp expect actual
1003 '
1004
1005 test_expect_success 'format.signaturefile works' '
1006         test_config format.signaturefile mail-signature &&
1007         git format-patch --stdout -1 >output &&
1008         check_patch output &&
1009         sed -e "1,/^-- \$/d" output >actual &&
1010         {
1011                 cat mail-signature && echo
1012         } >expect &&
1013         test_cmp expect actual
1014 '
1015
1016 test_expect_success '--no-signature suppresses format.signaturefile ' '
1017         test_config format.signaturefile mail-signature &&
1018         git format-patch --stdout --no-signature -1 >output &&
1019         check_patch output &&
1020         ! grep "^-- \$" output
1021 '
1022
1023 test_expect_success '--signature-file overrides format.signaturefile' '
1024         cat >other-mail-signature <<-\EOF &&
1025         Use this other signature instead of mail-signature.
1026         EOF
1027         test_config format.signaturefile mail-signature &&
1028         git format-patch --stdout \
1029                         --signature-file=other-mail-signature -1 >output &&
1030         check_patch output &&
1031         sed -e "1,/^-- \$/d" output >actual &&
1032         {
1033                 cat other-mail-signature && echo
1034         } >expect &&
1035         test_cmp expect actual
1036 '
1037
1038 test_expect_success '--signature overrides format.signaturefile' '
1039         test_config format.signaturefile mail-signature &&
1040         git format-patch --stdout --signature="my sig" -1 >output &&
1041         check_patch output &&
1042         grep "my sig" output
1043 '
1044
1045 test_expect_success TTY 'format-patch --stdout paginates' '
1046         rm -f pager_used &&
1047         test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
1048         test_path_is_file pager_used
1049 '
1050
1051  test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
1052         rm -f pager_used &&
1053         test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
1054         test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
1055         test_path_is_missing pager_used &&
1056         test_path_is_missing .git/pager_used
1057 '
1058
1059 test_expect_success 'format-patch handles multi-line subjects' '
1060         rm -rf patches/ &&
1061         echo content >>file &&
1062         for i in one two three; do echo $i; done >msg &&
1063         git add file &&
1064         git commit -F msg &&
1065         git format-patch -o patches -1 &&
1066         grep ^Subject: patches/0001-one.patch >actual &&
1067         echo "Subject: [PATCH] one two three" >expect &&
1068         test_cmp expect actual
1069 '
1070
1071 test_expect_success 'format-patch handles multi-line encoded subjects' '
1072         rm -rf patches/ &&
1073         echo content >>file &&
1074         for i in en två tre; do echo $i; done >msg &&
1075         git add file &&
1076         git commit -F msg &&
1077         git format-patch -o patches -1 &&
1078         grep ^Subject: patches/0001-en.patch >actual &&
1079         echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
1080         test_cmp expect actual
1081 '
1082
1083 M8="foo bar "
1084 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1085 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1086 cat >expect <<'EOF'
1087 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1088  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1089  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1090  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1091  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1092  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1093  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1094 EOF
1095 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
1096         echo content >>file &&
1097         git add file &&
1098         git commit -m "$M512" &&
1099         git format-patch --stdout -1 >patch &&
1100         sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1101         test_cmp expect subject
1102 '
1103
1104 M8="föö bar "
1105 M64=$M8$M8$M8$M8$M8$M8$M8$M8
1106 M512=$M64$M64$M64$M64$M64$M64$M64$M64
1107 cat >expect <<'EOF'
1108 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1109  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1110  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1111  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1112  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1113  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1114  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1115  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1116  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1117  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1118  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1119  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1120  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1121  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1122  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1123  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1124  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1125  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1126  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1127  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1128  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1129  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1130  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1131  =?UTF-8?q?bar?=
1132 EOF
1133 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
1134         rm -rf patches/ &&
1135         echo content >>file &&
1136         git add file &&
1137         git commit -m "$M512" &&
1138         git format-patch --stdout -1 >patch &&
1139         sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
1140         test_cmp expect subject
1141 '
1142
1143 check_author() {
1144         echo content >>file &&
1145         git add file &&
1146         GIT_AUTHOR_NAME=$1 git commit -m author-check &&
1147         git format-patch --stdout -1 >patch &&
1148         sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1149         test_cmp expect actual
1150 }
1151
1152 cat >expect <<'EOF'
1153 From: "Foo B. Bar" <author@example.com>
1154 EOF
1155 test_expect_success 'format-patch quotes dot in from-headers' '
1156         check_author "Foo B. Bar"
1157 '
1158
1159 cat >expect <<'EOF'
1160 From: "Foo \"The Baz\" Bar" <author@example.com>
1161 EOF
1162 test_expect_success 'format-patch quotes double-quote in from-headers' '
1163         check_author "Foo \"The Baz\" Bar"
1164 '
1165
1166 cat >expect <<'EOF'
1167 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1168 EOF
1169 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1170         check_author "Föo Bar"
1171 '
1172
1173 cat >expect <<'EOF'
1174 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1175 EOF
1176 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1177         check_author "Föo B. Bar"
1178 '
1179
1180 cat >expect <<EOF
1181 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1182  <author@example.com>
1183 EOF
1184 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1185         check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1186 '
1187
1188 cat >expect <<'EOF'
1189 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1190  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1191  Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1192 EOF
1193 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1194         check_author "Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
1195 '
1196
1197 cat >expect <<'EOF'
1198 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1199  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1200  Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1201 EOF
1202 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1203         check_author "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
1204 '
1205
1206 cat >expect <<'EOF'
1207 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1208  =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1209  =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1210  =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1211  =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1212 EOF
1213 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1214         check_author "Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar"
1215 '
1216
1217 cat >expect <<'EOF'
1218 From: Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1219  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1220  Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1221 EOF
1222 test_expect_success 'format-patch wraps extremely long from-header (non-ASCII without Q-encoding)' '
1223         echo content >>file &&
1224         git add file &&
1225         GIT_AUTHOR_NAME="Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar" \
1226         git commit -m author-check &&
1227         git format-patch --no-encode-email-headers --stdout -1 >patch &&
1228         sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
1229         test_cmp expect actual
1230 '
1231
1232 cat >expect <<'EOF'
1233 Subject: [PATCH] Foö
1234 EOF
1235 test_expect_success 'subject lines are unencoded with --no-encode-email-headers' '
1236         echo content >>file &&
1237         git add file &&
1238         git commit -m "Foö" &&
1239         git format-patch --no-encode-email-headers -1 --stdout >patch &&
1240         grep ^Subject: patch >actual &&
1241         test_cmp expect actual
1242 '
1243
1244 cat >expect <<'EOF'
1245 Subject: [PATCH] Foö
1246 EOF
1247 test_expect_success 'subject lines are unencoded with format.encodeEmailHeaders=false' '
1248         echo content >>file &&
1249         git add file &&
1250         git commit -m "Foö" &&
1251         git config format.encodeEmailHeaders false &&
1252         git format-patch -1 --stdout >patch &&
1253         grep ^Subject: patch >actual &&
1254         test_cmp expect actual
1255 '
1256
1257 cat >expect <<'EOF'
1258 Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?=
1259 EOF
1260 test_expect_success '--encode-email-headers overrides format.encodeEmailHeaders' '
1261         echo content >>file &&
1262         git add file &&
1263         git commit -m "Foö" &&
1264         git config format.encodeEmailHeaders false &&
1265         git format-patch --encode-email-headers -1 --stdout >patch &&
1266         grep ^Subject: patch >actual &&
1267         test_cmp expect actual
1268 '
1269
1270 cat >expect <<'EOF'
1271 Subject: header with . in it
1272 EOF
1273 test_expect_success 'subject lines do not have 822 atom-quoting' '
1274         echo content >>file &&
1275         git add file &&
1276         git commit -m "header with . in it" &&
1277         git format-patch -k -1 --stdout >patch &&
1278         grep ^Subject: patch >actual &&
1279         test_cmp expect actual
1280 '
1281
1282 cat >expect <<'EOF'
1283 Subject: [PREFIX 1/1] header with . in it
1284 EOF
1285 test_expect_success 'subject prefixes have space prepended' '
1286         git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1287         grep ^Subject: patch >actual &&
1288         test_cmp expect actual
1289 '
1290
1291 cat >expect <<'EOF'
1292 Subject: [1/1] header with . in it
1293 EOF
1294 test_expect_success 'empty subject prefix does not have extra space' '
1295         git format-patch -n -1 --stdout --subject-prefix= >patch &&
1296         grep ^Subject: patch >actual &&
1297         test_cmp expect actual
1298 '
1299
1300 test_expect_success '--rfc' '
1301         cat >expect <<-\EOF &&
1302         Subject: [RFC PATCH 1/1] header with . in it
1303         EOF
1304         git format-patch -n -1 --stdout --rfc >patch &&
1305         grep ^Subject: patch >actual &&
1306         test_cmp expect actual
1307 '
1308
1309 test_expect_success '--from=ident notices bogus ident' '
1310         test_must_fail git format-patch -1 --stdout --from=foo >patch
1311 '
1312
1313 test_expect_success '--from=ident replaces author' '
1314         git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1315         cat >expect <<-\EOF &&
1316         From: Me <me@example.com>
1317
1318         From: A U Thor <author@example.com>
1319
1320         EOF
1321         sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1322         test_cmp expect patch.head
1323 '
1324
1325 test_expect_success '--from uses committer ident' '
1326         git format-patch -1 --stdout --from >patch &&
1327         cat >expect <<-\EOF &&
1328         From: C O Mitter <committer@example.com>
1329
1330         From: A U Thor <author@example.com>
1331
1332         EOF
1333         sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1334         test_cmp expect patch.head
1335 '
1336
1337 test_expect_success '--from omits redundant in-body header' '
1338         git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1339         cat >expect <<-\EOF &&
1340         From: A U Thor <author@example.com>
1341
1342         EOF
1343         sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
1344         test_cmp expect patch.head
1345 '
1346
1347 test_expect_success 'in-body headers trigger content encoding' '
1348         test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1349         test_when_finished "git reset --hard HEAD^" &&
1350         git format-patch -1 --stdout --from >patch &&
1351         cat >expect <<-\EOF &&
1352         From: C O Mitter <committer@example.com>
1353         Content-Type: text/plain; charset=UTF-8
1354
1355         From: éxötìc <author@example.com>
1356
1357         EOF
1358         sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
1359         test_cmp expect patch.head
1360 '
1361
1362 append_signoff()
1363 {
1364         C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1365         git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1366         sed -n -e "1,/^---$/p" append_signoff.patch |
1367                 egrep -n "^Subject|Sign|^$"
1368 }
1369
1370 test_expect_success 'signoff: commit with no body' '
1371         append_signoff </dev/null >actual &&
1372         cat <<-\EOF | sed "s/EOL$//" >expect &&
1373         4:Subject: [PATCH] EOL
1374         8:
1375         9:Signed-off-by: C O Mitter <committer@example.com>
1376         EOF
1377         test_cmp expect actual
1378 '
1379
1380 test_expect_success 'signoff: commit with only subject' '
1381         echo subject | append_signoff >actual &&
1382         cat >expect <<-\EOF &&
1383         4:Subject: [PATCH] subject
1384         8:
1385         9:Signed-off-by: C O Mitter <committer@example.com>
1386         EOF
1387         test_cmp expect actual
1388 '
1389
1390 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1391         printf subject | append_signoff >actual &&
1392         cat >expect <<-\EOF &&
1393         4:Subject: [PATCH] subject
1394         8:
1395         9:Signed-off-by: C O Mitter <committer@example.com>
1396         EOF
1397         test_cmp expect actual
1398 '
1399
1400 test_expect_success 'signoff: no existing signoffs' '
1401         append_signoff <<-\EOF >actual &&
1402         subject
1403
1404         body
1405         EOF
1406         cat >expect <<-\EOF &&
1407         4:Subject: [PATCH] subject
1408         8:
1409         10:
1410         11:Signed-off-by: C O Mitter <committer@example.com>
1411         EOF
1412         test_cmp expect actual
1413 '
1414
1415 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1416         printf "subject\n\nbody" | append_signoff >actual &&
1417         cat >expect <<-\EOF &&
1418         4:Subject: [PATCH] subject
1419         8:
1420         10:
1421         11:Signed-off-by: C O Mitter <committer@example.com>
1422         EOF
1423         test_cmp expect actual
1424 '
1425
1426 test_expect_success 'signoff: some random signoff' '
1427         append_signoff <<-\EOF >actual &&
1428         subject
1429
1430         body
1431
1432         Signed-off-by: my@house
1433         EOF
1434         cat >expect <<-\EOF &&
1435         4:Subject: [PATCH] subject
1436         8:
1437         10:
1438         11:Signed-off-by: my@house
1439         12:Signed-off-by: C O Mitter <committer@example.com>
1440         EOF
1441         test_cmp expect actual
1442 '
1443
1444 test_expect_success 'signoff: misc conforming footer elements' '
1445         append_signoff <<-\EOF >actual &&
1446         subject
1447
1448         body
1449
1450         Signed-off-by: my@house
1451         (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1452         Tested-by: Some One <someone@example.com>
1453         Bug: 1234
1454         EOF
1455         cat >expect <<-\EOF &&
1456         4:Subject: [PATCH] subject
1457         8:
1458         10:
1459         11:Signed-off-by: my@house
1460         15:Signed-off-by: C O Mitter <committer@example.com>
1461         EOF
1462         test_cmp expect actual
1463 '
1464
1465 test_expect_success 'signoff: some random signoff-alike' '
1466         append_signoff <<-\EOF >actual &&
1467         subject
1468
1469         body
1470         Fooled-by-me: my@house
1471         EOF
1472         cat >expect <<-\EOF &&
1473         4:Subject: [PATCH] subject
1474         8:
1475         11:
1476         12:Signed-off-by: C O Mitter <committer@example.com>
1477         EOF
1478         test_cmp expect actual
1479 '
1480
1481 test_expect_success 'signoff: not really a signoff' '
1482         append_signoff <<-\EOF >actual &&
1483         subject
1484
1485         I want to mention about Signed-off-by: here.
1486         EOF
1487         cat >expect <<-\EOF &&
1488         4:Subject: [PATCH] subject
1489         8:
1490         9:I want to mention about Signed-off-by: here.
1491         10:
1492         11:Signed-off-by: C O Mitter <committer@example.com>
1493         EOF
1494         test_cmp expect actual
1495 '
1496
1497 test_expect_success 'signoff: not really a signoff (2)' '
1498         append_signoff <<-\EOF >actual &&
1499         subject
1500
1501         My unfortunate
1502         Signed-off-by: example happens to be wrapped here.
1503         EOF
1504         cat >expect <<-\EOF &&
1505         4:Subject: [PATCH] subject
1506         8:
1507         10:Signed-off-by: example happens to be wrapped here.
1508         11:Signed-off-by: C O Mitter <committer@example.com>
1509         EOF
1510         test_cmp expect actual
1511 '
1512
1513 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1514         append_signoff <<-\EOF >actual &&
1515         subject
1516
1517         Signed-off-by: my@house
1518         Signed-off-by: your@house
1519
1520         A lot of houses.
1521         EOF
1522         cat >expect <<-\EOF &&
1523         4:Subject: [PATCH] subject
1524         8:
1525         9:Signed-off-by: my@house
1526         10:Signed-off-by: your@house
1527         11:
1528         13:
1529         14:Signed-off-by: C O Mitter <committer@example.com>
1530         EOF
1531         test_cmp expect actual
1532 '
1533
1534 test_expect_success 'signoff: the same signoff at the end' '
1535         append_signoff <<-\EOF >actual &&
1536         subject
1537
1538         body
1539
1540         Signed-off-by: C O Mitter <committer@example.com>
1541         EOF
1542         cat >expect <<-\EOF &&
1543         4:Subject: [PATCH] subject
1544         8:
1545         10:
1546         11:Signed-off-by: C O Mitter <committer@example.com>
1547         EOF
1548         test_cmp expect actual
1549 '
1550
1551 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1552         printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1553                 append_signoff >actual &&
1554         cat >expect <<-\EOF &&
1555         4:Subject: [PATCH] subject
1556         8:
1557         9:Signed-off-by: C O Mitter <committer@example.com>
1558         EOF
1559         test_cmp expect actual
1560 '
1561
1562 test_expect_success 'signoff: the same signoff NOT at the end' '
1563         append_signoff <<-\EOF >actual &&
1564         subject
1565
1566         body
1567
1568         Signed-off-by: C O Mitter <committer@example.com>
1569         Signed-off-by: my@house
1570         EOF
1571         cat >expect <<-\EOF &&
1572         4:Subject: [PATCH] subject
1573         8:
1574         10:
1575         11:Signed-off-by: C O Mitter <committer@example.com>
1576         12:Signed-off-by: my@house
1577         EOF
1578         test_cmp expect actual
1579 '
1580
1581 test_expect_success 'signoff: tolerate garbage in conforming footer' '
1582         append_signoff <<-\EOF >actual &&
1583         subject
1584
1585         body
1586
1587         Tested-by: my@house
1588         Some Trash
1589         Signed-off-by: C O Mitter <committer@example.com>
1590         EOF
1591         cat >expect <<-\EOF &&
1592         4:Subject: [PATCH] subject
1593         8:
1594         10:
1595         13:Signed-off-by: C O Mitter <committer@example.com>
1596         EOF
1597         test_cmp expect actual
1598 '
1599
1600 test_expect_success 'signoff: respect trailer config' '
1601         append_signoff <<-\EOF >actual &&
1602         subject
1603
1604         Myfooter: x
1605         Some Trash
1606         EOF
1607         cat >expect <<-\EOF &&
1608         4:Subject: [PATCH] subject
1609         8:
1610         11:
1611         12:Signed-off-by: C O Mitter <committer@example.com>
1612         EOF
1613         test_cmp expect actual &&
1614
1615         test_config trailer.Myfooter.ifexists add &&
1616         append_signoff <<-\EOF >actual &&
1617         subject
1618
1619         Myfooter: x
1620         Some Trash
1621         EOF
1622         cat >expect <<-\EOF &&
1623         4:Subject: [PATCH] subject
1624         8:
1625         11:Signed-off-by: C O Mitter <committer@example.com>
1626         EOF
1627         test_cmp expect actual
1628 '
1629
1630 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1631         append_signoff <<-\EOF >actual &&
1632         subject
1633
1634         body
1635
1636         Reviewed-id: Noone
1637         Tested-by: my@house
1638         Change-id: Ideadbeef
1639         Signed-off-by: C O Mitter <committer@example.com>
1640         Bug: 1234
1641         EOF
1642         cat >expect <<-\EOF &&
1643         4:Subject: [PATCH] subject
1644         8:
1645         10:
1646         14:Signed-off-by: C O Mitter <committer@example.com>
1647         EOF
1648         test_cmp expect actual
1649 '
1650
1651 test_expect_success 'format patch ignores color.ui' '
1652         test_unconfig color.ui &&
1653         git format-patch --stdout -1 >expect &&
1654         test_config color.ui always &&
1655         git format-patch --stdout -1 >actual &&
1656         test_cmp expect actual
1657 '
1658
1659 test_expect_success 'format patch respects diff.relative' '
1660         rm -rf subdir &&
1661         mkdir subdir &&
1662         echo other content >subdir/file2 &&
1663         git add subdir/file2 &&
1664         git commit -F msg &&
1665         test_unconfig diff.relative &&
1666         git format-patch --relative=subdir --stdout -1 >expect &&
1667         test_config diff.relative true &&
1668         git -C subdir format-patch --stdout -1 >actual &&
1669         test_cmp expect actual
1670 '
1671
1672 test_expect_success 'cover letter with invalid --cover-from-description and config' '
1673         test_config branch.rebuild-1.description "config subject
1674
1675 body" &&
1676         test_must_fail git format-patch --cover-letter --cover-from-description garbage master &&
1677         test_config format.coverFromDescription garbage &&
1678         test_must_fail git format-patch --cover-letter master
1679 '
1680
1681 test_expect_success 'cover letter with format.coverFromDescription = default' '
1682         test_config branch.rebuild-1.description "config subject
1683
1684 body" &&
1685         test_config format.coverFromDescription default &&
1686         git checkout rebuild-1 &&
1687         git format-patch --stdout --cover-letter master >actual &&
1688         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1689         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1690         grep "^config subject$" actual &&
1691         grep "^body$" actual
1692 '
1693
1694 test_expect_success 'cover letter with --cover-from-description default' '
1695         test_config branch.rebuild-1.description "config subject
1696
1697 body" &&
1698         git checkout rebuild-1 &&
1699         git format-patch --stdout --cover-letter --cover-from-description default master >actual &&
1700         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1701         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1702         grep "^config subject$" actual &&
1703         grep "^body$" actual
1704 '
1705
1706 test_expect_success 'cover letter with format.coverFromDescription = none' '
1707         test_config branch.rebuild-1.description "config subject
1708
1709 body" &&
1710         test_config format.coverFromDescription none &&
1711         git checkout rebuild-1 &&
1712         git format-patch --stdout --cover-letter master >actual &&
1713         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1714         grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1715         ! grep "^config subject$" actual &&
1716         ! grep "^body$" actual
1717 '
1718
1719 test_expect_success 'cover letter with --cover-from-description none' '
1720         test_config branch.rebuild-1.description "config subject
1721
1722 body" &&
1723         git checkout rebuild-1 &&
1724         git format-patch --stdout --cover-letter --cover-from-description none master >actual &&
1725         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1726         grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1727         ! grep "^config subject$" actual &&
1728         ! grep "^body$" actual
1729 '
1730
1731 test_expect_success 'cover letter with format.coverFromDescription = message' '
1732         test_config branch.rebuild-1.description "config subject
1733
1734 body" &&
1735         test_config format.coverFromDescription message &&
1736         git checkout rebuild-1 &&
1737         git format-patch --stdout --cover-letter master >actual &&
1738         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1739         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1740         grep "^config subject$" actual &&
1741         grep "^body$" actual
1742 '
1743
1744 test_expect_success 'cover letter with --cover-from-description message' '
1745         test_config branch.rebuild-1.description "config subject
1746
1747 body" &&
1748         git checkout rebuild-1 &&
1749         git format-patch --stdout --cover-letter --cover-from-description message master >actual &&
1750         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1751         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1752         grep "^config subject$" actual &&
1753         grep "^body$" actual
1754 '
1755
1756 test_expect_success 'cover letter with format.coverFromDescription = subject' '
1757         test_config branch.rebuild-1.description "config subject
1758
1759 body" &&
1760         test_config format.coverFromDescription subject &&
1761         git checkout rebuild-1 &&
1762         git format-patch --stdout --cover-letter master >actual &&
1763         grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1764         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1765         ! grep "^config subject$" actual &&
1766         grep "^body$" actual
1767 '
1768
1769 test_expect_success 'cover letter with --cover-from-description subject' '
1770         test_config branch.rebuild-1.description "config subject
1771
1772 body" &&
1773         git checkout rebuild-1 &&
1774         git format-patch --stdout --cover-letter --cover-from-description subject master >actual &&
1775         grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1776         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1777         ! grep "^config subject$" actual &&
1778         grep "^body$" actual
1779 '
1780
1781 test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '
1782         test_config branch.rebuild-1.description "config subject
1783
1784 body" &&
1785         test_config format.coverFromDescription auto &&
1786         git checkout rebuild-1 &&
1787         git format-patch --stdout --cover-letter master >actual &&
1788         grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1789         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1790         ! grep "^config subject$" actual &&
1791         grep "^body$" actual
1792 '
1793
1794 test_expect_success 'cover letter with --cover-from-description auto (short subject line)' '
1795         test_config branch.rebuild-1.description "config subject
1796
1797 body" &&
1798         git checkout rebuild-1 &&
1799         git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1800         grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1801         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1802         ! grep "^config subject$" actual &&
1803         grep "^body$" actual
1804 '
1805
1806 test_expect_success 'cover letter with format.coverFromDescription = auto (long subject line)' '
1807         test_config branch.rebuild-1.description "this is a really long first line and it is over 100 characters long which is the threshold for long subjects
1808
1809 body" &&
1810         test_config format.coverFromDescription auto &&
1811         git checkout rebuild-1 &&
1812         git format-patch --stdout --cover-letter master >actual &&
1813         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1814         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1815         grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1816         grep "^body$" actual
1817 '
1818
1819 test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '
1820         test_config branch.rebuild-1.description "this is a really long first line and it is over 100 characters long which is the threshold for long subjects
1821
1822 body" &&
1823         git checkout rebuild-1 &&
1824         git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1825         grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1826         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1827         grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1828         grep "^body$" actual
1829 '
1830
1831 test_expect_success 'cover letter with command-line --cover-from-description overrides config' '
1832         test_config branch.rebuild-1.description "config subject
1833
1834 body" &&
1835         test_config format.coverFromDescription none &&
1836         git checkout rebuild-1 &&
1837         git format-patch --stdout --cover-letter --cover-from-description subject master >actual &&
1838         grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1839         ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1840         ! grep "^config subject$" actual &&
1841         grep "^body$" actual
1842 '
1843
1844 test_expect_success 'cover letter using branch description (1)' '
1845         git checkout rebuild-1 &&
1846         test_config branch.rebuild-1.description hello &&
1847         git format-patch --stdout --cover-letter master >actual &&
1848         grep hello actual
1849 '
1850
1851 test_expect_success 'cover letter using branch description (2)' '
1852         git checkout rebuild-1 &&
1853         test_config branch.rebuild-1.description hello &&
1854         git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1855         grep hello actual
1856 '
1857
1858 test_expect_success 'cover letter using branch description (3)' '
1859         git checkout rebuild-1 &&
1860         test_config branch.rebuild-1.description hello &&
1861         git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1862         grep hello actual
1863 '
1864
1865 test_expect_success 'cover letter using branch description (4)' '
1866         git checkout rebuild-1 &&
1867         test_config branch.rebuild-1.description hello &&
1868         git format-patch --stdout --cover-letter master.. >actual &&
1869         grep hello actual
1870 '
1871
1872 test_expect_success 'cover letter using branch description (5)' '
1873         git checkout rebuild-1 &&
1874         test_config branch.rebuild-1.description hello &&
1875         git format-patch --stdout --cover-letter -2 HEAD >actual &&
1876         grep hello actual
1877 '
1878
1879 test_expect_success 'cover letter using branch description (6)' '
1880         git checkout rebuild-1 &&
1881         test_config branch.rebuild-1.description hello &&
1882         git format-patch --stdout --cover-letter -2 >actual &&
1883         grep hello actual
1884 '
1885
1886 test_expect_success 'cover letter with nothing' '
1887         git format-patch --stdout --cover-letter >actual &&
1888         test_line_count = 0 actual
1889 '
1890
1891 test_expect_success 'cover letter auto' '
1892         mkdir -p tmp &&
1893         test_when_finished "rm -rf tmp;
1894                 git config --unset format.coverletter" &&
1895
1896         git config format.coverletter auto &&
1897         git format-patch -o tmp -1 >list &&
1898         test_line_count = 1 list &&
1899         git format-patch -o tmp -2 >list &&
1900         test_line_count = 3 list
1901 '
1902
1903 test_expect_success 'cover letter auto user override' '
1904         mkdir -p tmp &&
1905         test_when_finished "rm -rf tmp;
1906                 git config --unset format.coverletter" &&
1907
1908         git config format.coverletter auto &&
1909         git format-patch -o tmp --cover-letter -1 >list &&
1910         test_line_count = 2 list &&
1911         git format-patch -o tmp --cover-letter -2 >list &&
1912         test_line_count = 3 list &&
1913         git format-patch -o tmp --no-cover-letter -1 >list &&
1914         test_line_count = 1 list &&
1915         git format-patch -o tmp --no-cover-letter -2 >list &&
1916         test_line_count = 2 list
1917 '
1918
1919 test_expect_success 'format-patch --zero-commit' '
1920         git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1921         grep "^From " patch2 | sort | uniq >actual &&
1922         echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
1923         test_cmp expect actual
1924 '
1925
1926 test_expect_success 'From line has expected format' '
1927         git format-patch --stdout v2..v1 >patch2 &&
1928         grep "^From " patch2 >from &&
1929         grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1930         test_cmp from filtered
1931 '
1932
1933 test_expect_success 'format-patch -o with no leading directories' '
1934         rm -fr patches &&
1935         git format-patch -o patches master..side &&
1936         count=$(git rev-list --count master..side) &&
1937         ls patches >list &&
1938         test_line_count = $count list
1939 '
1940
1941 test_expect_success 'format-patch -o with leading existing directories' '
1942         rm -rf existing-dir &&
1943         mkdir existing-dir &&
1944         git format-patch -o existing-dir/patches master..side &&
1945         count=$(git rev-list --count master..side) &&
1946         ls existing-dir/patches >list &&
1947         test_line_count = $count list
1948 '
1949
1950 test_expect_success 'format-patch -o with leading non-existing directories' '
1951         rm -rf non-existing-dir &&
1952         git format-patch -o non-existing-dir/patches master..side &&
1953         count=$(git rev-list --count master..side) &&
1954         test_path_is_dir non-existing-dir &&
1955         ls non-existing-dir/patches >list &&
1956         test_line_count = $count list
1957 '
1958
1959 test_expect_success 'format-patch format.outputDirectory option' '
1960         test_config format.outputDirectory patches &&
1961         rm -fr patches &&
1962         git format-patch master..side &&
1963         count=$(git rev-list --count master..side) &&
1964         ls patches >list &&
1965         test_line_count = $count list
1966 '
1967
1968 test_expect_success 'format-patch -o overrides format.outputDirectory' '
1969         test_config format.outputDirectory patches &&
1970         rm -fr patches patchset &&
1971         git format-patch master..side -o patchset &&
1972         test_path_is_missing patches &&
1973         test_path_is_dir patchset
1974 '
1975
1976 test_expect_success 'format-patch forbids multiple outputs' '
1977         rm -fr outfile outdir &&
1978         test_must_fail \
1979                 git format-patch --stdout --output-directory=outdir &&
1980         test_must_fail \
1981                 git format-patch --stdout --output=outfile &&
1982         test_must_fail \
1983                 git format-patch --output=outfile --output-directory=outdir
1984 '
1985
1986 test_expect_success 'configured outdir does not conflict with output options' '
1987         rm -fr outfile outdir &&
1988         test_config format.outputDirectory outdir &&
1989         git format-patch --stdout &&
1990         test_path_is_missing outdir &&
1991         git format-patch --output=outfile &&
1992         test_path_is_missing outdir
1993 '
1994
1995 test_expect_success 'format-patch --output' '
1996         rm -fr outfile &&
1997         git format-patch -3 --stdout HEAD >expect &&
1998         git format-patch -3 --output=outfile HEAD &&
1999         test_cmp expect outfile
2000 '
2001
2002 test_expect_success 'format-patch --cover-letter --output' '
2003         rm -fr outfile &&
2004         git format-patch --cover-letter -3 --stdout HEAD >expect &&
2005         git format-patch --cover-letter -3 --output=outfile HEAD &&
2006         test_cmp expect outfile
2007 '
2008
2009 test_expect_success 'format-patch --base' '
2010         git checkout patchid &&
2011
2012         git format-patch --stdout --base=HEAD~3 -1 >patch &&
2013         tail -n 7 patch >actual1 &&
2014
2015         git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
2016         tail -n 7 patch >actual2 &&
2017
2018         echo >expect &&
2019         git rev-parse HEAD~3 >commit-id-base &&
2020         echo "base-commit: $(cat commit-id-base)" >>expect &&
2021
2022         git show --patch HEAD~2 >patch &&
2023         git patch-id --stable <patch >patch.id.raw &&
2024         awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2025
2026         git show --patch HEAD~1 >patch &&
2027         git patch-id --stable <patch >patch.id.raw &&
2028         awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
2029
2030         signature >>expect &&
2031         test_cmp expect actual1 &&
2032         test_cmp expect actual2 &&
2033
2034         echo >fail &&
2035         echo "base-commit: $(cat commit-id-base)" >>fail &&
2036
2037         git show --patch HEAD~2 >patch &&
2038         git patch-id --unstable <patch >patch.id.raw &&
2039         awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2040
2041         git show --patch HEAD~1 >patch &&
2042         git patch-id --unstable <patch >patch.id.raw &&
2043         awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
2044
2045         signature >>fail &&
2046         ! test_cmp fail actual1 &&
2047         ! test_cmp fail actual2
2048 '
2049
2050 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
2051         test_must_fail git format-patch --base=HEAD -2 &&
2052         test_must_fail git format-patch --base=HEAD~1 -2 &&
2053         git format-patch --stdout --base=HEAD~2 -2 >patch &&
2054         grep "^base-commit:" patch >actual &&
2055         git rev-parse HEAD~2 >commit-id-base &&
2056         echo "base-commit: $(cat commit-id-base)" >expect &&
2057         test_cmp expect actual
2058 '
2059
2060 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
2061         # For history as below:
2062         #
2063         #    ---Q---P---Z---Y---*---X
2064         #        \             /
2065         #         ------------W
2066         #
2067         # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
2068         git checkout -b topic1 master &&
2069         git rev-parse HEAD >commit-id-base &&
2070         test_commit P &&
2071         git rev-parse HEAD >commit-id-P &&
2072         test_commit Z &&
2073         git rev-parse HEAD >commit-id-Z &&
2074         test_commit Y &&
2075         git checkout -b topic2 master &&
2076         test_commit W &&
2077         git merge topic1 &&
2078         test_commit X &&
2079         test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
2080         test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
2081         git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
2082         grep "^base-commit:" patch >actual &&
2083         echo "base-commit: $(cat commit-id-base)" >expect &&
2084         test_cmp expect actual
2085 '
2086
2087 test_expect_success 'format-patch --base=auto' '
2088         git checkout -b upstream master &&
2089         git checkout -b local upstream &&
2090         git branch --set-upstream-to=upstream &&
2091         test_commit N1 &&
2092         test_commit N2 &&
2093         git format-patch --stdout --base=auto -2 >patch &&
2094         grep "^base-commit:" patch >actual &&
2095         git rev-parse upstream >commit-id-base &&
2096         echo "base-commit: $(cat commit-id-base)" >expect &&
2097         test_cmp expect actual
2098 '
2099
2100 test_expect_success 'format-patch errors out when history involves criss-cross' '
2101         # setup criss-cross history
2102         #
2103         #   B---M1---D
2104         #  / \ /
2105         # A   X
2106         #  \ / \
2107         #   C---M2---E
2108         #
2109         git checkout master &&
2110         test_commit A &&
2111         git checkout -b xb master &&
2112         test_commit B &&
2113         git checkout -b xc master &&
2114         test_commit C &&
2115         git checkout -b xbc xb -- &&
2116         git merge xc &&
2117         git checkout -b xcb xc -- &&
2118         git branch --set-upstream-to=xbc &&
2119         git merge xb &&
2120         git checkout xbc &&
2121         test_commit D &&
2122         git checkout xcb &&
2123         test_commit E &&
2124         test_must_fail  git format-patch --base=auto -1
2125 '
2126
2127 test_expect_success 'format-patch format.useAutoBase whenAble history involves criss-cross' '
2128         test_config format.useAutoBase whenAble &&
2129         git format-patch -1 >patch &&
2130         ! grep "^base-commit:" patch
2131 '
2132
2133 test_expect_success 'format-patch format.useAutoBase option' '
2134         git checkout local &&
2135         test_config format.useAutoBase true &&
2136         git format-patch --stdout -1 >patch &&
2137         grep "^base-commit:" patch >actual &&
2138         git rev-parse upstream >commit-id-base &&
2139         echo "base-commit: $(cat commit-id-base)" >expect &&
2140         test_cmp expect actual
2141 '
2142
2143 test_expect_success 'format-patch format.useAutoBase option with whenAble' '
2144         git checkout local &&
2145         test_config format.useAutoBase whenAble &&
2146         git format-patch --stdout -1 >patch &&
2147         grep "^base-commit:" patch >actual &&
2148         git rev-parse upstream >commit-id-base &&
2149         echo "base-commit: $(cat commit-id-base)" >expect &&
2150         test_cmp expect actual
2151 '
2152
2153 test_expect_success 'format-patch --base overrides format.useAutoBase' '
2154         test_config format.useAutoBase true &&
2155         git format-patch --stdout --base=HEAD~1 -1 >patch &&
2156         grep "^base-commit:" patch >actual &&
2157         git rev-parse HEAD~1 >commit-id-base &&
2158         echo "base-commit: $(cat commit-id-base)" >expect &&
2159         test_cmp expect actual
2160 '
2161
2162 test_expect_success 'format-patch --no-base overrides format.useAutoBase' '
2163         test_config format.useAutoBase true &&
2164         git format-patch --stdout --no-base -1 >patch &&
2165         ! grep "^base-commit:" patch
2166 '
2167
2168 test_expect_success 'format-patch --no-base overrides format.useAutoBase whenAble' '
2169         test_config format.useAutoBase whenAble &&
2170         git format-patch --stdout --no-base -1 >patch &&
2171         ! grep "^base-commit:" patch
2172 '
2173
2174 test_expect_success 'format-patch --base with --attach' '
2175         git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
2176         sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
2177                 patch >actual &&
2178         test_write_lines 1 2 >expect &&
2179         test_cmp expect actual
2180 '
2181 test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
2182         test_when_finished "rm -fr patches" &&
2183         git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
2184         ! egrep "^--+mimemime" patches/0000*.patch &&
2185         egrep "^--+mimemime$" patches/0001*.patch >output &&
2186         test_line_count = 2 output &&
2187         egrep "^--+mimemime--$" patches/0001*.patch >output &&
2188         test_line_count = 1 output
2189 '
2190
2191 test_expect_success 'format-patch --pretty=mboxrd' '
2192         sp=" " &&
2193         cat >msg <<-INPUT_END &&
2194         mboxrd should escape the body
2195
2196         From could trip up a loose mbox parser
2197         >From extra escape for reversibility
2198         >>From extra escape for reversibility 2
2199         from lower case not escaped
2200         Fromm bad speling not escaped
2201          From with leading space not escaped
2202
2203         F
2204         From
2205         From$sp
2206         From    $sp
2207         From    $sp
2208         INPUT_END
2209
2210         cat >expect <<-INPUT_END &&
2211         >From could trip up a loose mbox parser
2212         >>From extra escape for reversibility
2213         >>>From extra escape for reversibility 2
2214         from lower case not escaped
2215         Fromm bad speling not escaped
2216          From with leading space not escaped
2217
2218         F
2219         From
2220         From
2221         From
2222         From
2223         INPUT_END
2224
2225         C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2226         git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
2227         git grep -h --no-index -A11 \
2228                 "^>From could trip up a loose mbox parser" patch >actual &&
2229         test_cmp expect actual
2230 '
2231
2232 test_expect_success 'interdiff: setup' '
2233         git checkout -b boop master &&
2234         test_commit fnorp blorp &&
2235         test_commit fleep blorp
2236 '
2237
2238 test_expect_success 'interdiff: cover-letter' '
2239         sed "y/q/ /" >expect <<-\EOF &&
2240         +fleep
2241         --q
2242         EOF
2243         git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2244         test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
2245         test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
2246         sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
2247         test_cmp expect actual
2248 '
2249
2250 test_expect_success 'interdiff: reroll-count' '
2251         git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2252         test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2253 '
2254
2255 test_expect_success 'interdiff: solo-patch' '
2256         cat >expect <<-\EOF &&
2257           +fleep
2258
2259         EOF
2260         git format-patch --interdiff=boop~2 -1 boop &&
2261         test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
2262         sed "1,/^  @@ /d; /^$/q" 0001-fleep.patch >actual &&
2263         test_cmp expect actual
2264 '
2265
2266 test_done