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