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