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