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