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