Merge branch 'cc/apply-am'
[git] / t / t4014-format-patch.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2006 Junio C Hamano
4 #
5
6 test_description='various format-patch tests'
7
8 . ./test-lib.sh
9 . "$TEST_DIRECTORY"/lib-terminal.sh
10
11 test_expect_success setup '
12
13         for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
14         cat file >elif &&
15         git add file elif &&
16         test_tick &&
17         git commit -m Initial &&
18         git checkout -b side &&
19
20         for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
21         test_chmod +x elif &&
22         test_tick &&
23         git commit -m "Side changes #1" &&
24
25         for i in D E F; do echo "$i"; done >>file &&
26         git update-index file &&
27         test_tick &&
28         git commit -m "Side changes #2" &&
29         git tag C2 &&
30
31         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
32         git update-index file &&
33         test_tick &&
34         git commit -m "Side changes #3 with \\n backslash-n in it." &&
35
36         git checkout master &&
37         git diff-tree -p C2 | git apply --index &&
38         test_tick &&
39         git commit -m "Master accepts moral equivalent of #2"
40
41 '
42
43 test_expect_success "format-patch --ignore-if-in-upstream" '
44
45         git format-patch --stdout master..side >patch0 &&
46         cnt=$(grep "^From " patch0 | wc -l) &&
47         test $cnt = 3
48
49 '
50
51 test_expect_success "format-patch --ignore-if-in-upstream" '
52
53         git format-patch --stdout \
54                 --ignore-if-in-upstream master..side >patch1 &&
55         cnt=$(grep "^From " patch1 | wc -l) &&
56         test $cnt = 2
57
58 '
59
60 test_expect_success "format-patch --ignore-if-in-upstream handles tags" '
61         git tag -a v1 -m tag side &&
62         git tag -a v2 -m tag master &&
63         git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
64         cnt=$(grep "^From " patch1 | wc -l) &&
65         test $cnt = 2
66 '
67
68 test_expect_success "format-patch doesn't consider merge commits" '
69
70         git checkout -b slave master &&
71         echo "Another line" >>file &&
72         test_tick &&
73         git commit -am "Slave change #1" &&
74         echo "Yet another line" >>file &&
75         test_tick &&
76         git commit -am "Slave change #2" &&
77         git checkout -b merger master &&
78         test_tick &&
79         git merge --no-ff slave &&
80         cnt=$(git format-patch -3 --stdout | grep "^From " | wc -l) &&
81         test $cnt = 3
82 '
83
84 test_expect_success "format-patch result applies" '
85
86         git checkout -b rebuild-0 master &&
87         git am -3 patch0 &&
88         cnt=$(git rev-list master.. | wc -l) &&
89         test $cnt = 2
90 '
91
92 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
93
94         git checkout -b rebuild-1 master &&
95         git am -3 patch1 &&
96         cnt=$(git rev-list master.. | wc -l) &&
97         test $cnt = 2
98 '
99
100 test_expect_success 'commit did not screw up the log message' '
101
102         git cat-file commit side | grep "^Side .* with .* backslash-n"
103
104 '
105
106 test_expect_success 'format-patch did not screw up the log message' '
107
108         grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
109         grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
110
111 '
112
113 test_expect_success 'replay did not screw up the log message' '
114
115         git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
116
117 '
118
119 test_expect_success 'extra headers' '
120
121         git config format.headers "To: R E Cipient <rcipient@example.com>
122 " &&
123         git config --add format.headers "Cc: S E Cipient <scipient@example.com>
124 " &&
125         git format-patch --stdout master..side > patch2 &&
126         sed -e "/^\$/q" patch2 > hdrs2 &&
127         grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
128         grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
129
130 '
131
132 test_expect_success 'extra headers without newlines' '
133
134         git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
135         git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
136         git format-patch --stdout master..side >patch3 &&
137         sed -e "/^\$/q" patch3 > hdrs3 &&
138         grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
139         grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
140
141 '
142
143 test_expect_success 'extra headers with multiple To:s' '
144
145         git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
146         git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
147         git format-patch --stdout master..side > patch4 &&
148         sed -e "/^\$/q" patch4 > hdrs4 &&
149         grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
150         grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
151 '
152
153 test_expect_success 'additional command line cc (ascii)' '
154
155         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
156         git format-patch --cc="S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
157         grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
158         grep "^ *S E Cipient <scipient@example.com>\$" patch5
159 '
160
161 test_expect_failure 'additional command line cc (rfc822)' '
162
163         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
164         git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
165         grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
166         grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" patch5
167 '
168
169 test_expect_success 'command line headers' '
170
171         git config --unset-all format.headers &&
172         git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
173         grep "^Cc: R E Cipient <rcipient@example.com>\$" patch6
174 '
175
176 test_expect_success 'configuration headers and command line headers' '
177
178         git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
179         git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
180         grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch7 &&
181         grep "^ *S E Cipient <scipient@example.com>\$" patch7
182 '
183
184 test_expect_success 'command line To: header (ascii)' '
185
186         git config --unset-all format.headers &&
187         git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
188         grep "^To: R E Cipient <rcipient@example.com>\$" patch8
189 '
190
191 test_expect_failure 'command line To: header (rfc822)' '
192
193         git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
194         grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch8
195 '
196
197 test_expect_failure 'command line To: header (rfc2047)' '
198
199         git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
200         grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch8
201 '
202
203 test_expect_success 'configuration To: header (ascii)' '
204
205         git config format.to "R E Cipient <rcipient@example.com>" &&
206         git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
207         grep "^To: R E Cipient <rcipient@example.com>\$" patch9
208 '
209
210 test_expect_failure 'configuration To: header (rfc822)' '
211
212         git config format.to "R. E. Cipient <rcipient@example.com>" &&
213         git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
214         grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch9
215 '
216
217 test_expect_failure 'configuration To: header (rfc2047)' '
218
219         git config format.to "R Ä Cipient <rcipient@example.com>" &&
220         git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
221         grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch9
222 '
223
224 # check_patch <patch>: Verify that <patch> looks like a half-sane
225 # patch email to avoid a false positive with !grep
226 check_patch () {
227         grep -e "^From:" "$1" &&
228         grep -e "^Date:" "$1" &&
229         grep -e "^Subject:" "$1"
230 }
231
232 test_expect_success 'format.from=false' '
233
234         git -c format.from=false format-patch --stdout master..side |
235         sed -e "/^\$/q" >patch &&
236         check_patch patch &&
237         ! grep "^From: C O Mitter <committer@example.com>\$" patch
238 '
239
240 test_expect_success 'format.from=true' '
241
242         git -c format.from=true format-patch --stdout master..side |
243         sed -e "/^\$/q" >patch &&
244         check_patch patch &&
245         grep "^From: C O Mitter <committer@example.com>\$" patch
246 '
247
248 test_expect_success 'format.from with address' '
249
250         git -c format.from="F R Om <from@example.com>" format-patch --stdout master..side |
251         sed -e "/^\$/q" >patch &&
252         check_patch patch &&
253         grep "^From: F R Om <from@example.com>\$" patch
254 '
255
256 test_expect_success '--no-from overrides format.from' '
257
258         git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout master..side |
259         sed -e "/^\$/q" >patch &&
260         check_patch patch &&
261         ! grep "^From: F R Om <from@example.com>\$" patch
262 '
263
264 test_expect_success '--from overrides format.from' '
265
266         git -c format.from="F R Om <from@example.com>" format-patch --from --stdout master..side |
267         sed -e "/^\$/q" >patch &&
268         check_patch patch &&
269         ! grep "^From: F R Om <from@example.com>\$" patch
270 '
271
272 test_expect_success '--no-to overrides config.to' '
273
274         git config --replace-all format.to \
275                 "R E Cipient <rcipient@example.com>" &&
276         git format-patch --no-to --stdout master..side |
277         sed -e "/^\$/q" >patch10 &&
278         check_patch patch10 &&
279         ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10
280 '
281
282 test_expect_success '--no-to and --to replaces config.to' '
283
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 master..side |
288         sed -e "/^\$/q" >patch11 &&
289         check_patch patch11 &&
290         ! grep "^To: Someone <someone@out.there>\$" patch11 &&
291         grep "^To: Someone Else <else@out.there>\$" patch11
292 '
293
294 test_expect_success '--no-cc overrides config.cc' '
295
296         git config --replace-all format.cc \
297                 "C E Cipient <rcipient@example.com>" &&
298         git format-patch --no-cc --stdout master..side |
299         sed -e "/^\$/q" >patch12 &&
300         check_patch patch12 &&
301         ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12
302 '
303
304 test_expect_success '--no-add-header overrides config.headers' '
305
306         git config --replace-all format.headers \
307                 "Header1: B E Cipient <rcipient@example.com>" &&
308         git format-patch --no-add-header --stdout master..side |
309         sed -e "/^\$/q" >patch13 &&
310         check_patch patch13 &&
311         ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13
312 '
313
314 test_expect_success 'multiple files' '
315
316         rm -rf patches/ &&
317         git checkout side &&
318         git format-patch -o patches/ master &&
319         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
320 '
321
322 test_expect_success 'reroll count' '
323         rm -fr patches &&
324         git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
325         ! grep -v "^patches/v4-000[0-3]-" list &&
326         sed -n -e "/^Subject: /p" $(cat list) >subjects &&
327         ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
328 '
329
330 test_expect_success 'reroll count (-v)' '
331         rm -fr patches &&
332         git format-patch -o patches --cover-letter -v4 master..side >list &&
333         ! grep -v "^patches/v4-000[0-3]-" list &&
334         sed -n -e "/^Subject: /p" $(cat list) >subjects &&
335         ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
336 '
337
338 check_threading () {
339         expect="$1" &&
340         shift &&
341         (git format-patch --stdout "$@"; echo $? > status.out) |
342         # Prints everything between the Message-ID and In-Reply-To,
343         # and replaces all Message-ID-lookalikes by a sequence number
344         perl -ne '
345                 if (/^(message-id|references|in-reply-to)/i) {
346                         $printing = 1;
347                 } elsif (/^\S/) {
348                         $printing = 0;
349                 }
350                 if ($printing) {
351                         $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
352                         for $k (keys %h) {s/$k/$h{$k}/};
353                         print;
354                 }
355                 print "---\n" if /^From /i;
356         ' > actual &&
357         test 0 = "$(cat status.out)" &&
358         test_cmp "$expect" actual
359 }
360
361 cat >> expect.no-threading <<EOF
362 ---
363 ---
364 ---
365 EOF
366
367 test_expect_success 'no threading' '
368         git checkout side &&
369         check_threading expect.no-threading master
370 '
371
372 cat > expect.thread <<EOF
373 ---
374 Message-Id: <0>
375 ---
376 Message-Id: <1>
377 In-Reply-To: <0>
378 References: <0>
379 ---
380 Message-Id: <2>
381 In-Reply-To: <0>
382 References: <0>
383 EOF
384
385 test_expect_success 'thread' '
386         check_threading expect.thread --thread master
387 '
388
389 cat > expect.in-reply-to <<EOF
390 ---
391 Message-Id: <0>
392 In-Reply-To: <1>
393 References: <1>
394 ---
395 Message-Id: <2>
396 In-Reply-To: <1>
397 References: <1>
398 ---
399 Message-Id: <3>
400 In-Reply-To: <1>
401 References: <1>
402 EOF
403
404 test_expect_success 'thread in-reply-to' '
405         check_threading expect.in-reply-to --in-reply-to="<test.message>" \
406                 --thread master
407 '
408
409 cat > expect.cover-letter <<EOF
410 ---
411 Message-Id: <0>
412 ---
413 Message-Id: <1>
414 In-Reply-To: <0>
415 References: <0>
416 ---
417 Message-Id: <2>
418 In-Reply-To: <0>
419 References: <0>
420 ---
421 Message-Id: <3>
422 In-Reply-To: <0>
423 References: <0>
424 EOF
425
426 test_expect_success 'thread cover-letter' '
427         check_threading expect.cover-letter --cover-letter --thread master
428 '
429
430 cat > expect.cl-irt <<EOF
431 ---
432 Message-Id: <0>
433 In-Reply-To: <1>
434 References: <1>
435 ---
436 Message-Id: <2>
437 In-Reply-To: <0>
438 References: <1>
439         <0>
440 ---
441 Message-Id: <3>
442 In-Reply-To: <0>
443 References: <1>
444         <0>
445 ---
446 Message-Id: <4>
447 In-Reply-To: <0>
448 References: <1>
449         <0>
450 EOF
451
452 test_expect_success 'thread cover-letter in-reply-to' '
453         check_threading expect.cl-irt --cover-letter \
454                 --in-reply-to="<test.message>" --thread master
455 '
456
457 test_expect_success 'thread explicit shallow' '
458         check_threading expect.cl-irt --cover-letter \
459                 --in-reply-to="<test.message>" --thread=shallow master
460 '
461
462 cat > expect.deep <<EOF
463 ---
464 Message-Id: <0>
465 ---
466 Message-Id: <1>
467 In-Reply-To: <0>
468 References: <0>
469 ---
470 Message-Id: <2>
471 In-Reply-To: <1>
472 References: <0>
473         <1>
474 EOF
475
476 test_expect_success 'thread deep' '
477         check_threading expect.deep --thread=deep master
478 '
479
480 cat > expect.deep-irt <<EOF
481 ---
482 Message-Id: <0>
483 In-Reply-To: <1>
484 References: <1>
485 ---
486 Message-Id: <2>
487 In-Reply-To: <0>
488 References: <1>
489         <0>
490 ---
491 Message-Id: <3>
492 In-Reply-To: <2>
493 References: <1>
494         <0>
495         <2>
496 EOF
497
498 test_expect_success 'thread deep in-reply-to' '
499         check_threading expect.deep-irt  --thread=deep \
500                 --in-reply-to="<test.message>" master
501 '
502
503 cat > expect.deep-cl <<EOF
504 ---
505 Message-Id: <0>
506 ---
507 Message-Id: <1>
508 In-Reply-To: <0>
509 References: <0>
510 ---
511 Message-Id: <2>
512 In-Reply-To: <1>
513 References: <0>
514         <1>
515 ---
516 Message-Id: <3>
517 In-Reply-To: <2>
518 References: <0>
519         <1>
520         <2>
521 EOF
522
523 test_expect_success 'thread deep cover-letter' '
524         check_threading expect.deep-cl --cover-letter --thread=deep master
525 '
526
527 cat > expect.deep-cl-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 ---
544 Message-Id: <4>
545 In-Reply-To: <3>
546 References: <1>
547         <0>
548         <2>
549         <3>
550 EOF
551
552 test_expect_success 'thread deep cover-letter in-reply-to' '
553         check_threading expect.deep-cl-irt --cover-letter \
554                 --in-reply-to="<test.message>" --thread=deep master
555 '
556
557 test_expect_success 'thread via config' '
558         test_config format.thread true &&
559         check_threading expect.thread master
560 '
561
562 test_expect_success 'thread deep via config' '
563         test_config format.thread deep &&
564         check_threading expect.deep master
565 '
566
567 test_expect_success 'thread config + override' '
568         test_config format.thread deep &&
569         check_threading expect.thread --thread master
570 '
571
572 test_expect_success 'thread config + --no-thread' '
573         test_config format.thread deep &&
574         check_threading expect.no-threading --no-thread master
575 '
576
577 test_expect_success 'excessive subject' '
578
579         rm -rf patches/ &&
580         git checkout side &&
581         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
582         git update-index file &&
583         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." &&
584         git format-patch -o patches/ master..side &&
585         ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
586 '
587
588 test_expect_success 'cover-letter inherits diff options' '
589
590         git mv file foo &&
591         git commit -m foo &&
592         git format-patch --no-renames --cover-letter -1 &&
593         check_patch 0000-cover-letter.patch &&
594         ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
595         git format-patch --cover-letter -1 -M &&
596         grep "file => foo .* 0 *\$" 0000-cover-letter.patch
597
598 '
599
600 cat > expect << EOF
601   This is an excessively long subject line for a message due to the
602     habit some projects have of not having a short, one-line subject at
603     the start of the commit message, but rather sticking a whole
604     paragraph right at the start as the only thing in the commit
605     message. It had better not become the filename for the patch.
606   foo
607
608 EOF
609
610 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
611
612         git format-patch --cover-letter -2 &&
613         sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
614         test_cmp expect output
615
616 '
617
618 cat > expect << EOF
619 index 40f36c6..2dc5c23 100644
620 --- a/file
621 +++ b/file
622 @@ -13,4 +13,20 @@ C
623  10
624  D
625  E
626  F
627 +5
628 EOF
629
630 test_expect_success 'format-patch respects -U' '
631
632         git format-patch -U4 -2 &&
633         sed -e "1,/^diff/d" -e "/^+5/q" \
634                 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
635                 >output &&
636         test_cmp expect output
637
638 '
639
640 cat > expect << EOF
641
642 diff --git a/file b/file
643 index 40f36c6..2dc5c23 100644
644 --- a/file
645 +++ b/file
646 @@ -14,3 +14,19 @@ C
647  D
648  E
649  F
650 +5
651 EOF
652
653 test_expect_success 'format-patch -p suppresses stat' '
654
655         git format-patch -p -2 &&
656         sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
657         test_cmp expect output
658
659 '
660
661 test_expect_success 'format-patch from a subdirectory (1)' '
662         filename=$(
663                 rm -rf sub &&
664                 mkdir -p sub/dir &&
665                 cd sub/dir &&
666                 git format-patch -1
667         ) &&
668         case "$filename" in
669         0*)
670                 ;; # ok
671         *)
672                 echo "Oops? $filename"
673                 false
674                 ;;
675         esac &&
676         test -f "$filename"
677 '
678
679 test_expect_success 'format-patch from a subdirectory (2)' '
680         filename=$(
681                 rm -rf sub &&
682                 mkdir -p sub/dir &&
683                 cd sub/dir &&
684                 git format-patch -1 -o ..
685         ) &&
686         case "$filename" in
687         ../0*)
688                 ;; # ok
689         *)
690                 echo "Oops? $filename"
691                 false
692                 ;;
693         esac &&
694         basename=$(expr "$filename" : ".*/\(.*\)") &&
695         test -f "sub/$basename"
696 '
697
698 test_expect_success 'format-patch from a subdirectory (3)' '
699         rm -f 0* &&
700         filename=$(
701                 rm -rf sub &&
702                 mkdir -p sub/dir &&
703                 cd sub/dir &&
704                 git format-patch -1 -o "$TRASH_DIRECTORY"
705         ) &&
706         basename=$(expr "$filename" : ".*/\(.*\)") &&
707         test -f "$basename"
708 '
709
710 test_expect_success 'format-patch --in-reply-to' '
711         git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
712         grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
713         grep "^References: <baz@foo.bar>" patch8
714 '
715
716 test_expect_success 'format-patch --signoff' '
717         git format-patch -1 --signoff --stdout >out &&
718         grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
719 '
720
721 test_expect_success 'format-patch --notes --signoff' '
722         git notes --ref test add -m "test message" HEAD &&
723         git format-patch -1 --signoff --stdout --notes=test >out &&
724         # Three dashes must come after S-o-b
725         ! sed "/^Signed-off-by: /q" out | grep "test message" &&
726         sed "1,/^Signed-off-by: /d" out | grep "test message" &&
727         # Notes message must come after three dashes
728         ! sed "/^---$/q" out | grep "test message" &&
729         sed "1,/^---$/d" out | grep "test message"
730 '
731
732 echo "fatal: --name-only does not make sense" > expect.name-only
733 echo "fatal: --name-status does not make sense" > expect.name-status
734 echo "fatal: --check does not make sense" > expect.check
735
736 test_expect_success 'options no longer allowed for format-patch' '
737         test_must_fail git format-patch --name-only 2> output &&
738         test_i18ncmp expect.name-only output &&
739         test_must_fail git format-patch --name-status 2> output &&
740         test_i18ncmp expect.name-status output &&
741         test_must_fail git format-patch --check 2> output &&
742         test_i18ncmp expect.check output'
743
744 test_expect_success 'format-patch --numstat should produce a patch' '
745         git format-patch --numstat --stdout master..side > output &&
746         test 5 = $(grep "^diff --git a/" output | wc -l)'
747
748 test_expect_success 'format-patch -- <path>' '
749         git format-patch master..side -- file 2>error &&
750         ! grep "Use .--" error
751 '
752
753 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
754         git format-patch --ignore-if-in-upstream HEAD
755 '
756
757 test_expect_success 'format-patch --signature' '
758         git format-patch --stdout --signature="my sig" -1 >output &&
759         grep "my sig" output
760 '
761
762 test_expect_success 'format-patch with format.signature config' '
763         git config format.signature "config sig" &&
764         git format-patch --stdout -1 >output &&
765         grep "config sig" output
766 '
767
768 test_expect_success 'format-patch --signature overrides format.signature' '
769         git config format.signature "config sig" &&
770         git format-patch --stdout --signature="overrides" -1 >output &&
771         ! grep "config sig" output &&
772         grep "overrides" output
773 '
774
775 test_expect_success 'format-patch --no-signature ignores format.signature' '
776         git config format.signature "config sig" &&
777         git format-patch --stdout --signature="my sig" --no-signature \
778                 -1 >output &&
779         check_patch output &&
780         ! grep "config sig" output &&
781         ! grep "my sig" output &&
782         ! grep "^-- \$" output
783 '
784
785 test_expect_success 'format-patch --signature --cover-letter' '
786         git config --unset-all format.signature &&
787         git format-patch --stdout --signature="my sig" --cover-letter \
788                 -1 >output &&
789         grep "my sig" output &&
790         test 2 = $(grep "my sig" output | wc -l)
791 '
792
793 test_expect_success 'format.signature="" suppresses signatures' '
794         git config format.signature "" &&
795         git format-patch --stdout -1 >output &&
796         check_patch output &&
797         ! grep "^-- \$" output
798 '
799
800 test_expect_success 'format-patch --no-signature suppresses signatures' '
801         git config --unset-all format.signature &&
802         git format-patch --stdout --no-signature -1 >output &&
803         check_patch output &&
804         ! grep "^-- \$" output
805 '
806
807 test_expect_success 'format-patch --signature="" suppresses signatures' '
808         git format-patch --stdout --signature="" -1 >output &&
809         check_patch output &&
810         ! grep "^-- \$" output
811 '
812
813 test_expect_success 'prepare mail-signature input' '
814         cat >mail-signature <<-\EOF
815
816         Test User <test.email@kernel.org>
817         http://git.kernel.org/cgit/git/git.git
818
819         git.kernel.org/?p=git/git.git;a=summary
820
821         EOF
822 '
823
824 test_expect_success '--signature-file=file works' '
825         git format-patch --stdout --signature-file=mail-signature -1 >output &&
826         check_patch output &&
827         sed -e "1,/^-- \$/d" <output >actual &&
828         {
829                 cat mail-signature && echo
830         } >expect &&
831         test_cmp expect actual
832 '
833
834 test_expect_success 'format.signaturefile works' '
835         test_config format.signaturefile mail-signature &&
836         git format-patch --stdout -1 >output &&
837         check_patch output &&
838         sed -e "1,/^-- \$/d" <output >actual &&
839         {
840                 cat mail-signature && echo
841         } >expect &&
842         test_cmp expect actual
843 '
844
845 test_expect_success '--no-signature suppresses format.signaturefile ' '
846         test_config format.signaturefile mail-signature &&
847         git format-patch --stdout --no-signature -1 >output &&
848         check_patch output &&
849         ! grep "^-- \$" output
850 '
851
852 test_expect_success '--signature-file overrides format.signaturefile' '
853         cat >other-mail-signature <<-\EOF &&
854         Use this other signature instead of mail-signature.
855         EOF
856         test_config format.signaturefile mail-signature &&
857         git format-patch --stdout \
858                         --signature-file=other-mail-signature -1 >output &&
859         check_patch output &&
860         sed -e "1,/^-- \$/d" <output >actual &&
861         {
862                 cat other-mail-signature && echo
863         } >expect &&
864         test_cmp expect actual
865 '
866
867 test_expect_success '--signature overrides format.signaturefile' '
868         test_config format.signaturefile mail-signature &&
869         git format-patch --stdout --signature="my sig" -1 >output &&
870         check_patch output &&
871         grep "my sig" output
872 '
873
874 test_expect_success TTY 'format-patch --stdout paginates' '
875         rm -f pager_used &&
876         test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
877         test_path_is_file pager_used
878 '
879
880  test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
881         rm -f pager_used &&
882         test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
883         test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
884         test_path_is_missing pager_used &&
885         test_path_is_missing .git/pager_used
886 '
887
888 test_expect_success 'format-patch handles multi-line subjects' '
889         rm -rf patches/ &&
890         echo content >>file &&
891         for i in one two three; do echo $i; done >msg &&
892         git add file &&
893         git commit -F msg &&
894         git format-patch -o patches -1 &&
895         grep ^Subject: patches/0001-one.patch >actual &&
896         echo "Subject: [PATCH] one two three" >expect &&
897         test_cmp expect actual
898 '
899
900 test_expect_success 'format-patch handles multi-line encoded subjects' '
901         rm -rf patches/ &&
902         echo content >>file &&
903         for i in en två tre; do echo $i; done >msg &&
904         git add file &&
905         git commit -F msg &&
906         git format-patch -o patches -1 &&
907         grep ^Subject: patches/0001-en.patch >actual &&
908         echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
909         test_cmp expect actual
910 '
911
912 M8="foo bar "
913 M64=$M8$M8$M8$M8$M8$M8$M8$M8
914 M512=$M64$M64$M64$M64$M64$M64$M64$M64
915 cat >expect <<'EOF'
916 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
917  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
918  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
919  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
920  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
921  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
922  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
923 EOF
924 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
925         echo content >>file &&
926         git add file &&
927         git commit -m "$M512" &&
928         git format-patch --stdout -1 >patch &&
929         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
930         test_cmp expect subject
931 '
932
933 M8="föö bar "
934 M64=$M8$M8$M8$M8$M8$M8$M8$M8
935 M512=$M64$M64$M64$M64$M64$M64$M64$M64
936 cat >expect <<'EOF'
937 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
938  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
939  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
940  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
941  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
942  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
943  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
944  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
945  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
946  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
947  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
948  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
949  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
950  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
951  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
952  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
953  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
954  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
955  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
956  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
957  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
958  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
959  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
960  =?UTF-8?q?bar?=
961 EOF
962 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
963         rm -rf patches/ &&
964         echo content >>file &&
965         git add file &&
966         git commit -m "$M512" &&
967         git format-patch --stdout -1 >patch &&
968         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
969         test_cmp expect subject
970 '
971
972 check_author() {
973         echo content >>file &&
974         git add file &&
975         GIT_AUTHOR_NAME=$1 git commit -m author-check &&
976         git format-patch --stdout -1 >patch &&
977         sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
978         test_cmp expect actual
979 }
980
981 cat >expect <<'EOF'
982 From: "Foo B. Bar" <author@example.com>
983 EOF
984 test_expect_success 'format-patch quotes dot in from-headers' '
985         check_author "Foo B. Bar"
986 '
987
988 cat >expect <<'EOF'
989 From: "Foo \"The Baz\" Bar" <author@example.com>
990 EOF
991 test_expect_success 'format-patch quotes double-quote in from-headers' '
992         check_author "Foo \"The Baz\" Bar"
993 '
994
995 cat >expect <<'EOF'
996 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
997 EOF
998 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
999         check_author "Föo Bar"
1000 '
1001
1002 cat >expect <<'EOF'
1003 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1004 EOF
1005 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1006         check_author "Föo B. Bar"
1007 '
1008
1009 cat >expect <<EOF
1010 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1011  <author@example.com>
1012 EOF
1013 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1014         check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1015 '
1016
1017 cat >expect <<'EOF'
1018 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1019  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1020  Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1021 EOF
1022 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1023         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"
1024 '
1025
1026 cat >expect <<'EOF'
1027 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1028  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1029  Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1030 EOF
1031 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1032         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"
1033 '
1034
1035 cat >expect <<'EOF'
1036 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1037  =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1038  =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1039  =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1040  =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1041 EOF
1042 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1043         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"
1044 '
1045
1046 cat >expect <<'EOF'
1047 Subject: header with . in it
1048 EOF
1049 test_expect_success 'subject lines do not have 822 atom-quoting' '
1050         echo content >>file &&
1051         git add file &&
1052         git commit -m "header with . in it" &&
1053         git format-patch -k -1 --stdout >patch &&
1054         grep ^Subject: patch >actual &&
1055         test_cmp expect actual
1056 '
1057
1058 cat >expect <<'EOF'
1059 Subject: [PREFIX 1/1] header with . in it
1060 EOF
1061 test_expect_success 'subject prefixes have space prepended' '
1062         git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1063         grep ^Subject: patch >actual &&
1064         test_cmp expect actual
1065 '
1066
1067 cat >expect <<'EOF'
1068 Subject: [1/1] header with . in it
1069 EOF
1070 test_expect_success 'empty subject prefix does not have extra space' '
1071         git format-patch -n -1 --stdout --subject-prefix= >patch &&
1072         grep ^Subject: patch >actual &&
1073         test_cmp expect actual
1074 '
1075
1076 test_expect_success '--from=ident notices bogus ident' '
1077         test_must_fail git format-patch -1 --stdout --from=foo >patch
1078 '
1079
1080 test_expect_success '--from=ident replaces author' '
1081         git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1082         cat >expect <<-\EOF &&
1083         From: Me <me@example.com>
1084
1085         From: A U Thor <author@example.com>
1086
1087         EOF
1088         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1089         test_cmp expect patch.head
1090 '
1091
1092 test_expect_success '--from uses committer ident' '
1093         git format-patch -1 --stdout --from >patch &&
1094         cat >expect <<-\EOF &&
1095         From: C O Mitter <committer@example.com>
1096
1097         From: A U Thor <author@example.com>
1098
1099         EOF
1100         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1101         test_cmp expect patch.head
1102 '
1103
1104 test_expect_success '--from omits redundant in-body header' '
1105         git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1106         cat >expect <<-\EOF &&
1107         From: A U Thor <author@example.com>
1108
1109         EOF
1110         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1111         test_cmp expect patch.head
1112 '
1113
1114 test_expect_success 'in-body headers trigger content encoding' '
1115         test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1116         test_when_finished "git reset --hard HEAD^" &&
1117         git format-patch -1 --stdout --from >patch &&
1118         cat >expect <<-\EOF &&
1119         From: C O Mitter <committer@example.com>
1120         Content-Type: text/plain; charset=UTF-8
1121
1122         From: éxötìc <author@example.com>
1123
1124         EOF
1125         sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1126         test_cmp expect patch.head
1127 '
1128
1129 append_signoff()
1130 {
1131         C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1132         git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1133         sed -n -e "1,/^---$/p" append_signoff.patch |
1134                 egrep -n "^Subject|Sign|^$"
1135 }
1136
1137 test_expect_success 'signoff: commit with no body' '
1138         append_signoff </dev/null >actual &&
1139         cat <<\EOF | sed "s/EOL$//" >expected &&
1140 4:Subject: [PATCH] EOL
1141 8:
1142 9:Signed-off-by: C O Mitter <committer@example.com>
1143 EOF
1144         test_cmp expected actual
1145 '
1146
1147 test_expect_success 'signoff: commit with only subject' '
1148         echo subject | append_signoff >actual &&
1149         cat >expected <<\EOF &&
1150 4:Subject: [PATCH] subject
1151 8:
1152 9:Signed-off-by: C O Mitter <committer@example.com>
1153 EOF
1154         test_cmp expected actual
1155 '
1156
1157 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1158         printf subject | append_signoff >actual &&
1159         cat >expected <<\EOF &&
1160 4:Subject: [PATCH] subject
1161 8:
1162 9:Signed-off-by: C O Mitter <committer@example.com>
1163 EOF
1164         test_cmp expected actual
1165 '
1166
1167 test_expect_success 'signoff: no existing signoffs' '
1168         append_signoff <<\EOF >actual &&
1169 subject
1170
1171 body
1172 EOF
1173         cat >expected <<\EOF &&
1174 4:Subject: [PATCH] subject
1175 8:
1176 10:
1177 11:Signed-off-by: C O Mitter <committer@example.com>
1178 EOF
1179         test_cmp expected actual
1180 '
1181
1182 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1183         printf "subject\n\nbody" | append_signoff >actual &&
1184         cat >expected <<\EOF &&
1185 4:Subject: [PATCH] subject
1186 8:
1187 10:
1188 11:Signed-off-by: C O Mitter <committer@example.com>
1189 EOF
1190         test_cmp expected actual
1191 '
1192
1193 test_expect_success 'signoff: some random signoff' '
1194         append_signoff <<\EOF >actual &&
1195 subject
1196
1197 body
1198
1199 Signed-off-by: my@house
1200 EOF
1201         cat >expected <<\EOF &&
1202 4:Subject: [PATCH] subject
1203 8:
1204 10:
1205 11:Signed-off-by: my@house
1206 12:Signed-off-by: C O Mitter <committer@example.com>
1207 EOF
1208         test_cmp expected actual
1209 '
1210
1211 test_expect_success 'signoff: misc conforming footer elements' '
1212         append_signoff <<\EOF >actual &&
1213 subject
1214
1215 body
1216
1217 Signed-off-by: my@house
1218 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1219 Tested-by: Some One <someone@example.com>
1220 Bug: 1234
1221 EOF
1222         cat >expected <<\EOF &&
1223 4:Subject: [PATCH] subject
1224 8:
1225 10:
1226 11:Signed-off-by: my@house
1227 15:Signed-off-by: C O Mitter <committer@example.com>
1228 EOF
1229         test_cmp expected actual
1230 '
1231
1232 test_expect_success 'signoff: some random signoff-alike' '
1233         append_signoff <<\EOF >actual &&
1234 subject
1235
1236 body
1237 Fooled-by-me: my@house
1238 EOF
1239         cat >expected <<\EOF &&
1240 4:Subject: [PATCH] subject
1241 8:
1242 11:
1243 12:Signed-off-by: C O Mitter <committer@example.com>
1244 EOF
1245         test_cmp expected actual
1246 '
1247
1248 test_expect_success 'signoff: not really a signoff' '
1249         append_signoff <<\EOF >actual &&
1250 subject
1251
1252 I want to mention about Signed-off-by: here.
1253 EOF
1254         cat >expected <<\EOF &&
1255 4:Subject: [PATCH] subject
1256 8:
1257 9:I want to mention about Signed-off-by: here.
1258 10:
1259 11:Signed-off-by: C O Mitter <committer@example.com>
1260 EOF
1261         test_cmp expected actual
1262 '
1263
1264 test_expect_success 'signoff: not really a signoff (2)' '
1265         append_signoff <<\EOF >actual &&
1266 subject
1267
1268 My unfortunate
1269 Signed-off-by: example happens to be wrapped here.
1270 EOF
1271         cat >expected <<\EOF &&
1272 4:Subject: [PATCH] subject
1273 8:
1274 10:Signed-off-by: example happens to be wrapped here.
1275 11:
1276 12:Signed-off-by: C O Mitter <committer@example.com>
1277 EOF
1278         test_cmp expected actual
1279 '
1280
1281 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1282         append_signoff <<\EOF >actual &&
1283 subject
1284
1285 Signed-off-by: my@house
1286 Signed-off-by: your@house
1287
1288 A lot of houses.
1289 EOF
1290         cat >expected <<\EOF &&
1291 4:Subject: [PATCH] subject
1292 8:
1293 9:Signed-off-by: my@house
1294 10:Signed-off-by: your@house
1295 11:
1296 13:
1297 14:Signed-off-by: C O Mitter <committer@example.com>
1298 EOF
1299         test_cmp expected actual
1300 '
1301
1302 test_expect_success 'signoff: the same signoff at the end' '
1303         append_signoff <<\EOF >actual &&
1304 subject
1305
1306 body
1307
1308 Signed-off-by: C O Mitter <committer@example.com>
1309 EOF
1310         cat >expected <<\EOF &&
1311 4:Subject: [PATCH] subject
1312 8:
1313 10:
1314 11:Signed-off-by: C O Mitter <committer@example.com>
1315 EOF
1316         test_cmp expected actual
1317 '
1318
1319 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1320         printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1321                 append_signoff >actual &&
1322         cat >expected <<\EOF &&
1323 4:Subject: [PATCH] subject
1324 8:
1325 9:Signed-off-by: C O Mitter <committer@example.com>
1326 EOF
1327         test_cmp expected actual
1328 '
1329
1330 test_expect_success 'signoff: the same signoff NOT at the end' '
1331         append_signoff <<\EOF >actual &&
1332 subject
1333
1334 body
1335
1336 Signed-off-by: C O Mitter <committer@example.com>
1337 Signed-off-by: my@house
1338 EOF
1339         cat >expected <<\EOF &&
1340 4:Subject: [PATCH] subject
1341 8:
1342 10:
1343 11:Signed-off-by: C O Mitter <committer@example.com>
1344 12:Signed-off-by: my@house
1345 EOF
1346         test_cmp expected actual
1347 '
1348
1349 test_expect_success 'signoff: detect garbage in non-conforming footer' '
1350         append_signoff <<\EOF >actual &&
1351 subject
1352
1353 body
1354
1355 Tested-by: my@house
1356 Some Trash
1357 Signed-off-by: C O Mitter <committer@example.com>
1358 EOF
1359         cat >expected <<\EOF &&
1360 4:Subject: [PATCH] subject
1361 8:
1362 10:
1363 13:Signed-off-by: C O Mitter <committer@example.com>
1364 14:
1365 15:Signed-off-by: C O Mitter <committer@example.com>
1366 EOF
1367         test_cmp expected actual
1368 '
1369
1370 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1371         append_signoff <<\EOF >actual &&
1372 subject
1373
1374 body
1375
1376 Reviewed-id: Noone
1377 Tested-by: my@house
1378 Change-id: Ideadbeef
1379 Signed-off-by: C O Mitter <committer@example.com>
1380 Bug: 1234
1381 EOF
1382         cat >expected <<\EOF &&
1383 4:Subject: [PATCH] subject
1384 8:
1385 10:
1386 14:Signed-off-by: C O Mitter <committer@example.com>
1387 EOF
1388         test_cmp expected actual
1389 '
1390
1391 test_expect_success 'format patch ignores color.ui' '
1392         test_unconfig color.ui &&
1393         git format-patch --stdout -1 >expect &&
1394         test_config color.ui always &&
1395         git format-patch --stdout -1 >actual &&
1396         test_cmp expect actual
1397 '
1398
1399 test_expect_success 'cover letter using branch description (1)' '
1400         git checkout rebuild-1 &&
1401         test_config branch.rebuild-1.description hello &&
1402         git format-patch --stdout --cover-letter master >actual &&
1403         grep hello actual >/dev/null
1404 '
1405
1406 test_expect_success 'cover letter using branch description (2)' '
1407         git checkout rebuild-1 &&
1408         test_config branch.rebuild-1.description hello &&
1409         git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1410         grep hello actual >/dev/null
1411 '
1412
1413 test_expect_success 'cover letter using branch description (3)' '
1414         git checkout rebuild-1 &&
1415         test_config branch.rebuild-1.description hello &&
1416         git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1417         grep hello actual >/dev/null
1418 '
1419
1420 test_expect_success 'cover letter using branch description (4)' '
1421         git checkout rebuild-1 &&
1422         test_config branch.rebuild-1.description hello &&
1423         git format-patch --stdout --cover-letter master.. >actual &&
1424         grep hello actual >/dev/null
1425 '
1426
1427 test_expect_success 'cover letter using branch description (5)' '
1428         git checkout rebuild-1 &&
1429         test_config branch.rebuild-1.description hello &&
1430         git format-patch --stdout --cover-letter -2 HEAD >actual &&
1431         grep hello actual >/dev/null
1432 '
1433
1434 test_expect_success 'cover letter using branch description (6)' '
1435         git checkout rebuild-1 &&
1436         test_config branch.rebuild-1.description hello &&
1437         git format-patch --stdout --cover-letter -2 >actual &&
1438         grep hello actual >/dev/null
1439 '
1440
1441 test_expect_success 'cover letter with nothing' '
1442         git format-patch --stdout --cover-letter >actual &&
1443         test_line_count = 0 actual
1444 '
1445
1446 test_expect_success 'cover letter auto' '
1447         mkdir -p tmp &&
1448         test_when_finished "rm -rf tmp;
1449                 git config --unset format.coverletter" &&
1450
1451         git config format.coverletter auto &&
1452         git format-patch -o tmp -1 >list &&
1453         test_line_count = 1 list &&
1454         git format-patch -o tmp -2 >list &&
1455         test_line_count = 3 list
1456 '
1457
1458 test_expect_success 'cover letter auto user override' '
1459         mkdir -p tmp &&
1460         test_when_finished "rm -rf tmp;
1461                 git config --unset format.coverletter" &&
1462
1463         git config format.coverletter auto &&
1464         git format-patch -o tmp --cover-letter -1 >list &&
1465         test_line_count = 2 list &&
1466         git format-patch -o tmp --cover-letter -2 >list &&
1467         test_line_count = 3 list &&
1468         git format-patch -o tmp --no-cover-letter -1 >list &&
1469         test_line_count = 1 list &&
1470         git format-patch -o tmp --no-cover-letter -2 >list &&
1471         test_line_count = 2 list
1472 '
1473
1474 test_expect_success 'format-patch --zero-commit' '
1475         git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1476         grep "^From " patch2 | sort | uniq >actual &&
1477         echo "From $_z40 Mon Sep 17 00:00:00 2001" >expect &&
1478         test_cmp expect actual
1479 '
1480
1481 test_expect_success 'From line has expected format' '
1482         git format-patch --stdout v2..v1 >patch2 &&
1483         grep "^From " patch2 >from &&
1484         grep "^From $_x40 Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1485         test_cmp from filtered
1486 '
1487
1488 test_expect_success 'format-patch format.outputDirectory option' '
1489         test_config format.outputDirectory patches &&
1490         rm -fr patches &&
1491         git format-patch master..side &&
1492         test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1493 '
1494
1495 test_expect_success 'format-patch -o overrides format.outputDirectory' '
1496         test_config format.outputDirectory patches &&
1497         rm -fr patches patchset &&
1498         git format-patch master..side -o patchset &&
1499         test_path_is_missing patches &&
1500         test_path_is_dir patchset
1501 '
1502
1503 test_expect_success 'format-patch --base' '
1504         git checkout side &&
1505         git format-patch --stdout --base=HEAD~3 -1 >patch &&
1506         grep "^base-commit:" patch >actual &&
1507         grep "^prerequisite-patch-id:" patch >>actual &&
1508         echo "base-commit: $(git rev-parse HEAD~3)" >expected &&
1509         echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1510         echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1511         test_cmp expected actual
1512 '
1513
1514 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1515         test_must_fail git format-patch --base=HEAD -2 &&
1516         test_must_fail git format-patch --base=HEAD~1 -2 &&
1517         git format-patch --stdout --base=HEAD~2 -2 >patch &&
1518         grep "^base-commit:" patch >actual &&
1519         echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1520         test_cmp expected actual
1521 '
1522
1523 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1524         # For history as below:
1525         #
1526         #    ---Q---P---Z---Y---*---X
1527         #        \             /
1528         #         ------------W
1529         #
1530         # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1531         git checkout -b topic1 master &&
1532         git rev-parse HEAD >commit-id-base &&
1533         test_commit P &&
1534         git rev-parse HEAD >commit-id-P &&
1535         test_commit Z &&
1536         git rev-parse HEAD >commit-id-Z &&
1537         test_commit Y &&
1538         git checkout -b topic2 master &&
1539         test_commit W &&
1540         git merge topic1 &&
1541         test_commit X &&
1542         test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1543         test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1544         git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1545         grep "^base-commit:" patch >actual &&
1546         echo "base-commit: $(cat commit-id-base)" >expected &&
1547         test_cmp expected actual
1548 '
1549
1550 test_expect_success 'format-patch --base=auto' '
1551         git checkout -b upstream master &&
1552         git checkout -b local upstream &&
1553         git branch --set-upstream-to=upstream &&
1554         test_commit N1 &&
1555         test_commit N2 &&
1556         git format-patch --stdout --base=auto -2 >patch &&
1557         grep "^base-commit:" patch >actual &&
1558         echo "base-commit: $(git rev-parse upstream)" >expected &&
1559         test_cmp expected actual
1560 '
1561
1562 test_expect_success 'format-patch errors out when history involves criss-cross' '
1563         # setup criss-cross history
1564         #
1565         #   B---M1---D
1566         #  / \ /
1567         # A   X
1568         #  \ / \
1569         #   C---M2---E
1570         #
1571         git checkout master &&
1572         test_commit A &&
1573         git checkout -b xb master &&
1574         test_commit B &&
1575         git checkout -b xc master &&
1576         test_commit C &&
1577         git checkout -b xbc xb -- &&
1578         git merge xc &&
1579         git checkout -b xcb xc -- &&
1580         git branch --set-upstream-to=xbc &&
1581         git merge xb &&
1582         git checkout xbc &&
1583         test_commit D &&
1584         git checkout xcb &&
1585         test_commit E &&
1586         test_must_fail  git format-patch --base=auto -1
1587 '
1588
1589 test_expect_success 'format-patch format.useAutoBaseoption' '
1590         test_when_finished "git config --unset format.useAutoBase" &&
1591         git checkout local &&
1592         git config format.useAutoBase true &&
1593         git format-patch --stdout -1 >patch &&
1594         grep "^base-commit:" patch >actual &&
1595         echo "base-commit: $(git rev-parse upstream)" >expected &&
1596         test_cmp expected actual
1597 '
1598
1599 test_expect_success 'format-patch --base overrides format.useAutoBase' '
1600         test_when_finished "git config --unset format.useAutoBase" &&
1601         git config format.useAutoBase true &&
1602         git format-patch --stdout --base=HEAD~1 -1 >patch &&
1603         grep "^base-commit:" patch >actual &&
1604         echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1605         test_cmp expected actual
1606 '
1607
1608 test_expect_success 'format-patch --pretty=mboxrd' '
1609         sp=" " &&
1610         cat >msg <<-INPUT_END &&
1611         mboxrd should escape the body
1612
1613         From could trip up a loose mbox parser
1614         >From extra escape for reversibility
1615         >>From extra escape for reversibility 2
1616         from lower case not escaped
1617         Fromm bad speling not escaped
1618          From with leading space not escaped
1619
1620         F
1621         From
1622         From$sp
1623         From    $sp
1624         From    $sp
1625         INPUT_END
1626
1627         cat >expect <<-INPUT_END &&
1628         >From could trip up a loose mbox parser
1629         >>From extra escape for reversibility
1630         >>>From extra escape for reversibility 2
1631         from lower case not escaped
1632         Fromm bad speling not escaped
1633          From with leading space not escaped
1634
1635         F
1636         From
1637         From
1638         From
1639         From
1640         INPUT_END
1641
1642         C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
1643         git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
1644         git grep -h --no-index -A11 \
1645                 "^>From could trip up a loose mbox parser" patch >actual &&
1646         test_cmp expect actual
1647 '
1648
1649 test_done