]> git.ipfire.org Git - thirdparty/git.git/blob - t/t4014-format-patch.sh
dir.c: unify is_excluded and is_path_excluded APIs
[thirdparty/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 doesn't consider merge commits" '
61
62 git checkout -b slave master &&
63 echo "Another line" >>file &&
64 test_tick &&
65 git commit -am "Slave change #1" &&
66 echo "Yet another line" >>file &&
67 test_tick &&
68 git commit -am "Slave change #2" &&
69 git checkout -b merger master &&
70 test_tick &&
71 git merge --no-ff slave &&
72 cnt=`git format-patch -3 --stdout | grep "^From " | wc -l` &&
73 test $cnt = 3
74 '
75
76 test_expect_success "format-patch result applies" '
77
78 git checkout -b rebuild-0 master &&
79 git am -3 patch0 &&
80 cnt=`git rev-list master.. | wc -l` &&
81 test $cnt = 2
82 '
83
84 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
85
86 git checkout -b rebuild-1 master &&
87 git am -3 patch1 &&
88 cnt=`git rev-list master.. | wc -l` &&
89 test $cnt = 2
90 '
91
92 test_expect_success 'commit did not screw up the log message' '
93
94 git cat-file commit side | grep "^Side .* with .* backslash-n"
95
96 '
97
98 test_expect_success 'format-patch did not screw up the log message' '
99
100 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
101 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
102
103 '
104
105 test_expect_success 'replay did not screw up the log message' '
106
107 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
108
109 '
110
111 test_expect_success 'extra headers' '
112
113 git config format.headers "To: R E Cipient <rcipient@example.com>
114 " &&
115 git config --add format.headers "Cc: S E Cipient <scipient@example.com>
116 " &&
117 git format-patch --stdout master..side > patch2 &&
118 sed -e "/^\$/q" patch2 > hdrs2 &&
119 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
120 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
121
122 '
123
124 test_expect_success 'extra headers without newlines' '
125
126 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
127 git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
128 git format-patch --stdout master..side >patch3 &&
129 sed -e "/^\$/q" patch3 > hdrs3 &&
130 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
131 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
132
133 '
134
135 test_expect_success 'extra headers with multiple To:s' '
136
137 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
138 git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
139 git format-patch --stdout master..side > patch4 &&
140 sed -e "/^\$/q" patch4 > hdrs4 &&
141 grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
142 grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
143 '
144
145 test_expect_success 'additional command line cc (ascii)' '
146
147 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
148 git format-patch --cc="S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
149 grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
150 grep "^ *S E Cipient <scipient@example.com>\$" patch5
151 '
152
153 test_expect_failure 'additional command line cc (rfc822)' '
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_success 'command line headers' '
162
163 git config --unset-all format.headers &&
164 git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
165 grep "^Cc: R E Cipient <rcipient@example.com>\$" patch6
166 '
167
168 test_expect_success 'configuration headers and command line headers' '
169
170 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
171 git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
172 grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch7 &&
173 grep "^ *S E Cipient <scipient@example.com>\$" patch7
174 '
175
176 test_expect_success 'command line To: header (ascii)' '
177
178 git config --unset-all format.headers &&
179 git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
180 grep "^To: R E Cipient <rcipient@example.com>\$" patch8
181 '
182
183 test_expect_failure 'command line To: header (rfc822)' '
184
185 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
186 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch8
187 '
188
189 test_expect_failure 'command line To: header (rfc2047)' '
190
191 git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
192 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch8
193 '
194
195 test_expect_success 'configuration To: header (ascii)' '
196
197 git config format.to "R E Cipient <rcipient@example.com>" &&
198 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
199 grep "^To: R E Cipient <rcipient@example.com>\$" patch9
200 '
201
202 test_expect_failure 'configuration To: header (rfc822)' '
203
204 git config format.to "R. E. Cipient <rcipient@example.com>" &&
205 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
206 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch9
207 '
208
209 test_expect_failure 'configuration To: header (rfc2047)' '
210
211 git config format.to "R Ä Cipient <rcipient@example.com>" &&
212 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
213 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch9
214 '
215
216 # check_patch <patch>: Verify that <patch> looks like a half-sane
217 # patch email to avoid a false positive with !grep
218 check_patch () {
219 grep -e "^From:" "$1" &&
220 grep -e "^Date:" "$1" &&
221 grep -e "^Subject:" "$1"
222 }
223
224 test_expect_success '--no-to overrides config.to' '
225
226 git config --replace-all format.to \
227 "R E Cipient <rcipient@example.com>" &&
228 git format-patch --no-to --stdout master..side |
229 sed -e "/^\$/q" >patch10 &&
230 check_patch patch10 &&
231 ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10
232 '
233
234 test_expect_success '--no-to and --to replaces config.to' '
235
236 git config --replace-all format.to \
237 "Someone <someone@out.there>" &&
238 git format-patch --no-to --to="Someone Else <else@out.there>" \
239 --stdout master..side |
240 sed -e "/^\$/q" >patch11 &&
241 check_patch patch11 &&
242 ! grep "^To: Someone <someone@out.there>\$" patch11 &&
243 grep "^To: Someone Else <else@out.there>\$" patch11
244 '
245
246 test_expect_success '--no-cc overrides config.cc' '
247
248 git config --replace-all format.cc \
249 "C E Cipient <rcipient@example.com>" &&
250 git format-patch --no-cc --stdout master..side |
251 sed -e "/^\$/q" >patch12 &&
252 check_patch patch12 &&
253 ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12
254 '
255
256 test_expect_success '--no-add-header overrides config.headers' '
257
258 git config --replace-all format.headers \
259 "Header1: B E Cipient <rcipient@example.com>" &&
260 git format-patch --no-add-header --stdout master..side |
261 sed -e "/^\$/q" >patch13 &&
262 check_patch patch13 &&
263 ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13
264 '
265
266 test_expect_success 'multiple files' '
267
268 rm -rf patches/ &&
269 git checkout side &&
270 git format-patch -o patches/ master &&
271 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
272 '
273
274 test_expect_success 'reroll count' '
275 rm -fr patches &&
276 git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
277 ! grep -v "^patches/v4-000[0-3]-" list &&
278 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
279 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
280 '
281
282 test_expect_success 'reroll count (-v)' '
283 rm -fr patches &&
284 git format-patch -o patches --cover-letter -v4 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 check_threading () {
291 expect="$1" &&
292 shift &&
293 (git format-patch --stdout "$@"; echo $? > status.out) |
294 # Prints everything between the Message-ID and In-Reply-To,
295 # and replaces all Message-ID-lookalikes by a sequence number
296 "$PERL_PATH" -ne '
297 if (/^(message-id|references|in-reply-to)/i) {
298 $printing = 1;
299 } elsif (/^\S/) {
300 $printing = 0;
301 }
302 if ($printing) {
303 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
304 for $k (keys %h) {s/$k/$h{$k}/};
305 print;
306 }
307 print "---\n" if /^From /i;
308 ' > actual &&
309 test 0 = "$(cat status.out)" &&
310 test_cmp "$expect" actual
311 }
312
313 cat >> expect.no-threading <<EOF
314 ---
315 ---
316 ---
317 EOF
318
319 test_expect_success 'no threading' '
320 git checkout side &&
321 check_threading expect.no-threading master
322 '
323
324 cat > expect.thread <<EOF
325 ---
326 Message-Id: <0>
327 ---
328 Message-Id: <1>
329 In-Reply-To: <0>
330 References: <0>
331 ---
332 Message-Id: <2>
333 In-Reply-To: <0>
334 References: <0>
335 EOF
336
337 test_expect_success 'thread' '
338 check_threading expect.thread --thread master
339 '
340
341 cat > expect.in-reply-to <<EOF
342 ---
343 Message-Id: <0>
344 In-Reply-To: <1>
345 References: <1>
346 ---
347 Message-Id: <2>
348 In-Reply-To: <1>
349 References: <1>
350 ---
351 Message-Id: <3>
352 In-Reply-To: <1>
353 References: <1>
354 EOF
355
356 test_expect_success 'thread in-reply-to' '
357 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
358 --thread master
359 '
360
361 cat > expect.cover-letter <<EOF
362 ---
363 Message-Id: <0>
364 ---
365 Message-Id: <1>
366 In-Reply-To: <0>
367 References: <0>
368 ---
369 Message-Id: <2>
370 In-Reply-To: <0>
371 References: <0>
372 ---
373 Message-Id: <3>
374 In-Reply-To: <0>
375 References: <0>
376 EOF
377
378 test_expect_success 'thread cover-letter' '
379 check_threading expect.cover-letter --cover-letter --thread master
380 '
381
382 cat > expect.cl-irt <<EOF
383 ---
384 Message-Id: <0>
385 In-Reply-To: <1>
386 References: <1>
387 ---
388 Message-Id: <2>
389 In-Reply-To: <0>
390 References: <1>
391 <0>
392 ---
393 Message-Id: <3>
394 In-Reply-To: <0>
395 References: <1>
396 <0>
397 ---
398 Message-Id: <4>
399 In-Reply-To: <0>
400 References: <1>
401 <0>
402 EOF
403
404 test_expect_success 'thread cover-letter in-reply-to' '
405 check_threading expect.cl-irt --cover-letter \
406 --in-reply-to="<test.message>" --thread master
407 '
408
409 test_expect_success 'thread explicit shallow' '
410 check_threading expect.cl-irt --cover-letter \
411 --in-reply-to="<test.message>" --thread=shallow master
412 '
413
414 cat > expect.deep <<EOF
415 ---
416 Message-Id: <0>
417 ---
418 Message-Id: <1>
419 In-Reply-To: <0>
420 References: <0>
421 ---
422 Message-Id: <2>
423 In-Reply-To: <1>
424 References: <0>
425 <1>
426 EOF
427
428 test_expect_success 'thread deep' '
429 check_threading expect.deep --thread=deep master
430 '
431
432 cat > expect.deep-irt <<EOF
433 ---
434 Message-Id: <0>
435 In-Reply-To: <1>
436 References: <1>
437 ---
438 Message-Id: <2>
439 In-Reply-To: <0>
440 References: <1>
441 <0>
442 ---
443 Message-Id: <3>
444 In-Reply-To: <2>
445 References: <1>
446 <0>
447 <2>
448 EOF
449
450 test_expect_success 'thread deep in-reply-to' '
451 check_threading expect.deep-irt --thread=deep \
452 --in-reply-to="<test.message>" master
453 '
454
455 cat > expect.deep-cl <<EOF
456 ---
457 Message-Id: <0>
458 ---
459 Message-Id: <1>
460 In-Reply-To: <0>
461 References: <0>
462 ---
463 Message-Id: <2>
464 In-Reply-To: <1>
465 References: <0>
466 <1>
467 ---
468 Message-Id: <3>
469 In-Reply-To: <2>
470 References: <0>
471 <1>
472 <2>
473 EOF
474
475 test_expect_success 'thread deep cover-letter' '
476 check_threading expect.deep-cl --cover-letter --thread=deep master
477 '
478
479 cat > expect.deep-cl-irt <<EOF
480 ---
481 Message-Id: <0>
482 In-Reply-To: <1>
483 References: <1>
484 ---
485 Message-Id: <2>
486 In-Reply-To: <0>
487 References: <1>
488 <0>
489 ---
490 Message-Id: <3>
491 In-Reply-To: <2>
492 References: <1>
493 <0>
494 <2>
495 ---
496 Message-Id: <4>
497 In-Reply-To: <3>
498 References: <1>
499 <0>
500 <2>
501 <3>
502 EOF
503
504 test_expect_success 'thread deep cover-letter in-reply-to' '
505 check_threading expect.deep-cl-irt --cover-letter \
506 --in-reply-to="<test.message>" --thread=deep master
507 '
508
509 test_expect_success 'thread via config' '
510 test_config format.thread true &&
511 check_threading expect.thread master
512 '
513
514 test_expect_success 'thread deep via config' '
515 test_config format.thread deep &&
516 check_threading expect.deep master
517 '
518
519 test_expect_success 'thread config + override' '
520 test_config format.thread deep &&
521 check_threading expect.thread --thread master
522 '
523
524 test_expect_success 'thread config + --no-thread' '
525 test_config format.thread deep &&
526 check_threading expect.no-threading --no-thread master
527 '
528
529 test_expect_success 'excessive subject' '
530
531 rm -rf patches/ &&
532 git checkout side &&
533 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
534 git update-index file &&
535 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." &&
536 git format-patch -o patches/ master..side &&
537 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
538 '
539
540 test_expect_success 'cover-letter inherits diff options' '
541
542 git mv file foo &&
543 git commit -m foo &&
544 git format-patch --cover-letter -1 &&
545 check_patch 0000-cover-letter.patch &&
546 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
547 git format-patch --cover-letter -1 -M &&
548 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
549
550 '
551
552 cat > expect << EOF
553 This is an excessively long subject line for a message due to the
554 habit some projects have of not having a short, one-line subject at
555 the start of the commit message, but rather sticking a whole
556 paragraph right at the start as the only thing in the commit
557 message. It had better not become the filename for the patch.
558 foo
559
560 EOF
561
562 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
563
564 git format-patch --cover-letter -2 &&
565 sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
566 test_cmp expect output
567
568 '
569
570 cat > expect << EOF
571 index 40f36c6..2dc5c23 100644
572 --- a/file
573 +++ b/file
574 @@ -13,4 +13,20 @@ C
575 10
576 D
577 E
578 F
579 +5
580 EOF
581
582 test_expect_success 'format-patch respects -U' '
583
584 git format-patch -U4 -2 &&
585 sed -e "1,/^diff/d" -e "/^+5/q" \
586 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
587 >output &&
588 test_cmp expect output
589
590 '
591
592 cat > expect << EOF
593
594 diff --git a/file b/file
595 index 40f36c6..2dc5c23 100644
596 --- a/file
597 +++ b/file
598 @@ -14,3 +14,19 @@ C
599 D
600 E
601 F
602 +5
603 EOF
604
605 test_expect_success 'format-patch -p suppresses stat' '
606
607 git format-patch -p -2 &&
608 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
609 test_cmp expect output
610
611 '
612
613 test_expect_success 'format-patch from a subdirectory (1)' '
614 filename=$(
615 rm -rf sub &&
616 mkdir -p sub/dir &&
617 cd sub/dir &&
618 git format-patch -1
619 ) &&
620 case "$filename" in
621 0*)
622 ;; # ok
623 *)
624 echo "Oops? $filename"
625 false
626 ;;
627 esac &&
628 test -f "$filename"
629 '
630
631 test_expect_success 'format-patch from a subdirectory (2)' '
632 filename=$(
633 rm -rf sub &&
634 mkdir -p sub/dir &&
635 cd sub/dir &&
636 git format-patch -1 -o ..
637 ) &&
638 case "$filename" in
639 ../0*)
640 ;; # ok
641 *)
642 echo "Oops? $filename"
643 false
644 ;;
645 esac &&
646 basename=$(expr "$filename" : ".*/\(.*\)") &&
647 test -f "sub/$basename"
648 '
649
650 test_expect_success 'format-patch from a subdirectory (3)' '
651 rm -f 0* &&
652 filename=$(
653 rm -rf sub &&
654 mkdir -p sub/dir &&
655 cd sub/dir &&
656 git format-patch -1 -o "$TRASH_DIRECTORY"
657 ) &&
658 basename=$(expr "$filename" : ".*/\(.*\)") &&
659 test -f "$basename"
660 '
661
662 test_expect_success 'format-patch --in-reply-to' '
663 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
664 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
665 grep "^References: <baz@foo.bar>" patch8
666 '
667
668 test_expect_success 'format-patch --signoff' '
669 git format-patch -1 --signoff --stdout >out &&
670 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
671 '
672
673 test_expect_success 'format-patch --notes --signoff' '
674 git notes --ref test add -m "test message" HEAD &&
675 git format-patch -1 --signoff --stdout --notes=test >out &&
676 # Three dashes must come after S-o-b
677 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
678 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
679 # Notes message must come after three dashes
680 ! sed "/^---$/q" out | grep "test message" &&
681 sed "1,/^---$/d" out | grep "test message"
682 '
683
684 echo "fatal: --name-only does not make sense" > expect.name-only
685 echo "fatal: --name-status does not make sense" > expect.name-status
686 echo "fatal: --check does not make sense" > expect.check
687
688 test_expect_success 'options no longer allowed for format-patch' '
689 test_must_fail git format-patch --name-only 2> output &&
690 test_i18ncmp expect.name-only output &&
691 test_must_fail git format-patch --name-status 2> output &&
692 test_i18ncmp expect.name-status output &&
693 test_must_fail git format-patch --check 2> output &&
694 test_i18ncmp expect.check output'
695
696 test_expect_success 'format-patch --numstat should produce a patch' '
697 git format-patch --numstat --stdout master..side > output &&
698 test 6 = $(grep "^diff --git a/" output | wc -l)'
699
700 test_expect_success 'format-patch -- <path>' '
701 git format-patch master..side -- file 2>error &&
702 ! grep "Use .--" error
703 '
704
705 test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
706 git format-patch --ignore-if-in-upstream HEAD
707 '
708
709 test_expect_success 'format-patch --signature' '
710 git format-patch --stdout --signature="my sig" -1 >output &&
711 grep "my sig" output
712 '
713
714 test_expect_success 'format-patch with format.signature config' '
715 git config format.signature "config sig" &&
716 git format-patch --stdout -1 >output &&
717 grep "config sig" output
718 '
719
720 test_expect_success 'format-patch --signature overrides format.signature' '
721 git config format.signature "config sig" &&
722 git format-patch --stdout --signature="overrides" -1 >output &&
723 ! grep "config sig" output &&
724 grep "overrides" output
725 '
726
727 test_expect_success 'format-patch --no-signature ignores format.signature' '
728 git config format.signature "config sig" &&
729 git format-patch --stdout --signature="my sig" --no-signature \
730 -1 >output &&
731 check_patch output &&
732 ! grep "config sig" output &&
733 ! grep "my sig" output &&
734 ! grep "^-- \$" output
735 '
736
737 test_expect_success 'format-patch --signature --cover-letter' '
738 git config --unset-all format.signature &&
739 git format-patch --stdout --signature="my sig" --cover-letter \
740 -1 >output &&
741 grep "my sig" output &&
742 test 2 = $(grep "my sig" output | wc -l)
743 '
744
745 test_expect_success 'format.signature="" suppresses signatures' '
746 git config format.signature "" &&
747 git format-patch --stdout -1 >output &&
748 check_patch output &&
749 ! grep "^-- \$" output
750 '
751
752 test_expect_success 'format-patch --no-signature suppresses signatures' '
753 git config --unset-all format.signature &&
754 git format-patch --stdout --no-signature -1 >output &&
755 check_patch output &&
756 ! grep "^-- \$" output
757 '
758
759 test_expect_success 'format-patch --signature="" suppresses signatures' '
760 git format-patch --stdout --signature="" -1 >output &&
761 check_patch output &&
762 ! grep "^-- \$" output
763 '
764
765 test_expect_success TTY 'format-patch --stdout paginates' '
766 rm -f pager_used &&
767 (
768 GIT_PAGER="wc >pager_used" &&
769 export GIT_PAGER &&
770 test_terminal git format-patch --stdout --all
771 ) &&
772 test_path_is_file pager_used
773 '
774
775 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
776 rm -f pager_used &&
777 (
778 GIT_PAGER="wc >pager_used" &&
779 export GIT_PAGER &&
780 test_terminal git --no-pager format-patch --stdout --all &&
781 test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
782 ) &&
783 test_path_is_missing pager_used &&
784 test_path_is_missing .git/pager_used
785 '
786
787 test_expect_success 'format-patch handles multi-line subjects' '
788 rm -rf patches/ &&
789 echo content >>file &&
790 for i in one two three; do echo $i; done >msg &&
791 git add file &&
792 git commit -F msg &&
793 git format-patch -o patches -1 &&
794 grep ^Subject: patches/0001-one.patch >actual &&
795 echo "Subject: [PATCH] one two three" >expect &&
796 test_cmp expect actual
797 '
798
799 test_expect_success 'format-patch handles multi-line encoded subjects' '
800 rm -rf patches/ &&
801 echo content >>file &&
802 for i in en två tre; do echo $i; done >msg &&
803 git add file &&
804 git commit -F msg &&
805 git format-patch -o patches -1 &&
806 grep ^Subject: patches/0001-en.patch >actual &&
807 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
808 test_cmp expect actual
809 '
810
811 M8="foo bar "
812 M64=$M8$M8$M8$M8$M8$M8$M8$M8
813 M512=$M64$M64$M64$M64$M64$M64$M64$M64
814 cat >expect <<'EOF'
815 Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
816 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
817 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
818 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
819 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
820 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
821 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
822 EOF
823 test_expect_success 'format-patch wraps extremely long subject (ascii)' '
824 echo content >>file &&
825 git add file &&
826 git commit -m "$M512" &&
827 git format-patch --stdout -1 >patch &&
828 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
829 test_cmp expect subject
830 '
831
832 M8="föö bar "
833 M64=$M8$M8$M8$M8$M8$M8$M8$M8
834 M512=$M64$M64$M64$M64$M64$M64$M64$M64
835 cat >expect <<'EOF'
836 Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
837 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
838 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
839 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
840 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
841 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
842 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
843 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
844 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
845 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
846 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
847 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
848 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
849 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
850 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
851 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
852 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
853 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
854 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
855 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
856 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
857 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
858 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
859 =?UTF-8?q?bar?=
860 EOF
861 test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
862 rm -rf patches/ &&
863 echo content >>file &&
864 git add file &&
865 git commit -m "$M512" &&
866 git format-patch --stdout -1 >patch &&
867 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
868 test_cmp expect subject
869 '
870
871 check_author() {
872 echo content >>file &&
873 git add file &&
874 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
875 git format-patch --stdout -1 >patch &&
876 sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
877 test_cmp expect actual
878 }
879
880 cat >expect <<'EOF'
881 From: "Foo B. Bar" <author@example.com>
882 EOF
883 test_expect_success 'format-patch quotes dot in from-headers' '
884 check_author "Foo B. Bar"
885 '
886
887 cat >expect <<'EOF'
888 From: "Foo \"The Baz\" Bar" <author@example.com>
889 EOF
890 test_expect_success 'format-patch quotes double-quote in from-headers' '
891 check_author "Foo \"The Baz\" Bar"
892 '
893
894 cat >expect <<'EOF'
895 From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
896 EOF
897 test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
898 check_author "Föo Bar"
899 '
900
901 cat >expect <<'EOF'
902 From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
903 EOF
904 test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
905 check_author "Föo B. Bar"
906 '
907
908 cat >expect <<EOF
909 From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
910 <author@example.com>
911 EOF
912 test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
913 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
914 '
915
916 cat >expect <<'EOF'
917 From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
918 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
919 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
920 EOF
921 test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
922 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"
923 '
924
925 cat >expect <<'EOF'
926 From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
927 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
928 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
929 EOF
930 test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
931 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"
932 '
933
934 cat >expect <<'EOF'
935 From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
936 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
937 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
938 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
939 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
940 EOF
941 test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
942 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"
943 '
944
945 cat >expect <<'EOF'
946 Subject: header with . in it
947 EOF
948 test_expect_success 'subject lines do not have 822 atom-quoting' '
949 echo content >>file &&
950 git add file &&
951 git commit -m "header with . in it" &&
952 git format-patch -k -1 --stdout >patch &&
953 grep ^Subject: patch >actual &&
954 test_cmp expect actual
955 '
956
957 cat >expect <<'EOF'
958 Subject: [PREFIX 1/1] header with . in it
959 EOF
960 test_expect_success 'subject prefixes have space prepended' '
961 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
962 grep ^Subject: patch >actual &&
963 test_cmp expect actual
964 '
965
966 cat >expect <<'EOF'
967 Subject: [1/1] header with . in it
968 EOF
969 test_expect_success 'empty subject prefix does not have extra space' '
970 git format-patch -n -1 --stdout --subject-prefix= >patch &&
971 grep ^Subject: patch >actual &&
972 test_cmp expect actual
973 '
974
975 append_signoff()
976 {
977 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
978 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
979 sed -n -e "1,/^---$/p" append_signoff.patch |
980 egrep -n "^Subject|Sign|^$"
981 }
982
983 test_expect_success 'signoff: commit with no body' '
984 append_signoff </dev/null >actual &&
985 cat <<\EOF | sed "s/EOL$//" >expected &&
986 4:Subject: [PATCH] EOL
987 8:
988 9:Signed-off-by: C O Mitter <committer@example.com>
989 EOF
990 test_cmp expected actual
991 '
992
993 test_expect_success 'signoff: commit with only subject' '
994 echo subject | append_signoff >actual &&
995 cat >expected <<\EOF &&
996 4:Subject: [PATCH] subject
997 8:
998 9:Signed-off-by: C O Mitter <committer@example.com>
999 EOF
1000 test_cmp expected actual
1001 '
1002
1003 test_expect_success 'signoff: commit with only subject that does not end with NL' '
1004 printf subject | append_signoff >actual &&
1005 cat >expected <<\EOF &&
1006 4:Subject: [PATCH] subject
1007 8:
1008 9:Signed-off-by: C O Mitter <committer@example.com>
1009 EOF
1010 test_cmp expected actual
1011 '
1012
1013 test_expect_success 'signoff: no existing signoffs' '
1014 append_signoff <<\EOF >actual &&
1015 subject
1016
1017 body
1018 EOF
1019 cat >expected <<\EOF &&
1020 4:Subject: [PATCH] subject
1021 8:
1022 10:
1023 11:Signed-off-by: C O Mitter <committer@example.com>
1024 EOF
1025 test_cmp expected actual
1026 '
1027
1028 test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1029 printf "subject\n\nbody" | append_signoff >actual &&
1030 cat >expected <<\EOF &&
1031 4:Subject: [PATCH] subject
1032 8:
1033 10:
1034 11:Signed-off-by: C O Mitter <committer@example.com>
1035 EOF
1036 test_cmp expected actual
1037 '
1038
1039 test_expect_success 'signoff: some random signoff' '
1040 append_signoff <<\EOF >actual &&
1041 subject
1042
1043 body
1044
1045 Signed-off-by: my@house
1046 EOF
1047 cat >expected <<\EOF &&
1048 4:Subject: [PATCH] subject
1049 8:
1050 10:
1051 11:Signed-off-by: my@house
1052 12:Signed-off-by: C O Mitter <committer@example.com>
1053 EOF
1054 test_cmp expected actual
1055 '
1056
1057 test_expect_success 'signoff: misc conforming footer elements' '
1058 append_signoff <<\EOF >actual &&
1059 subject
1060
1061 body
1062
1063 Signed-off-by: my@house
1064 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1065 Tested-by: Some One <someone@example.com>
1066 Bug: 1234
1067 EOF
1068 cat >expected <<\EOF &&
1069 4:Subject: [PATCH] subject
1070 8:
1071 10:
1072 11:Signed-off-by: my@house
1073 15:Signed-off-by: C O Mitter <committer@example.com>
1074 EOF
1075 test_cmp expected actual
1076 '
1077
1078 test_expect_success 'signoff: some random signoff-alike' '
1079 append_signoff <<\EOF >actual &&
1080 subject
1081
1082 body
1083 Fooled-by-me: my@house
1084 EOF
1085 cat >expected <<\EOF &&
1086 4:Subject: [PATCH] subject
1087 8:
1088 11:
1089 12:Signed-off-by: C O Mitter <committer@example.com>
1090 EOF
1091 test_cmp expected actual
1092 '
1093
1094 test_expect_success 'signoff: not really a signoff' '
1095 append_signoff <<\EOF >actual &&
1096 subject
1097
1098 I want to mention about Signed-off-by: here.
1099 EOF
1100 cat >expected <<\EOF &&
1101 4:Subject: [PATCH] subject
1102 8:
1103 9:I want to mention about Signed-off-by: here.
1104 10:
1105 11:Signed-off-by: C O Mitter <committer@example.com>
1106 EOF
1107 test_cmp expected actual
1108 '
1109
1110 test_expect_success 'signoff: not really a signoff (2)' '
1111 append_signoff <<\EOF >actual &&
1112 subject
1113
1114 My unfortunate
1115 Signed-off-by: example happens to be wrapped here.
1116 EOF
1117 cat >expected <<\EOF &&
1118 4:Subject: [PATCH] subject
1119 8:
1120 10:Signed-off-by: example happens to be wrapped here.
1121 11:
1122 12:Signed-off-by: C O Mitter <committer@example.com>
1123 EOF
1124 test_cmp expected actual
1125 '
1126
1127 test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
1128 append_signoff <<\EOF >actual &&
1129 subject
1130
1131 Signed-off-by: my@house
1132 Signed-off-by: your@house
1133
1134 A lot of houses.
1135 EOF
1136 cat >expected <<\EOF &&
1137 4:Subject: [PATCH] subject
1138 8:
1139 9:Signed-off-by: my@house
1140 10:Signed-off-by: your@house
1141 11:
1142 13:
1143 14:Signed-off-by: C O Mitter <committer@example.com>
1144 EOF
1145 test_cmp expected actual
1146 '
1147
1148 test_expect_success 'signoff: the same signoff at the end' '
1149 append_signoff <<\EOF >actual &&
1150 subject
1151
1152 body
1153
1154 Signed-off-by: C O Mitter <committer@example.com>
1155 EOF
1156 cat >expected <<\EOF &&
1157 4:Subject: [PATCH] subject
1158 8:
1159 10:
1160 11:Signed-off-by: C O Mitter <committer@example.com>
1161 EOF
1162 test_cmp expected actual
1163 '
1164
1165 test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1166 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1167 append_signoff >actual &&
1168 cat >expected <<\EOF &&
1169 4:Subject: [PATCH] subject
1170 8:
1171 9:Signed-off-by: C O Mitter <committer@example.com>
1172 EOF
1173 test_cmp expected actual
1174 '
1175
1176 test_expect_success 'signoff: the same signoff NOT at the end' '
1177 append_signoff <<\EOF >actual &&
1178 subject
1179
1180 body
1181
1182 Signed-off-by: C O Mitter <committer@example.com>
1183 Signed-off-by: my@house
1184 EOF
1185 cat >expected <<\EOF &&
1186 4:Subject: [PATCH] subject
1187 8:
1188 10:
1189 11:Signed-off-by: C O Mitter <committer@example.com>
1190 12:Signed-off-by: my@house
1191 EOF
1192 test_cmp expected actual
1193 '
1194
1195 test_expect_success 'signoff: detect garbage in non-conforming footer' '
1196 append_signoff <<\EOF >actual &&
1197 subject
1198
1199 body
1200
1201 Tested-by: my@house
1202 Some Trash
1203 Signed-off-by: C O Mitter <committer@example.com>
1204 EOF
1205 cat >expected <<\EOF &&
1206 4:Subject: [PATCH] subject
1207 8:
1208 10:
1209 13:Signed-off-by: C O Mitter <committer@example.com>
1210 14:
1211 15:Signed-off-by: C O Mitter <committer@example.com>
1212 EOF
1213 test_cmp expected actual
1214 '
1215
1216 test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1217 append_signoff <<\EOF >actual &&
1218 subject
1219
1220 body
1221
1222 Reviewed-id: Noone
1223 Tested-by: my@house
1224 Change-id: Ideadbeef
1225 Signed-off-by: C O Mitter <committer@example.com>
1226 Bug: 1234
1227 EOF
1228 cat >expected <<\EOF &&
1229 4:Subject: [PATCH] subject
1230 8:
1231 10:
1232 14:Signed-off-by: C O Mitter <committer@example.com>
1233 EOF
1234 test_cmp expected actual
1235 '
1236
1237 test_expect_success 'format patch ignores color.ui' '
1238 test_unconfig color.ui &&
1239 git format-patch --stdout -1 >expect &&
1240 test_config color.ui always &&
1241 git format-patch --stdout -1 >actual &&
1242 test_cmp expect actual
1243 '
1244
1245 test_expect_success 'cover letter using branch description (1)' '
1246 git checkout rebuild-1 &&
1247 test_config branch.rebuild-1.description hello &&
1248 git format-patch --stdout --cover-letter master >actual &&
1249 grep hello actual >/dev/null
1250 '
1251
1252 test_expect_success 'cover letter using branch description (2)' '
1253 git checkout rebuild-1 &&
1254 test_config branch.rebuild-1.description hello &&
1255 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1256 grep hello actual >/dev/null
1257 '
1258
1259 test_expect_success 'cover letter using branch description (3)' '
1260 git checkout rebuild-1 &&
1261 test_config branch.rebuild-1.description hello &&
1262 git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1263 grep hello actual >/dev/null
1264 '
1265
1266 test_expect_success 'cover letter using branch description (4)' '
1267 git checkout rebuild-1 &&
1268 test_config branch.rebuild-1.description hello &&
1269 git format-patch --stdout --cover-letter master.. >actual &&
1270 grep hello actual >/dev/null
1271 '
1272
1273 test_expect_success 'cover letter using branch description (5)' '
1274 git checkout rebuild-1 &&
1275 test_config branch.rebuild-1.description hello &&
1276 git format-patch --stdout --cover-letter -2 HEAD >actual &&
1277 grep hello actual >/dev/null
1278 '
1279
1280 test_expect_success 'cover letter using branch description (6)' '
1281 git checkout rebuild-1 &&
1282 test_config branch.rebuild-1.description hello &&
1283 git format-patch --stdout --cover-letter -2 >actual &&
1284 grep hello actual >/dev/null
1285 '
1286
1287 test_done