t3427: accelerate this test by using fast-export and fast-import
[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         before=$(git hash-object file) &&
582         before=$(git rev-parse --short $before) &&
583         for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
584         after=$(git hash-object file) &&
585         after=$(git rev-parse --short $after) &&
586         git update-index file &&
587         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." &&
588         git format-patch -o patches/ master..side &&
589         ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
590 '
591
592 test_expect_success 'failure to write cover-letter aborts gracefully' '
593         test_when_finished "rmdir 0000-cover-letter.patch" &&
594         mkdir 0000-cover-letter.patch &&
595         test_must_fail git format-patch --no-renames --cover-letter -1
596 '
597
598 test_expect_success 'cover-letter inherits diff options' '
599         git mv file foo &&
600         git commit -m foo &&
601         git format-patch --no-renames --cover-letter -1 &&
602         check_patch 0000-cover-letter.patch &&
603         ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
604         git format-patch --cover-letter -1 -M &&
605         grep "file => foo .* 0 *\$" 0000-cover-letter.patch
606
607 '
608
609 cat > expect << EOF
610   This is an excessively long subject line for a message due to the
611     habit some projects have of not having a short, one-line subject at
612     the start of the commit message, but rather sticking a whole
613     paragraph right at the start as the only thing in the commit
614     message. It had better not become the filename for the patch.
615   foo
616
617 EOF
618
619 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
620
621         git format-patch --cover-letter -2 &&
622         sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
623         test_cmp expect output
624
625 '
626
627 cat > expect << EOF
628 index $before..$after 100644
629 --- a/file
630 +++ b/file
631 @@ -13,4 +13,20 @@ C
632  10
633  D
634  E
635  F
636 +5
637 EOF
638
639 test_expect_success 'format-patch respects -U' '
640
641         git format-patch -U4 -2 &&
642         sed -e "1,/^diff/d" -e "/^+5/q" \
643                 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
644                 >output &&
645         test_cmp expect output
646
647 '
648
649 cat > expect << EOF
650
651 diff --git a/file b/file
652 index $before..$after 100644
653 --- a/file
654 +++ b/file
655 @@ -14,3 +14,19 @@ C
656  D
657  E
658  F
659 +5
660 EOF
661
662 test_expect_success 'format-patch -p suppresses stat' '
663
664         git format-patch -p -2 &&
665         sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
666         test_cmp expect output
667
668 '
669
670 test_expect_success 'format-patch from a subdirectory (1)' '
671         filename=$(
672                 rm -rf sub &&
673                 mkdir -p sub/dir &&
674                 cd sub/dir &&
675                 git format-patch -1
676         ) &&
677         case "$filename" in
678         0*)
679                 ;; # ok
680         *)
681                 echo "Oops? $filename"
682                 false
683                 ;;
684         esac &&
685         test -f "$filename"
686 '
687
688 test_expect_success 'format-patch from a subdirectory (2)' '
689         filename=$(
690                 rm -rf sub &&
691                 mkdir -p sub/dir &&
692                 cd sub/dir &&
693                 git format-patch -1 -o ..
694         ) &&
695         case "$filename" in
696         ../0*)
697                 ;; # ok
698         *)
699                 echo "Oops? $filename"
700                 false
701                 ;;
702         esac &&
703         basename=$(expr "$filename" : ".*/\(.*\)") &&
704         test -f "sub/$basename"
705 '
706
707 test_expect_success 'format-patch from a subdirectory (3)' '
708         rm -f 0* &&
709         filename=$(
710                 rm -rf sub &&
711                 mkdir -p sub/dir &&
712                 cd sub/dir &&
713                 git format-patch -1 -o "$TRASH_DIRECTORY"
714         ) &&
715         basename=$(expr "$filename" : ".*/\(.*\)") &&
716         test -f "$basename"
717 '
718
719 test_expect_success 'format-patch --in-reply-to' '
720         git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
721         grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
722         grep "^References: <baz@foo.bar>" patch8
723 '
724
725 test_expect_success 'format-patch --signoff' '
726         git format-patch -1 --signoff --stdout >out &&
727         grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
728 '
729
730 test_expect_success 'format-patch --notes --signoff' '
731         git notes --ref test add -m "test message" HEAD &&
732         git format-patch -1 --signoff --stdout --notes=test >out &&
733         # Three dashes must come after S-o-b
734         ! sed "/^Signed-off-by: /q" out | grep "test message" &&
735         sed "1,/^Signed-off-by: /d" out | grep "test message" &&
736         # Notes message must come after three dashes
737         ! sed "/^---$/q" out | grep "test message" &&
738         sed "1,/^---$/d" out | grep "test message"
739 '
740
741 echo "fatal: --name-only does not make sense" > expect.name-only
742 echo "fatal: --name-status does not make sense" > expect.name-status
743 echo "fatal: --check does not make sense" > expect.check
744
745 test_expect_success 'options no longer allowed for format-patch' '
746         test_must_fail git format-patch --name-only 2> output &&
747         test_i18ncmp expect.name-only output &&
748         test_must_fail git format-patch --name-status 2> output &&
749         test_i18ncmp expect.name-status output &&
750         test_must_fail git format-patch --check 2> output &&
751         test_i18ncmp expect.check output'
752
753 test_expect_success 'format-patch --numstat should produce a patch' '
754         git format-patch --numstat --stdout master..side > output &&
755         test 5 = $(grep "^diff --git a/" output | wc -l)'
756
757 test_expect_success 'format-patch -- <path>' '
758         git format-patch master..side -- file 2>error &&
759         ! grep "Use .--" error
760 '
761
762 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
763         git format-patch --ignore-if-in-upstream HEAD
764 '
765
766 git_version="$(git --version | sed "s/.* //")"
767
768 signature() {
769         printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
770 }
771
772 test_expect_success 'format-patch default signature' '
773         git format-patch --stdout -1 | tail -n 3 >output &&
774         signature >expect &&
775         test_cmp expect output
776 '
777
778 test_expect_success 'format-patch --signature' '
779         git format-patch --stdout --signature="my sig" -1 | tail -n 3 >output &&
780         signature "my sig" >expect &&
781         test_cmp expect output
782 '
783
784 test_expect_success 'format-patch with format.signature config' '
785         git config format.signature "config sig" &&
786         git format-patch --stdout -1 >output &&
787         grep "config sig" output
788 '
789
790 test_expect_success 'format-patch --signature overrides format.signature' '
791         git config format.signature "config sig" &&
792         git format-patch --stdout --signature="overrides" -1 >output &&
793         ! grep "config sig" output &&
794         grep "overrides" output
795 '
796
797 test_expect_success 'format-patch --no-signature ignores format.signature' '
798         git config format.signature "config sig" &&
799         git format-patch --stdout --signature="my sig" --no-signature \
800                 -1 >output &&
801         check_patch output &&
802         ! grep "config sig" output &&
803         ! grep "my sig" output &&
804         ! grep "^-- \$" output
805 '
806
807 test_expect_success 'format-patch --signature --cover-letter' '
808         git config --unset-all format.signature &&
809         git format-patch --stdout --signature="my sig" --cover-letter \
810                 -1 >output &&
811         grep "my sig" output &&
812         test 2 = $(grep "my sig" output | wc -l)
813 '
814
815 test_expect_success 'format.signature="" suppresses signatures' '
816         git config format.signature "" &&
817         git format-patch --stdout -1 >output &&
818         check_patch output &&
819         ! grep "^-- \$" output
820 '
821
822 test_expect_success 'format-patch --no-signature suppresses signatures' '
823         git config --unset-all format.signature &&
824         git format-patch --stdout --no-signature -1 >output &&
825         check_patch output &&
826         ! grep "^-- \$" output
827 '
828
829 test_expect_success 'format-patch --signature="" suppresses signatures' '
830         git format-patch --stdout --signature="" -1 >output &&
831         check_patch output &&
832         ! grep "^-- \$" output
833 '
834
835 test_expect_success 'prepare mail-signature input' '
836         cat >mail-signature <<-\EOF
837
838         Test User <test.email@kernel.org>
839         http://git.kernel.org/cgit/git/git.git
840
841         git.kernel.org/?p=git/git.git;a=summary
842
843         EOF
844 '
845
846 test_expect_success '--signature-file=file works' '
847         git format-patch --stdout --signature-file=mail-signature -1 >output &&
848         check_patch output &&
849         sed -e "1,/^-- \$/d" <output >actual &&
850         {
851                 cat mail-signature && echo
852         } >expect &&
853         test_cmp expect actual
854 '
855
856 test_expect_success 'format.signaturefile works' '
857         test_config format.signaturefile mail-signature &&
858         git format-patch --stdout -1 >output &&
859         check_patch output &&
860         sed -e "1,/^-- \$/d" <output >actual &&
861         {
862                 cat mail-signature && echo
863         } >expect &&
864         test_cmp expect actual
865 '
866
867 test_expect_success '--no-signature suppresses format.signaturefile ' '
868         test_config format.signaturefile mail-signature &&
869         git format-patch --stdout --no-signature -1 >output &&
870         check_patch output &&
871         ! grep "^-- \$" output
872 '
873
874 test_expect_success '--signature-file overrides format.signaturefile' '
875         cat >other-mail-signature <<-\EOF &&
876         Use this other signature instead of mail-signature.
877         EOF
878         test_config format.signaturefile mail-signature &&
879         git format-patch --stdout \
880                         --signature-file=other-mail-signature -1 >output &&
881         check_patch output &&
882         sed -e "1,/^-- \$/d" <output >actual &&
883         {
884                 cat other-mail-signature && echo
885         } >expect &&
886         test_cmp expect actual
887 '
888
889 test_expect_success '--signature overrides format.signaturefile' '
890         test_config format.signaturefile mail-signature &&
891         git format-patch --stdout --signature="my sig" -1 >output &&
892         check_patch output &&
893         grep "my sig" output
894 '
895
896 test_expect_success TTY 'format-patch --stdout paginates' '
897         rm -f pager_used &&
898         test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
899         test_path_is_file pager_used
900 '
901
902  test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
903         rm -f pager_used &&
904         test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
905         test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
906         test_path_is_missing pager_used &&
907         test_path_is_missing .git/pager_used
908 '
909
910 test_expect_success 'format-patch handles multi-line subjects' '
911         rm -rf patches/ &&
912         echo content >>file &&
913         for i in one two three; do echo $i; done >msg &&
914         git add file &&
915         git commit -F msg &&
916         git format-patch -o patches -1 &&
917         grep ^Subject: patches/0001-one.patch >actual &&
918         echo "Subject: [PATCH] one two three" >expect &&
919         test_cmp expect actual
920 '
921
922 test_expect_success 'format-patch handles multi-line encoded subjects' '
923         rm -rf patches/ &&
924         echo content >>file &&
925         for i in en två tre; do echo $i; done >msg &&
926         git add file &&
927         git commit -F msg &&
928         git format-patch -o patches -1 &&
929         grep ^Subject: patches/0001-en.patch >actual &&
930         echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
931         test_cmp expect actual
932 '
933
934 M8="foo bar "
935 M64=$M8$M8$M8$M8$M8$M8$M8$M8
936 M512=$M64$M64$M64$M64$M64$M64$M64$M64
937 cat >expect <<'EOF'
938 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
939  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
940  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
941  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
942  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
943  bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
944  foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
945 EOF
946 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
947         echo content >>file &&
948         git add file &&
949         git commit -m "$M512" &&
950         git format-patch --stdout -1 >patch &&
951         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
952         test_cmp expect subject
953 '
954
955 M8="föö bar "
956 M64=$M8$M8$M8$M8$M8$M8$M8$M8
957 M512=$M64$M64$M64$M64$M64$M64$M64$M64
958 cat >expect <<'EOF'
959 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
960  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
961  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
962  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
963  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
964  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
965  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
966  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
967  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
968  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
969  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
970  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
971  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
972  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
973  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
974  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
975  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
976  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
977  =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
978  =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
979  =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
980  =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
981  =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
982  =?UTF-8?q?bar?=
983 EOF
984 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
985         rm -rf patches/ &&
986         echo content >>file &&
987         git add file &&
988         git commit -m "$M512" &&
989         git format-patch --stdout -1 >patch &&
990         sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
991         test_cmp expect subject
992 '
993
994 check_author() {
995         echo content >>file &&
996         git add file &&
997         GIT_AUTHOR_NAME=$1 git commit -m author-check &&
998         git format-patch --stdout -1 >patch &&
999         sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
1000         test_cmp expect actual
1001 }
1002
1003 cat >expect <<'EOF'
1004 From: "Foo B. Bar" <author@example.com>
1005 EOF
1006 test_expect_success 'format-patch quotes dot in from-headers' '
1007         check_author "Foo B. Bar"
1008 '
1009
1010 cat >expect <<'EOF'
1011 From: "Foo \"The Baz\" Bar" <author@example.com>
1012 EOF
1013 test_expect_success 'format-patch quotes double-quote in from-headers' '
1014         check_author "Foo \"The Baz\" Bar"
1015 '
1016
1017 cat >expect <<'EOF'
1018 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
1019 EOF
1020 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1021         check_author "Föo Bar"
1022 '
1023
1024 cat >expect <<'EOF'
1025 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1026 EOF
1027 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
1028         check_author "Föo B. Bar"
1029 '
1030
1031 cat >expect <<EOF
1032 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1033  <author@example.com>
1034 EOF
1035 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1036         check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1037 '
1038
1039 cat >expect <<'EOF'
1040 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1041  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1042  Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1043 EOF
1044 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1045         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"
1046 '
1047
1048 cat >expect <<'EOF'
1049 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1050  Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1051  Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1052 EOF
1053 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1054         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"
1055 '
1056
1057 cat >expect <<'EOF'
1058 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1059  =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1060  =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1061  =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1062  =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1063 EOF
1064 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1065         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"
1066 '
1067
1068 cat >expect <<'EOF'
1069 Subject: header with . in it
1070 EOF
1071 test_expect_success 'subject lines do not have 822 atom-quoting' '
1072         echo content >>file &&
1073         git add file &&
1074         git commit -m "header with . in it" &&
1075         git format-patch -k -1 --stdout >patch &&
1076         grep ^Subject: patch >actual &&
1077         test_cmp expect actual
1078 '
1079
1080 cat >expect <<'EOF'
1081 Subject: [PREFIX 1/1] header with . in it
1082 EOF
1083 test_expect_success 'subject prefixes have space prepended' '
1084         git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1085         grep ^Subject: patch >actual &&
1086         test_cmp expect actual
1087 '
1088
1089 cat >expect <<'EOF'
1090 Subject: [1/1] header with . in it
1091 EOF
1092 test_expect_success 'empty subject prefix does not have extra space' '
1093         git format-patch -n -1 --stdout --subject-prefix= >patch &&
1094         grep ^Subject: patch >actual &&
1095         test_cmp expect actual
1096 '
1097
1098 test_expect_success '--rfc' '
1099         cat >expect <<-\EOF &&
1100         Subject: [RFC PATCH 1/1] header with . in it
1101         EOF
1102         git format-patch -n -1 --stdout --rfc >patch &&
1103         grep ^Subject: patch >actual &&
1104         test_cmp expect actual
1105 '
1106
1107 test_expect_success '--from=ident notices bogus ident' '
1108         test_must_fail git format-patch -1 --stdout --from=foo >patch
1109 '
1110
1111 test_expect_success '--from=ident replaces author' '
1112         git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1113         cat >expect <<-\EOF &&
1114         From: Me <me@example.com>
1115
1116         From: A U Thor <author@example.com>
1117
1118         EOF
1119         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1120         test_cmp expect patch.head
1121 '
1122
1123 test_expect_success '--from uses committer ident' '
1124         git format-patch -1 --stdout --from >patch &&
1125         cat >expect <<-\EOF &&
1126         From: C O Mitter <committer@example.com>
1127
1128         From: A U Thor <author@example.com>
1129
1130         EOF
1131         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1132         test_cmp expect patch.head
1133 '
1134
1135 test_expect_success '--from omits redundant in-body header' '
1136         git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1137         cat >expect <<-\EOF &&
1138         From: A U Thor <author@example.com>
1139
1140         EOF
1141         sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1142         test_cmp expect patch.head
1143 '
1144
1145 test_expect_success 'in-body headers trigger content encoding' '
1146         test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
1147         test_when_finished "git reset --hard HEAD^" &&
1148         git format-patch -1 --stdout --from >patch &&
1149         cat >expect <<-\EOF &&
1150         From: C O Mitter <committer@example.com>
1151         Content-Type: text/plain; charset=UTF-8
1152
1153         From: éxötìc <author@example.com>
1154
1155         EOF
1156         sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1157         test_cmp expect patch.head
1158 '
1159
1160 append_signoff()
1161 {
1162         C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1163         git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1164         sed -n -e "1,/^---$/p" append_signoff.patch |
1165                 egrep -n "^Subject|Sign|^$"
1166 }
1167
1168 test_expect_success 'signoff: commit with no body' '
1169         append_signoff </dev/null >actual &&
1170         cat <<\EOF | sed "s/EOL$//" >expected &&
1171 4:Subject: [PATCH] EOL
1172 8:
1173 9:Signed-off-by: C O Mitter <committer@example.com>
1174 EOF
1175         test_cmp expected actual
1176 '
1177
1178 test_expect_success 'signoff: commit with only subject' '
1179         echo subject | append_signoff >actual &&
1180         cat >expected <<\EOF &&
1181 4:Subject: [PATCH] subject
1182 8:
1183 9:Signed-off-by: C O Mitter <committer@example.com>
1184 EOF
1185         test_cmp expected actual
1186 '
1187
1188 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1189         printf subject | append_signoff >actual &&
1190         cat >expected <<\EOF &&
1191 4:Subject: [PATCH] subject
1192 8:
1193 9:Signed-off-by: C O Mitter <committer@example.com>
1194 EOF
1195         test_cmp expected actual
1196 '
1197
1198 test_expect_success 'signoff: no existing signoffs' '
1199         append_signoff <<\EOF >actual &&
1200 subject
1201
1202 body
1203 EOF
1204         cat >expected <<\EOF &&
1205 4:Subject: [PATCH] subject
1206 8:
1207 10:
1208 11:Signed-off-by: C O Mitter <committer@example.com>
1209 EOF
1210         test_cmp expected actual
1211 '
1212
1213 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1214         printf "subject\n\nbody" | append_signoff >actual &&
1215         cat >expected <<\EOF &&
1216 4:Subject: [PATCH] subject
1217 8:
1218 10:
1219 11:Signed-off-by: C O Mitter <committer@example.com>
1220 EOF
1221         test_cmp expected actual
1222 '
1223
1224 test_expect_success 'signoff: some random signoff' '
1225         append_signoff <<\EOF >actual &&
1226 subject
1227
1228 body
1229
1230 Signed-off-by: my@house
1231 EOF
1232         cat >expected <<\EOF &&
1233 4:Subject: [PATCH] subject
1234 8:
1235 10:
1236 11:Signed-off-by: my@house
1237 12:Signed-off-by: C O Mitter <committer@example.com>
1238 EOF
1239         test_cmp expected actual
1240 '
1241
1242 test_expect_success 'signoff: misc conforming footer elements' '
1243         append_signoff <<\EOF >actual &&
1244 subject
1245
1246 body
1247
1248 Signed-off-by: my@house
1249 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1250 Tested-by: Some One <someone@example.com>
1251 Bug: 1234
1252 EOF
1253         cat >expected <<\EOF &&
1254 4:Subject: [PATCH] subject
1255 8:
1256 10:
1257 11:Signed-off-by: my@house
1258 15:Signed-off-by: C O Mitter <committer@example.com>
1259 EOF
1260         test_cmp expected actual
1261 '
1262
1263 test_expect_success 'signoff: some random signoff-alike' '
1264         append_signoff <<\EOF >actual &&
1265 subject
1266
1267 body
1268 Fooled-by-me: my@house
1269 EOF
1270         cat >expected <<\EOF &&
1271 4:Subject: [PATCH] subject
1272 8:
1273 11:
1274 12:Signed-off-by: C O Mitter <committer@example.com>
1275 EOF
1276         test_cmp expected actual
1277 '
1278
1279 test_expect_success 'signoff: not really a signoff' '
1280         append_signoff <<\EOF >actual &&
1281 subject
1282
1283 I want to mention about Signed-off-by: here.
1284 EOF
1285         cat >expected <<\EOF &&
1286 4:Subject: [PATCH] subject
1287 8:
1288 9:I want to mention about Signed-off-by: here.
1289 10:
1290 11:Signed-off-by: C O Mitter <committer@example.com>
1291 EOF
1292         test_cmp expected actual
1293 '
1294
1295 test_expect_success 'signoff: not really a signoff (2)' '
1296         append_signoff <<\EOF >actual &&
1297 subject
1298
1299 My unfortunate
1300 Signed-off-by: example happens to be wrapped here.
1301 EOF
1302         cat >expected <<\EOF &&
1303 4:Subject: [PATCH] subject
1304 8:
1305 10:Signed-off-by: example happens to be wrapped here.
1306 11:Signed-off-by: C O Mitter <committer@example.com>
1307 EOF
1308         test_cmp expected actual
1309 '
1310
1311 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1312         append_signoff <<\EOF >actual &&
1313 subject
1314
1315 Signed-off-by: my@house
1316 Signed-off-by: your@house
1317
1318 A lot of houses.
1319 EOF
1320         cat >expected <<\EOF &&
1321 4:Subject: [PATCH] subject
1322 8:
1323 9:Signed-off-by: my@house
1324 10:Signed-off-by: your@house
1325 11:
1326 13:
1327 14:Signed-off-by: C O Mitter <committer@example.com>
1328 EOF
1329         test_cmp expected actual
1330 '
1331
1332 test_expect_success 'signoff: the same signoff at the end' '
1333         append_signoff <<\EOF >actual &&
1334 subject
1335
1336 body
1337
1338 Signed-off-by: C O Mitter <committer@example.com>
1339 EOF
1340         cat >expected <<\EOF &&
1341 4:Subject: [PATCH] subject
1342 8:
1343 10:
1344 11:Signed-off-by: C O Mitter <committer@example.com>
1345 EOF
1346         test_cmp expected actual
1347 '
1348
1349 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1350         printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1351                 append_signoff >actual &&
1352         cat >expected <<\EOF &&
1353 4:Subject: [PATCH] subject
1354 8:
1355 9:Signed-off-by: C O Mitter <committer@example.com>
1356 EOF
1357         test_cmp expected actual
1358 '
1359
1360 test_expect_success 'signoff: the same signoff NOT at the end' '
1361         append_signoff <<\EOF >actual &&
1362 subject
1363
1364 body
1365
1366 Signed-off-by: C O Mitter <committer@example.com>
1367 Signed-off-by: my@house
1368 EOF
1369         cat >expected <<\EOF &&
1370 4:Subject: [PATCH] subject
1371 8:
1372 10:
1373 11:Signed-off-by: C O Mitter <committer@example.com>
1374 12:Signed-off-by: my@house
1375 EOF
1376         test_cmp expected actual
1377 '
1378
1379 test_expect_success 'signoff: tolerate garbage in conforming footer' '
1380         append_signoff <<\EOF >actual &&
1381 subject
1382
1383 body
1384
1385 Tested-by: my@house
1386 Some Trash
1387 Signed-off-by: C O Mitter <committer@example.com>
1388 EOF
1389         cat >expected <<\EOF &&
1390 4:Subject: [PATCH] subject
1391 8:
1392 10:
1393 13:Signed-off-by: C O Mitter <committer@example.com>
1394 EOF
1395         test_cmp expected actual
1396 '
1397
1398 test_expect_success 'signoff: respect trailer config' '
1399         append_signoff <<\EOF >actual &&
1400 subject
1401
1402 Myfooter: x
1403 Some Trash
1404 EOF
1405         cat >expected <<\EOF &&
1406 4:Subject: [PATCH] subject
1407 8:
1408 11:
1409 12:Signed-off-by: C O Mitter <committer@example.com>
1410 EOF
1411         test_cmp expected actual &&
1412
1413         test_config trailer.Myfooter.ifexists add &&
1414         append_signoff <<\EOF >actual &&
1415 subject
1416
1417 Myfooter: x
1418 Some Trash
1419 EOF
1420         cat >expected <<\EOF &&
1421 4:Subject: [PATCH] subject
1422 8:
1423 11:Signed-off-by: C O Mitter <committer@example.com>
1424 EOF
1425         test_cmp expected actual
1426 '
1427
1428 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1429         append_signoff <<\EOF >actual &&
1430 subject
1431
1432 body
1433
1434 Reviewed-id: Noone
1435 Tested-by: my@house
1436 Change-id: Ideadbeef
1437 Signed-off-by: C O Mitter <committer@example.com>
1438 Bug: 1234
1439 EOF
1440         cat >expected <<\EOF &&
1441 4:Subject: [PATCH] subject
1442 8:
1443 10:
1444 14:Signed-off-by: C O Mitter <committer@example.com>
1445 EOF
1446         test_cmp expected actual
1447 '
1448
1449 test_expect_success 'format patch ignores color.ui' '
1450         test_unconfig color.ui &&
1451         git format-patch --stdout -1 >expect &&
1452         test_config color.ui always &&
1453         git format-patch --stdout -1 >actual &&
1454         test_cmp expect actual
1455 '
1456
1457 test_expect_success 'cover letter using branch description (1)' '
1458         git checkout rebuild-1 &&
1459         test_config branch.rebuild-1.description hello &&
1460         git format-patch --stdout --cover-letter master >actual &&
1461         grep hello actual >/dev/null
1462 '
1463
1464 test_expect_success 'cover letter using branch description (2)' '
1465         git checkout rebuild-1 &&
1466         test_config branch.rebuild-1.description hello &&
1467         git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1468         grep hello actual >/dev/null
1469 '
1470
1471 test_expect_success 'cover letter using branch description (3)' '
1472         git checkout rebuild-1 &&
1473         test_config branch.rebuild-1.description hello &&
1474         git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1475         grep hello actual >/dev/null
1476 '
1477
1478 test_expect_success 'cover letter using branch description (4)' '
1479         git checkout rebuild-1 &&
1480         test_config branch.rebuild-1.description hello &&
1481         git format-patch --stdout --cover-letter master.. >actual &&
1482         grep hello actual >/dev/null
1483 '
1484
1485 test_expect_success 'cover letter using branch description (5)' '
1486         git checkout rebuild-1 &&
1487         test_config branch.rebuild-1.description hello &&
1488         git format-patch --stdout --cover-letter -2 HEAD >actual &&
1489         grep hello actual >/dev/null
1490 '
1491
1492 test_expect_success 'cover letter using branch description (6)' '
1493         git checkout rebuild-1 &&
1494         test_config branch.rebuild-1.description hello &&
1495         git format-patch --stdout --cover-letter -2 >actual &&
1496         grep hello actual >/dev/null
1497 '
1498
1499 test_expect_success 'cover letter with nothing' '
1500         git format-patch --stdout --cover-letter >actual &&
1501         test_line_count = 0 actual
1502 '
1503
1504 test_expect_success 'cover letter auto' '
1505         mkdir -p tmp &&
1506         test_when_finished "rm -rf tmp;
1507                 git config --unset format.coverletter" &&
1508
1509         git config format.coverletter auto &&
1510         git format-patch -o tmp -1 >list &&
1511         test_line_count = 1 list &&
1512         git format-patch -o tmp -2 >list &&
1513         test_line_count = 3 list
1514 '
1515
1516 test_expect_success 'cover letter auto user override' '
1517         mkdir -p tmp &&
1518         test_when_finished "rm -rf tmp;
1519                 git config --unset format.coverletter" &&
1520
1521         git config format.coverletter auto &&
1522         git format-patch -o tmp --cover-letter -1 >list &&
1523         test_line_count = 2 list &&
1524         git format-patch -o tmp --cover-letter -2 >list &&
1525         test_line_count = 3 list &&
1526         git format-patch -o tmp --no-cover-letter -1 >list &&
1527         test_line_count = 1 list &&
1528         git format-patch -o tmp --no-cover-letter -2 >list &&
1529         test_line_count = 2 list
1530 '
1531
1532 test_expect_success 'format-patch --zero-commit' '
1533         git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1534         grep "^From " patch2 | sort | uniq >actual &&
1535         echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
1536         test_cmp expect actual
1537 '
1538
1539 test_expect_success 'From line has expected format' '
1540         git format-patch --stdout v2..v1 >patch2 &&
1541         grep "^From " patch2 >from &&
1542         grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
1543         test_cmp from filtered
1544 '
1545
1546 test_expect_success 'format-patch format.outputDirectory option' '
1547         test_config format.outputDirectory patches &&
1548         rm -fr patches &&
1549         git format-patch master..side &&
1550         test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1551 '
1552
1553 test_expect_success 'format-patch -o overrides format.outputDirectory' '
1554         test_config format.outputDirectory patches &&
1555         rm -fr patches patchset &&
1556         git format-patch master..side -o patchset &&
1557         test_path_is_missing patches &&
1558         test_path_is_dir patchset
1559 '
1560
1561 test_expect_success 'format-patch --base' '
1562         git checkout side &&
1563         git format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&
1564         git format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&
1565         echo >expected &&
1566         echo "base-commit: $(git rev-parse HEAD~3)" >>expected &&
1567         echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1568         echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected &&
1569         signature >> expected &&
1570         test_cmp expected actual1 &&
1571         test_cmp expected actual2
1572 '
1573
1574 test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1575         test_must_fail git format-patch --base=HEAD -2 &&
1576         test_must_fail git format-patch --base=HEAD~1 -2 &&
1577         git format-patch --stdout --base=HEAD~2 -2 >patch &&
1578         grep "^base-commit:" patch >actual &&
1579         echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1580         test_cmp expected actual
1581 '
1582
1583 test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1584         # For history as below:
1585         #
1586         #    ---Q---P---Z---Y---*---X
1587         #        \             /
1588         #         ------------W
1589         #
1590         # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1591         git checkout -b topic1 master &&
1592         git rev-parse HEAD >commit-id-base &&
1593         test_commit P &&
1594         git rev-parse HEAD >commit-id-P &&
1595         test_commit Z &&
1596         git rev-parse HEAD >commit-id-Z &&
1597         test_commit Y &&
1598         git checkout -b topic2 master &&
1599         test_commit W &&
1600         git merge topic1 &&
1601         test_commit X &&
1602         test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1603         test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1604         git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1605         grep "^base-commit:" patch >actual &&
1606         echo "base-commit: $(cat commit-id-base)" >expected &&
1607         test_cmp expected actual
1608 '
1609
1610 test_expect_success 'format-patch --base=auto' '
1611         git checkout -b upstream master &&
1612         git checkout -b local upstream &&
1613         git branch --set-upstream-to=upstream &&
1614         test_commit N1 &&
1615         test_commit N2 &&
1616         git format-patch --stdout --base=auto -2 >patch &&
1617         grep "^base-commit:" patch >actual &&
1618         echo "base-commit: $(git rev-parse upstream)" >expected &&
1619         test_cmp expected actual
1620 '
1621
1622 test_expect_success 'format-patch errors out when history involves criss-cross' '
1623         # setup criss-cross history
1624         #
1625         #   B---M1---D
1626         #  / \ /
1627         # A   X
1628         #  \ / \
1629         #   C---M2---E
1630         #
1631         git checkout master &&
1632         test_commit A &&
1633         git checkout -b xb master &&
1634         test_commit B &&
1635         git checkout -b xc master &&
1636         test_commit C &&
1637         git checkout -b xbc xb -- &&
1638         git merge xc &&
1639         git checkout -b xcb xc -- &&
1640         git branch --set-upstream-to=xbc &&
1641         git merge xb &&
1642         git checkout xbc &&
1643         test_commit D &&
1644         git checkout xcb &&
1645         test_commit E &&
1646         test_must_fail  git format-patch --base=auto -1
1647 '
1648
1649 test_expect_success 'format-patch format.useAutoBaseoption' '
1650         test_when_finished "git config --unset format.useAutoBase" &&
1651         git checkout local &&
1652         git config format.useAutoBase true &&
1653         git format-patch --stdout -1 >patch &&
1654         grep "^base-commit:" patch >actual &&
1655         echo "base-commit: $(git rev-parse upstream)" >expected &&
1656         test_cmp expected actual
1657 '
1658
1659 test_expect_success 'format-patch --base overrides format.useAutoBase' '
1660         test_when_finished "git config --unset format.useAutoBase" &&
1661         git config format.useAutoBase true &&
1662         git format-patch --stdout --base=HEAD~1 -1 >patch &&
1663         grep "^base-commit:" patch >actual &&
1664         echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1665         test_cmp expected actual
1666 '
1667
1668 test_expect_success 'format-patch --base with --attach' '
1669         git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
1670         sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
1671                 patch >actual &&
1672         test_write_lines 1 2 >expect &&
1673         test_cmp expect actual
1674 '
1675 test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
1676         test_when_finished "rm -fr patches" &&
1677         git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
1678         ! egrep "^--+mimemime" patches/0000*.patch &&
1679         egrep "^--+mimemime$" patches/0001*.patch >output &&
1680         test_line_count = 2 output &&
1681         egrep "^--+mimemime--$" patches/0001*.patch >output &&
1682         test_line_count = 1 output
1683 '
1684
1685 test_expect_success 'format-patch --pretty=mboxrd' '
1686         sp=" " &&
1687         cat >msg <<-INPUT_END &&
1688         mboxrd should escape the body
1689
1690         From could trip up a loose mbox parser
1691         >From extra escape for reversibility
1692         >>From extra escape for reversibility 2
1693         from lower case not escaped
1694         Fromm bad speling not escaped
1695          From with leading space not escaped
1696
1697         F
1698         From
1699         From$sp
1700         From    $sp
1701         From    $sp
1702         INPUT_END
1703
1704         cat >expect <<-INPUT_END &&
1705         >From could trip up a loose mbox parser
1706         >>From extra escape for reversibility
1707         >>>From extra escape for reversibility 2
1708         from lower case not escaped
1709         Fromm bad speling not escaped
1710          From with leading space not escaped
1711
1712         F
1713         From
1714         From
1715         From
1716         From
1717         INPUT_END
1718
1719         C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
1720         git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
1721         git grep -h --no-index -A11 \
1722                 "^>From could trip up a loose mbox parser" patch >actual &&
1723         test_cmp expect actual
1724 '
1725
1726 test_expect_success 'interdiff: setup' '
1727         git checkout -b boop master &&
1728         test_commit fnorp blorp &&
1729         test_commit fleep blorp
1730 '
1731
1732 test_expect_success 'interdiff: cover-letter' '
1733         sed "y/q/ /" >expect <<-\EOF &&
1734         +fleep
1735         --q
1736         EOF
1737         git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
1738         test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
1739         test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
1740         sed "1,/^@@ /d; /^-- $/q" <0000-cover-letter.patch >actual &&
1741         test_cmp expect actual
1742 '
1743
1744 test_expect_success 'interdiff: reroll-count' '
1745         git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
1746         test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
1747 '
1748
1749 test_expect_success 'interdiff: solo-patch' '
1750         cat >expect <<-\EOF &&
1751           +fleep
1752
1753         EOF
1754         git format-patch --interdiff=boop~2 -1 boop &&
1755         test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
1756         sed "1,/^  @@ /d; /^$/q" <0001-fleep.patch >actual &&
1757         test_cmp expect actual
1758 '
1759
1760 test_done