]> git.ipfire.org Git - thirdparty/git.git/blame - t/t4014-format-patch.sh
Merge branch 'en/merge-recursive-directory-rename-fixes'
[thirdparty/git.git] / t / t4014-format-patch.sh
CommitLineData
ece3c67f
JH
1#!/bin/sh
2#
3# Copyright (c) 2006 Junio C Hamano
4#
5
9800a754 6test_description='various format-patch tests'
ece3c67f
JH
7
8. ./test-lib.sh
38a94bb6 9. "$TEST_DIRECTORY"/lib-terminal.sh
ece3c67f
JH
10
11test_expect_success setup '
ece3c67f 12 for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
cd894ee9
JH
13 cat file >elif &&
14 git add file elif &&
6426f2d2 15 test_tick &&
ece3c67f
JH
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 &&
1f553918 20 test_chmod +x elif &&
6426f2d2 21 test_tick &&
816366e2 22 git commit -m "Side changes #1" &&
ece3c67f
JH
23
24 for i in D E F; do echo "$i"; done >>file &&
25 git update-index file &&
6426f2d2 26 test_tick &&
816366e2 27 git commit -m "Side changes #2" &&
982b64e4 28 git tag C2 &&
ece3c67f
JH
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 &&
6426f2d2 32 test_tick &&
816366e2 33 git commit -m "Side changes #3 with \\n backslash-n in it." &&
ece3c67f
JH
34
35 git checkout master &&
854b5cb4
DL
36 git diff-tree -p C2 >patch &&
37 git apply --index <patch &&
6426f2d2 38 test_tick &&
6f93d261 39 git commit -m "Master accepts moral equivalent of #2" &&
ece3c67f 40
6f93d261
SB
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
ece3c67f
JH
60'
61
0ab74e97 62test_expect_success 'format-patch --ignore-if-in-upstream' '
ece3c67f 63 git format-patch --stdout master..side >patch0 &&
6bd26f58
DL
64 grep "^From " patch0 >from0 &&
65 test_line_count = 3 from0
ece3c67f
JH
66'
67
0ab74e97 68test_expect_success 'format-patch --ignore-if-in-upstream' '
ece3c67f
JH
69 git format-patch --stdout \
70 --ignore-if-in-upstream master..side >patch1 &&
6bd26f58
DL
71 grep "^From " patch1 >from1 &&
72 test_line_count = 2 from1
ece3c67f
JH
73'
74
0ab74e97 75test_expect_success 'format-patch --ignore-if-in-upstream handles tags' '
9b7a61d7
JH
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 &&
6bd26f58
DL
79 grep "^From " patch1 >from1 &&
80 test_line_count = 2 from1
9b7a61d7
JH
81'
82
2c642ed8 83test_expect_success "format-patch doesn't consider merge commits" '
2c642ed8
RR
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 &&
6bd26f58
DL
94 git format-patch -3 --stdout >patch &&
95 grep "^From " patch >from &&
96 test_line_count = 3 from
2c642ed8
RR
97'
98
0ab74e97 99test_expect_success 'format-patch result applies' '
ece3c67f
JH
100 git checkout -b rebuild-0 master &&
101 git am -3 patch0 &&
6bd26f58
DL
102 git rev-list master.. >list &&
103 test_line_count = 2 list
ece3c67f
JH
104'
105
0ab74e97 106test_expect_success 'format-patch --ignore-if-in-upstream result applies' '
ece3c67f
JH
107 git checkout -b rebuild-1 master &&
108 git am -3 patch1 &&
6bd26f58
DL
109 git rev-list master.. >list &&
110 test_line_count = 2 list
ece3c67f
JH
111'
112
816366e2 113test_expect_success 'commit did not screw up the log message' '
854b5cb4
DL
114 git cat-file commit side >actual &&
115 grep "^Side .* with .* backslash-n" actual
816366e2
JH
116'
117
118test_expect_success 'format-patch did not screw up the log message' '
816366e2
JH
119 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
120 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
816366e2
JH
121'
122
123test_expect_success 'replay did not screw up the log message' '
854b5cb4
DL
124 git cat-file commit rebuild-1 >actual &&
125 grep "^Side .* with .* backslash-n" actual
816366e2
JH
126'
127
a8d8173e 128test_expect_success 'extra headers' '
25dc8dad 129 git config format.headers "To: R E Cipient <rcipient@example.com>
a8d8173e 130" &&
25dc8dad 131 git config --add format.headers "Cc: S E Cipient <scipient@example.com>
a8d8173e 132" &&
92014b69
DL
133 git format-patch --stdout master..side >patch2 &&
134 sed -e "/^\$/q" patch2 >hdrs2 &&
25dc8dad
JS
135 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
136 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
a8d8173e
DB
137'
138
7d22708b 139test_expect_success 'extra headers without newlines' '
25dc8dad
JS
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>" &&
a8d8173e 142 git format-patch --stdout master..side >patch3 &&
92014b69 143 sed -e "/^\$/q" patch3 >hdrs3 &&
25dc8dad
JS
144 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
145 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
a8d8173e
DB
146'
147
3ee79d9f 148test_expect_success 'extra headers with multiple To:s' '
25dc8dad
JS
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>" &&
92014b69
DL
151 git format-patch --stdout master..side >patch4 &&
152 sed -e "/^\$/q" patch4 >hdrs4 &&
25dc8dad
JS
153 grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
154 grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
a8d8173e
DB
155'
156
25dc8dad 157test_expect_success 'additional command line cc (ascii)' '
25dc8dad 158 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
854b5cb4
DL
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
25dc8dad
JS
163'
164
165test_expect_failure 'additional command line cc (rfc822)' '
25dc8dad 166 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
854b5cb4
DL
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
736cc67d
DB
171'
172
d7d9c2d0 173test_expect_success 'command line headers' '
d7d9c2d0 174 git config --unset-all format.headers &&
854b5cb4
DL
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
d7d9c2d0
MH
178'
179
180test_expect_success 'configuration headers and command line headers' '
25dc8dad 181 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
854b5cb4
DL
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
d7d9c2d0
MH
186'
187
25dc8dad 188test_expect_success 'command line To: header (ascii)' '
ae6c098f 189 git config --unset-all format.headers &&
854b5cb4
DL
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
25dc8dad
JS
193'
194
195test_expect_failure 'command line To: header (rfc822)' '
854b5cb4
DL
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
25dc8dad
JS
199'
200
201test_expect_failure 'command line To: header (rfc2047)' '
854b5cb4
DL
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
ae6c098f
SD
205'
206
25dc8dad 207test_expect_success 'configuration To: header (ascii)' '
25dc8dad 208 git config format.to "R E Cipient <rcipient@example.com>" &&
854b5cb4
DL
209 git format-patch --stdout master..side >patch9 &&
210 sed -e "/^\$/q" patch9 >hdrs9 &&
211 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs9
25dc8dad
JS
212'
213
214test_expect_failure 'configuration To: header (rfc822)' '
ae6c098f 215 git config format.to "R. E. Cipient <rcipient@example.com>" &&
854b5cb4
DL
216 git format-patch --stdout master..side >patch9 &&
217 sed -e "/^\$/q" patch9 >hdrs9 &&
218 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs9
25dc8dad
JS
219'
220
221test_expect_failure 'configuration To: header (rfc2047)' '
25dc8dad 222 git config format.to "R Ä Cipient <rcipient@example.com>" &&
854b5cb4
DL
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
ae6c098f
SD
226'
227
cc663d14
TR
228# check_patch <patch>: Verify that <patch> looks like a half-sane
229# patch email to avoid a false positive with !grep
230check_patch () {
231 grep -e "^From:" "$1" &&
232 grep -e "^Date:" "$1" &&
233 grep -e "^Subject:" "$1"
234}
235
6bc6b6c0 236test_expect_success 'format.from=false' '
854b5cb4
DL
237 git -c format.from=false format-patch --stdout master..side >patch &&
238 sed -e "/^\$/q" patch >hdrs &&
6bc6b6c0 239 check_patch patch &&
854b5cb4 240 ! grep "^From: C O Mitter <committer@example.com>\$" hdrs
6bc6b6c0
JT
241'
242
243test_expect_success 'format.from=true' '
854b5cb4
DL
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
6bc6b6c0
JT
248'
249
250test_expect_success 'format.from with address' '
854b5cb4
DL
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
6bc6b6c0
JT
255'
256
257test_expect_success '--no-from overrides format.from' '
854b5cb4
DL
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
6bc6b6c0
JT
262'
263
264test_expect_success '--from overrides format.from' '
854b5cb4
DL
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
6bc6b6c0
JT
269'
270
c4260034 271test_expect_success '--no-to overrides config.to' '
c4260034 272 git config --replace-all format.to \
25dc8dad 273 "R E Cipient <rcipient@example.com>" &&
854b5cb4
DL
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
c4260034
SB
278'
279
280test_expect_success '--no-to and --to replaces config.to' '
c4260034
SB
281 git config --replace-all format.to \
282 "Someone <someone@out.there>" &&
283 git format-patch --no-to --to="Someone Else <else@out.there>" \
854b5cb4
DL
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
c4260034
SB
289'
290
291test_expect_success '--no-cc overrides config.cc' '
c4260034 292 git config --replace-all format.cc \
25dc8dad 293 "C E Cipient <rcipient@example.com>" &&
854b5cb4
DL
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
c4260034
SB
298'
299
688f4f2f 300test_expect_success '--no-add-header overrides config.headers' '
c4260034 301 git config --replace-all format.headers \
25dc8dad 302 "Header1: B E Cipient <rcipient@example.com>" &&
854b5cb4
DL
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
c4260034
SB
307'
308
7d812145 309test_expect_success 'multiple files' '
7d812145
DB
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
4aad08e0
JH
316test_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
7952ea66
JH
324test_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
484cf6c3
TR
332check_threading () {
333 expect="$1" &&
334 shift &&
dd2b6b68 335 git format-patch --stdout "$@" >patch &&
484cf6c3
TR
336 # Prints everything between the Message-ID and In-Reply-To,
337 # and replaces all Message-ID-lookalikes by a sequence number
94221d22 338 perl -ne '
484cf6c3
TR
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;
dd2b6b68 350 ' <patch >actual &&
484cf6c3
TR
351 test_cmp "$expect" actual
352}
353
92014b69 354cat >>expect.no-threading <<EOF
484cf6c3
TR
355---
356---
357---
358EOF
359
360test_expect_success 'no threading' '
7d812145 361 git checkout side &&
484cf6c3 362 check_threading expect.no-threading master
7d812145
DB
363'
364
92014b69 365cat >expect.thread <<EOF
484cf6c3
TR
366---
367Message-Id: <0>
368---
369Message-Id: <1>
370In-Reply-To: <0>
371References: <0>
372---
373Message-Id: <2>
374In-Reply-To: <0>
375References: <0>
376EOF
7d812145 377
484cf6c3
TR
378test_expect_success 'thread' '
379 check_threading expect.thread --thread master
7d812145
DB
380'
381
92014b69 382cat >expect.in-reply-to <<EOF
484cf6c3
TR
383---
384Message-Id: <0>
385In-Reply-To: <1>
386References: <1>
387---
388Message-Id: <2>
389In-Reply-To: <1>
390References: <1>
391---
392Message-Id: <3>
393In-Reply-To: <1>
394References: <1>
395EOF
a5a27c79 396
484cf6c3
TR
397test_expect_success 'thread in-reply-to' '
398 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
399 --thread master
a5a27c79
DB
400'
401
92014b69 402cat >expect.cover-letter <<EOF
484cf6c3
TR
403---
404Message-Id: <0>
405---
406Message-Id: <1>
407In-Reply-To: <0>
408References: <0>
409---
410Message-Id: <2>
411In-Reply-To: <0>
412References: <0>
413---
414Message-Id: <3>
415In-Reply-To: <0>
416References: <0>
417EOF
a5a27c79 418
484cf6c3
TR
419test_expect_success 'thread cover-letter' '
420 check_threading expect.cover-letter --cover-letter --thread master
421'
422
92014b69 423cat >expect.cl-irt <<EOF
484cf6c3
TR
424---
425Message-Id: <0>
426In-Reply-To: <1>
427References: <1>
428---
429Message-Id: <2>
2175c10d 430In-Reply-To: <0>
484cf6c3 431References: <1>
2175c10d 432 <0>
484cf6c3
TR
433---
434Message-Id: <3>
2175c10d 435In-Reply-To: <0>
484cf6c3 436References: <1>
2175c10d 437 <0>
484cf6c3
TR
438---
439Message-Id: <4>
2175c10d 440In-Reply-To: <0>
484cf6c3 441References: <1>
2175c10d 442 <0>
484cf6c3
TR
443EOF
444
445test_expect_success 'thread cover-letter in-reply-to' '
446 check_threading expect.cl-irt --cover-letter \
447 --in-reply-to="<test.message>" --thread master
a5a27c79
DB
448'
449
30984ed2
TR
450test_expect_success 'thread explicit shallow' '
451 check_threading expect.cl-irt --cover-letter \
452 --in-reply-to="<test.message>" --thread=shallow master
453'
454
92014b69 455cat >expect.deep <<EOF
30984ed2
TR
456---
457Message-Id: <0>
458---
459Message-Id: <1>
460In-Reply-To: <0>
461References: <0>
462---
463Message-Id: <2>
464In-Reply-To: <1>
465References: <0>
466 <1>
467EOF
468
469test_expect_success 'thread deep' '
470 check_threading expect.deep --thread=deep master
471'
472
92014b69 473cat >expect.deep-irt <<EOF
30984ed2
TR
474---
475Message-Id: <0>
476In-Reply-To: <1>
477References: <1>
478---
479Message-Id: <2>
480In-Reply-To: <0>
481References: <1>
482 <0>
483---
484Message-Id: <3>
485In-Reply-To: <2>
486References: <1>
487 <0>
488 <2>
489EOF
490
491test_expect_success 'thread deep in-reply-to' '
492 check_threading expect.deep-irt --thread=deep \
493 --in-reply-to="<test.message>" master
494'
495
92014b69 496cat >expect.deep-cl <<EOF
30984ed2
TR
497---
498Message-Id: <0>
499---
500Message-Id: <1>
501In-Reply-To: <0>
502References: <0>
503---
504Message-Id: <2>
505In-Reply-To: <1>
506References: <0>
507 <1>
508---
509Message-Id: <3>
510In-Reply-To: <2>
511References: <0>
512 <1>
513 <2>
514EOF
515
516test_expect_success 'thread deep cover-letter' '
517 check_threading expect.deep-cl --cover-letter --thread=deep master
518'
519
92014b69 520cat >expect.deep-cl-irt <<EOF
30984ed2
TR
521---
522Message-Id: <0>
523In-Reply-To: <1>
524References: <1>
525---
526Message-Id: <2>
527In-Reply-To: <0>
528References: <1>
529 <0>
530---
531Message-Id: <3>
532In-Reply-To: <2>
533References: <1>
534 <0>
535 <2>
536---
537Message-Id: <4>
538In-Reply-To: <3>
539References: <1>
540 <0>
541 <2>
542 <3>
543EOF
544
545test_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
550test_expect_success 'thread via config' '
e8107155 551 test_config format.thread true &&
30984ed2
TR
552 check_threading expect.thread master
553'
554
555test_expect_success 'thread deep via config' '
e8107155 556 test_config format.thread deep &&
30984ed2
TR
557 check_threading expect.deep master
558'
559
560test_expect_success 'thread config + override' '
e8107155 561 test_config format.thread deep &&
30984ed2
TR
562 check_threading expect.thread --thread master
563'
564
565test_expect_success 'thread config + --no-thread' '
e8107155 566 test_config format.thread deep &&
30984ed2
TR
567 check_threading expect.no-threading --no-thread master
568'
569
7d812145 570test_expect_success 'excessive subject' '
7d812145
DB
571 rm -rf patches/ &&
572 git checkout side &&
bdee9cd6 573 before=$(git hash-object file) &&
574 before=$(git rev-parse --short $before) &&
7d812145 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 &&
bdee9cd6 576 after=$(git hash-object file) &&
577 after=$(git rev-parse --short $after) &&
7d812145
DB
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
2fe95f49
JH
584test_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
5d02294c 590test_expect_success 'cover-letter inherits diff options' '
5d02294c
JS
591 git mv file foo &&
592 git commit -m foo &&
5404c116 593 git format-patch --no-renames --cover-letter -1 &&
cc663d14 594 check_patch 0000-cover-letter.patch &&
9524cf29 595 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
5d02294c 596 git format-patch --cover-letter -1 -M &&
9524cf29 597 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
5d02294c 598'
859c4fbe 599
92014b69 600cat >expect <<EOF
859c4fbe
JS
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
608EOF
609
610test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
859c4fbe 611 git format-patch --cover-letter -2 &&
c6ec6dad 612 sed -e "1,/A U Thor/d" -e "/^\$/q" 0000-cover-letter.patch >output &&
3af82863 613 test_cmp expect output
859c4fbe
JS
614'
615
92014b69 616cat >expect <<EOF
bdee9cd6 617index $before..$after 100644
68daa64d
JK
618--- a/file
619+++ b/file
620@@ -13,4 +13,20 @@ C
621 10
622 D
623 E
624 F
625+5
626EOF
627
628test_expect_success 'format-patch respects -U' '
68daa64d 629 git format-patch -U4 -2 &&
6dd88832
JN
630 sed -e "1,/^diff/d" -e "/^+5/q" \
631 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
632 >output &&
68daa64d 633 test_cmp expect output
68daa64d
JK
634'
635
92014b69 636cat >expect <<EOF
1d46f2ea
JK
637
638diff --git a/file b/file
bdee9cd6 639index $before..$after 100644
1d46f2ea
JK
640--- a/file
641+++ b/file
642@@ -14,3 +14,19 @@ C
643 D
644 E
645 F
646+5
647EOF
648
649test_expect_success 'format-patch -p suppresses stat' '
1d46f2ea 650 git format-patch -p -2 &&
c6ec6dad 651 sed -e "1,/^\$/d" -e "/^+5/q" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output &&
1d46f2ea 652 test_cmp expect output
1d46f2ea
JK
653'
654
9800a754
JH
655test_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
673test_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
692test_expect_success 'format-patch from a subdirectory (3)' '
9800a754
JH
693 rm -f 0* &&
694 filename=$(
695 rm -rf sub &&
696 mkdir -p sub/dir &&
697 cd sub/dir &&
91c8b825 698 git format-patch -1 -o "$TRASH_DIRECTORY"
9800a754
JH
699 ) &&
700 basename=$(expr "$filename" : ".*/\(.*\)") &&
701 test -f "$basename"
702'
703
f044fe2d 704test_expect_success 'format-patch --in-reply-to' '
92014b69 705 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" >patch8 &&
f044fe2d
SB
706 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
707 grep "^References: <baz@foo.bar>" patch8
708'
709
710test_expect_success 'format-patch --signoff' '
212620fe
JH
711 git format-patch -1 --signoff --stdout >out &&
712 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
713'
714
715test_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 &&
bd1470b8 718 # Three dashes must come after S-o-b
212620fe 719 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
bd1470b8
JH
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"
f044fe2d
SB
724'
725
13cdf780
DL
726test_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
754test_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
92014b69
DL
796echo "fatal: --name-only does not make sense" >expect.name-only
797echo "fatal: --name-status does not make sense" >expect.name-status
798echo "fatal: --check does not make sense" >expect.check
02bc5b03 799
68b2a005 800test_expect_success 'options no longer allowed for format-patch' '
92014b69 801 test_must_fail git format-patch --name-only 2>output &&
68b2a005 802 test_i18ncmp expect.name-only output &&
92014b69 803 test_must_fail git format-patch --name-status 2>output &&
68b2a005 804 test_i18ncmp expect.name-status output &&
92014b69 805 test_must_fail git format-patch --check 2>output &&
cb46c406
DL
806 test_i18ncmp expect.check output
807'
02bc5b03
BG
808
809test_expect_success 'format-patch --numstat should produce a patch' '
92014b69 810 git format-patch --numstat --stdout master..side >output &&
6bd26f58
DL
811 grep "^diff --git a/" output >diff &&
812 test_line_count = 5 diff
cb46c406 813'
02bc5b03 814
7e93d3b9
FC
815test_expect_success 'format-patch -- <path>' '
816 git format-patch master..side -- file 2>error &&
817 ! grep "Use .--" error
818'
819
657ab61e
KB
820test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
821 git format-patch --ignore-if-in-upstream HEAD
822'
823
854b5cb4
DL
824test_expect_success 'get git version' '
825 git_version=$(git --version) &&
826 git_version=${git_version##* }
827'
480871e0
JT
828
829signature() {
830 printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
831}
832
833test_expect_success 'format-patch default signature' '
854b5cb4
DL
834 git format-patch --stdout -1 >patch &&
835 tail -n 3 patch >output &&
480871e0
JT
836 signature >expect &&
837 test_cmp expect output
838'
839
6622d9c7 840test_expect_success 'format-patch --signature' '
854b5cb4
DL
841 git format-patch --stdout --signature="my sig" -1 >patch &&
842 tail -n 3 patch >output &&
480871e0
JT
843 signature "my sig" >expect &&
844 test_cmp expect output
6622d9c7
SB
845'
846
847test_expect_success 'format-patch with format.signature config' '
848 git config format.signature "config sig" &&
849 git format-patch --stdout -1 >output &&
850 grep "config sig" output
851'
852
853test_expect_success 'format-patch --signature overrides format.signature' '
854 git config format.signature "config sig" &&
855 git format-patch --stdout --signature="overrides" -1 >output &&
856 ! grep "config sig" output &&
857 grep "overrides" output
858'
859
860test_expect_success 'format-patch --no-signature ignores format.signature' '
861 git config format.signature "config sig" &&
862 git format-patch --stdout --signature="my sig" --no-signature \
863 -1 >output &&
cc663d14 864 check_patch output &&
6622d9c7
SB
865 ! grep "config sig" output &&
866 ! grep "my sig" output &&
867 ! grep "^-- \$" output
868'
869
870test_expect_success 'format-patch --signature --cover-letter' '
871 git config --unset-all format.signature &&
872 git format-patch --stdout --signature="my sig" --cover-letter \
873 -1 >output &&
6bd26f58
DL
874 grep "my sig" output >sig &&
875 test_line_count = 2 sig
6622d9c7
SB
876'
877
41ccfdd9 878test_expect_success 'format.signature="" suppresses signatures' '
6622d9c7
SB
879 git config format.signature "" &&
880 git format-patch --stdout -1 >output &&
cc663d14 881 check_patch output &&
6622d9c7
SB
882 ! grep "^-- \$" output
883'
884
41ccfdd9 885test_expect_success 'format-patch --no-signature suppresses signatures' '
6622d9c7
SB
886 git config --unset-all format.signature &&
887 git format-patch --stdout --no-signature -1 >output &&
cc663d14 888 check_patch output &&
6622d9c7
SB
889 ! grep "^-- \$" output
890'
891
41ccfdd9 892test_expect_success 'format-patch --signature="" suppresses signatures' '
2fdb5c62 893 git format-patch --stdout --signature="" -1 >output &&
cc663d14 894 check_patch output &&
6622d9c7
SB
895 ! grep "^-- \$" output
896'
897
7022650f
JM
898test_expect_success 'prepare mail-signature input' '
899 cat >mail-signature <<-\EOF
900
901 Test User <test.email@kernel.org>
902 http://git.kernel.org/cgit/git/git.git
903
904 git.kernel.org/?p=git/git.git;a=summary
905
906 EOF
907'
908
909test_expect_success '--signature-file=file works' '
910 git format-patch --stdout --signature-file=mail-signature -1 >output &&
911 check_patch output &&
c6ec6dad 912 sed -e "1,/^-- \$/d" output >actual &&
7022650f
JM
913 {
914 cat mail-signature && echo
915 } >expect &&
916 test_cmp expect actual
917'
918
919test_expect_success 'format.signaturefile works' '
920 test_config format.signaturefile mail-signature &&
921 git format-patch --stdout -1 >output &&
922 check_patch output &&
c6ec6dad 923 sed -e "1,/^-- \$/d" output >actual &&
7022650f
JM
924 {
925 cat mail-signature && echo
926 } >expect &&
927 test_cmp expect actual
928'
929
930test_expect_success '--no-signature suppresses format.signaturefile ' '
931 test_config format.signaturefile mail-signature &&
932 git format-patch --stdout --no-signature -1 >output &&
933 check_patch output &&
934 ! grep "^-- \$" output
935'
936
937test_expect_success '--signature-file overrides format.signaturefile' '
99094a7a 938 cat >other-mail-signature <<-\EOF &&
7022650f
JM
939 Use this other signature instead of mail-signature.
940 EOF
941 test_config format.signaturefile mail-signature &&
942 git format-patch --stdout \
943 --signature-file=other-mail-signature -1 >output &&
944 check_patch output &&
c6ec6dad 945 sed -e "1,/^-- \$/d" output >actual &&
7022650f
JM
946 {
947 cat other-mail-signature && echo
948 } >expect &&
949 test_cmp expect actual
950'
951
952test_expect_success '--signature overrides format.signaturefile' '
953 test_config format.signaturefile mail-signature &&
954 git format-patch --stdout --signature="my sig" -1 >output &&
955 check_patch output &&
956 grep "my sig" output
957'
958
38a94bb6
TRC
959test_expect_success TTY 'format-patch --stdout paginates' '
960 rm -f pager_used &&
512477b1 961 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
38a94bb6
TRC
962 test_path_is_file pager_used
963'
964
965 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
966 rm -f pager_used &&
512477b1
DT
967 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
968 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
38a94bb6
TRC
969 test_path_is_missing pager_used &&
970 test_path_is_missing .git/pager_used
971'
972
a1f6baa5
JK
973test_expect_success 'format-patch handles multi-line subjects' '
974 rm -rf patches/ &&
975 echo content >>file &&
976 for i in one two three; do echo $i; done >msg &&
977 git add file &&
978 git commit -F msg &&
979 git format-patch -o patches -1 &&
980 grep ^Subject: patches/0001-one.patch >actual &&
981 echo "Subject: [PATCH] one two three" >expect &&
982 test_cmp expect actual
983'
984
985test_expect_success 'format-patch handles multi-line encoded subjects' '
986 rm -rf patches/ &&
987 echo content >>file &&
988 for i in en två tre; do echo $i; done >msg &&
989 git add file &&
990 git commit -F msg &&
991 git format-patch -o patches -1 &&
992 grep ^Subject: patches/0001-en.patch >actual &&
993 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
994 test_cmp expect actual
995'
996
997M8="foo bar "
998M64=$M8$M8$M8$M8$M8$M8$M8$M8
999M512=$M64$M64$M64$M64$M64$M64$M64$M64
1000cat >expect <<'EOF'
1001Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
7a76e68a
JS
1002 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1003 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1004 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1005 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
1006 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
1007 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
a1f6baa5 1008EOF
7a76e68a 1009test_expect_success 'format-patch wraps extremely long subject (ascii)' '
a1f6baa5
JK
1010 echo content >>file &&
1011 git add file &&
1012 git commit -m "$M512" &&
1013 git format-patch --stdout -1 >patch &&
c6ec6dad 1014 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
a1f6baa5
JK
1015 test_cmp expect subject
1016'
1017
1018M8="föö bar "
1019M64=$M8$M8$M8$M8$M8$M8$M8$M8
1020M512=$M64$M64$M64$M64$M64$M64$M64$M64
1021cat >expect <<'EOF'
94f6cdf6
JS
1022Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1023 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1024 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1025 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
6cd3c053
KS
1026 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1027 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
94f6cdf6
JS
1028 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1029 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1030 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
6cd3c053
KS
1031 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1032 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
94f6cdf6
JS
1033 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1034 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1035 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
6cd3c053
KS
1036 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1037 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1038 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1039 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1040 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
1041 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
1042 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
1043 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1044 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1045 =?UTF-8?q?bar?=
a1f6baa5 1046EOF
94f6cdf6 1047test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
a1f6baa5
JK
1048 rm -rf patches/ &&
1049 echo content >>file &&
1050 git add file &&
1051 git commit -m "$M512" &&
1052 git format-patch --stdout -1 >patch &&
c6ec6dad 1053 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
a1f6baa5
JK
1054 test_cmp expect subject
1055'
1056
4d03c18a
JK
1057check_author() {
1058 echo content >>file &&
1059 git add file &&
1060 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
1061 git format-patch --stdout -1 >patch &&
c6ec6dad 1062 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
4d03c18a
JK
1063 test_cmp expect actual
1064}
1065
1066cat >expect <<'EOF'
1067From: "Foo B. Bar" <author@example.com>
1068EOF
0fcec2ce 1069test_expect_success 'format-patch quotes dot in from-headers' '
4d03c18a
JK
1070 check_author "Foo B. Bar"
1071'
1072
1073cat >expect <<'EOF'
1074From: "Foo \"The Baz\" Bar" <author@example.com>
1075EOF
0fcec2ce 1076test_expect_success 'format-patch quotes double-quote in from-headers' '
4d03c18a
JK
1077 check_author "Foo \"The Baz\" Bar"
1078'
1079
1080cat >expect <<'EOF'
0fcec2ce 1081From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
4d03c18a 1082EOF
0fcec2ce
JS
1083test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1084 check_author "Föo Bar"
1085'
1086
1087cat >expect <<'EOF'
1088From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1089EOF
41dd00ba 1090test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
4d03c18a
JK
1091 check_author "Föo B. Bar"
1092'
1093
7a76e68a
JS
1094cat >expect <<EOF
1095From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1096 <author@example.com>
1097EOF
1098test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1099 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1100'
1101
1102cat >expect <<'EOF'
1103From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1104 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1105 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1106EOF
1107test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1108 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"
1109'
1110
1111cat >expect <<'EOF'
1112From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1113 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1114 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1115EOF
1116test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1117 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"
1118'
1119
4d03c18a 1120cat >expect <<'EOF'
94f6cdf6
JS
1121From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1122 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1123 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1124 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1125 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1126EOF
1127test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1128 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"
1129'
1130
1131cat >expect <<'EOF'
4d03c18a
JK
1132Subject: header with . in it
1133EOF
1134test_expect_success 'subject lines do not have 822 atom-quoting' '
1135 echo content >>file &&
1136 git add file &&
1137 git commit -m "header with . in it" &&
1138 git format-patch -k -1 --stdout >patch &&
1139 grep ^Subject: patch >actual &&
1140 test_cmp expect actual
1141'
1142
e7af8e49
JK
1143cat >expect <<'EOF'
1144Subject: [PREFIX 1/1] header with . in it
1145EOF
1146test_expect_success 'subject prefixes have space prepended' '
1147 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1148 grep ^Subject: patch >actual &&
1149 test_cmp expect actual
1150'
1151
1152cat >expect <<'EOF'
1153Subject: [1/1] header with . in it
1154EOF
1155test_expect_success 'empty subject prefix does not have extra space' '
1156 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1157 grep ^Subject: patch >actual &&
1158 test_cmp expect actual
1159'
1160
68e83a5b
JT
1161test_expect_success '--rfc' '
1162 cat >expect <<-\EOF &&
1163 Subject: [RFC PATCH 1/1] header with . in it
1164 EOF
1165 git format-patch -n -1 --stdout --rfc >patch &&
1166 grep ^Subject: patch >actual &&
1167 test_cmp expect actual
1168'
1169
a9080475
JK
1170test_expect_success '--from=ident notices bogus ident' '
1171 test_must_fail git format-patch -1 --stdout --from=foo >patch
1172'
1173
1174test_expect_success '--from=ident replaces author' '
1175 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1176 cat >expect <<-\EOF &&
1177 From: Me <me@example.com>
1178
1179 From: A U Thor <author@example.com>
1180
1181 EOF
c6ec6dad 1182 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
a9080475
JK
1183 test_cmp expect patch.head
1184'
1185
1186test_expect_success '--from uses committer ident' '
1187 git format-patch -1 --stdout --from >patch &&
1188 cat >expect <<-\EOF &&
1189 From: C O Mitter <committer@example.com>
1190
1191 From: A U Thor <author@example.com>
1192
1193 EOF
c6ec6dad 1194 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
a9080475
JK
1195 test_cmp expect patch.head
1196'
1197
662cc30c
JK
1198test_expect_success '--from omits redundant in-body header' '
1199 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1200 cat >expect <<-\EOF &&
1201 From: A U Thor <author@example.com>
1202
1203 EOF
c6ec6dad 1204 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
662cc30c
JK
1205 test_cmp expect patch.head
1206'
1207
a9080475 1208test_expect_success 'in-body headers trigger content encoding' '
d2554c72 1209 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
a9080475
JK
1210 test_when_finished "git reset --hard HEAD^" &&
1211 git format-patch -1 --stdout --from >patch &&
1212 cat >expect <<-\EOF &&
1213 From: C O Mitter <committer@example.com>
1214 Content-Type: text/plain; charset=UTF-8
1215
1216 From: éxötìc <author@example.com>
1217
1218 EOF
c6ec6dad 1219 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
a9080475
JK
1220 test_cmp expect patch.head
1221'
1222
79133a66
NTND
1223append_signoff()
1224{
1225 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1226 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1227 sed -n -e "1,/^---$/p" append_signoff.patch |
1228 egrep -n "^Subject|Sign|^$"
1229}
1230
1231test_expect_success 'signoff: commit with no body' '
1232 append_signoff </dev/null >actual &&
460609cb
DL
1233 cat <<-\EOF | sed "s/EOL$//" >expect &&
1234 4:Subject: [PATCH] EOL
1235 8:
1236 9:Signed-off-by: C O Mitter <committer@example.com>
1237 EOF
b562a54c 1238 test_cmp expect actual
79133a66
NTND
1239'
1240
1241test_expect_success 'signoff: commit with only subject' '
1242 echo subject | append_signoff >actual &&
460609cb
DL
1243 cat >expect <<-\EOF &&
1244 4:Subject: [PATCH] subject
1245 8:
1246 9:Signed-off-by: C O Mitter <committer@example.com>
1247 EOF
b562a54c 1248 test_cmp expect actual
79133a66
NTND
1249'
1250
1251test_expect_success 'signoff: commit with only subject that does not end with NL' '
1252 printf subject | append_signoff >actual &&
460609cb
DL
1253 cat >expect <<-\EOF &&
1254 4:Subject: [PATCH] subject
1255 8:
1256 9:Signed-off-by: C O Mitter <committer@example.com>
1257 EOF
b562a54c 1258 test_cmp expect actual
79133a66
NTND
1259'
1260
1261test_expect_success 'signoff: no existing signoffs' '
460609cb
DL
1262 append_signoff <<-\EOF >actual &&
1263 subject
79133a66 1264
460609cb
DL
1265 body
1266 EOF
1267 cat >expect <<-\EOF &&
1268 4:Subject: [PATCH] subject
1269 8:
1270 10:
1271 11:Signed-off-by: C O Mitter <committer@example.com>
1272 EOF
b562a54c 1273 test_cmp expect actual
79133a66
NTND
1274'
1275
1276test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1277 printf "subject\n\nbody" | append_signoff >actual &&
460609cb
DL
1278 cat >expect <<-\EOF &&
1279 4:Subject: [PATCH] subject
1280 8:
1281 10:
1282 11:Signed-off-by: C O Mitter <committer@example.com>
1283 EOF
b562a54c 1284 test_cmp expect actual
79133a66
NTND
1285'
1286
1287test_expect_success 'signoff: some random signoff' '
460609cb
DL
1288 append_signoff <<-\EOF >actual &&
1289 subject
79133a66 1290
460609cb 1291 body
79133a66 1292
460609cb
DL
1293 Signed-off-by: my@house
1294 EOF
1295 cat >expect <<-\EOF &&
1296 4:Subject: [PATCH] subject
1297 8:
1298 10:
1299 11:Signed-off-by: my@house
1300 12:Signed-off-by: C O Mitter <committer@example.com>
1301 EOF
b562a54c 1302 test_cmp expect actual
79133a66
NTND
1303'
1304
959a2623 1305test_expect_success 'signoff: misc conforming footer elements' '
460609cb
DL
1306 append_signoff <<-\EOF >actual &&
1307 subject
959a2623 1308
460609cb 1309 body
959a2623 1310
460609cb
DL
1311 Signed-off-by: my@house
1312 (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1313 Tested-by: Some One <someone@example.com>
1314 Bug: 1234
1315 EOF
1316 cat >expect <<-\EOF &&
1317 4:Subject: [PATCH] subject
1318 8:
1319 10:
1320 11:Signed-off-by: my@house
1321 15:Signed-off-by: C O Mitter <committer@example.com>
1322 EOF
b562a54c 1323 test_cmp expect actual
959a2623
BC
1324'
1325
1326test_expect_success 'signoff: some random signoff-alike' '
460609cb
DL
1327 append_signoff <<-\EOF >actual &&
1328 subject
79133a66 1329
460609cb
DL
1330 body
1331 Fooled-by-me: my@house
1332 EOF
1333 cat >expect <<-\EOF &&
1334 4:Subject: [PATCH] subject
1335 8:
1336 11:
1337 12:Signed-off-by: C O Mitter <committer@example.com>
1338 EOF
b562a54c 1339 test_cmp expect actual
79133a66
NTND
1340'
1341
959a2623 1342test_expect_success 'signoff: not really a signoff' '
460609cb
DL
1343 append_signoff <<-\EOF >actual &&
1344 subject
79133a66 1345
460609cb
DL
1346 I want to mention about Signed-off-by: here.
1347 EOF
1348 cat >expect <<-\EOF &&
1349 4:Subject: [PATCH] subject
1350 8:
1351 9:I want to mention about Signed-off-by: here.
1352 10:
1353 11:Signed-off-by: C O Mitter <committer@example.com>
1354 EOF
b562a54c 1355 test_cmp expect actual
79133a66
NTND
1356'
1357
959a2623 1358test_expect_success 'signoff: not really a signoff (2)' '
460609cb
DL
1359 append_signoff <<-\EOF >actual &&
1360 subject
79133a66 1361
460609cb
DL
1362 My unfortunate
1363 Signed-off-by: example happens to be wrapped here.
1364 EOF
1365 cat >expect <<-\EOF &&
1366 4:Subject: [PATCH] subject
1367 8:
1368 10:Signed-off-by: example happens to be wrapped here.
1369 11:Signed-off-by: C O Mitter <committer@example.com>
1370 EOF
b562a54c 1371 test_cmp expect actual
79133a66
NTND
1372'
1373
959a2623 1374test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
460609cb
DL
1375 append_signoff <<-\EOF >actual &&
1376 subject
79133a66 1377
460609cb
DL
1378 Signed-off-by: my@house
1379 Signed-off-by: your@house
79133a66 1380
460609cb
DL
1381 A lot of houses.
1382 EOF
1383 cat >expect <<-\EOF &&
1384 4:Subject: [PATCH] subject
1385 8:
1386 9:Signed-off-by: my@house
1387 10:Signed-off-by: your@house
1388 11:
1389 13:
1390 14:Signed-off-by: C O Mitter <committer@example.com>
1391 EOF
b562a54c 1392 test_cmp expect actual
79133a66
NTND
1393'
1394
1395test_expect_success 'signoff: the same signoff at the end' '
460609cb
DL
1396 append_signoff <<-\EOF >actual &&
1397 subject
79133a66 1398
460609cb 1399 body
79133a66 1400
460609cb
DL
1401 Signed-off-by: C O Mitter <committer@example.com>
1402 EOF
1403 cat >expect <<-\EOF &&
1404 4:Subject: [PATCH] subject
1405 8:
1406 10:
1407 11:Signed-off-by: C O Mitter <committer@example.com>
1408 EOF
b562a54c 1409 test_cmp expect actual
79133a66
NTND
1410'
1411
1412test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1413 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1414 append_signoff >actual &&
460609cb
DL
1415 cat >expect <<-\EOF &&
1416 4:Subject: [PATCH] subject
1417 8:
1418 9:Signed-off-by: C O Mitter <committer@example.com>
1419 EOF
b562a54c 1420 test_cmp expect actual
79133a66
NTND
1421'
1422
1423test_expect_success 'signoff: the same signoff NOT at the end' '
460609cb
DL
1424 append_signoff <<-\EOF >actual &&
1425 subject
79133a66 1426
460609cb 1427 body
79133a66 1428
460609cb
DL
1429 Signed-off-by: C O Mitter <committer@example.com>
1430 Signed-off-by: my@house
1431 EOF
1432 cat >expect <<-\EOF &&
1433 4:Subject: [PATCH] subject
1434 8:
1435 10:
1436 11:Signed-off-by: C O Mitter <committer@example.com>
1437 12:Signed-off-by: my@house
1438 EOF
b562a54c 1439 test_cmp expect actual
79133a66
NTND
1440'
1441
967dfd4d 1442test_expect_success 'signoff: tolerate garbage in conforming footer' '
460609cb
DL
1443 append_signoff <<-\EOF >actual &&
1444 subject
79133a66 1445
460609cb 1446 body
79133a66 1447
460609cb
DL
1448 Tested-by: my@house
1449 Some Trash
1450 Signed-off-by: C O Mitter <committer@example.com>
1451 EOF
1452 cat >expect <<-\EOF &&
1453 4:Subject: [PATCH] subject
1454 8:
1455 10:
1456 13:Signed-off-by: C O Mitter <committer@example.com>
1457 EOF
b562a54c 1458 test_cmp expect actual
967dfd4d
JT
1459'
1460
1461test_expect_success 'signoff: respect trailer config' '
460609cb
DL
1462 append_signoff <<-\EOF >actual &&
1463 subject
967dfd4d 1464
460609cb
DL
1465 Myfooter: x
1466 Some Trash
1467 EOF
1468 cat >expect <<-\EOF &&
1469 4:Subject: [PATCH] subject
1470 8:
1471 11:
1472 12:Signed-off-by: C O Mitter <committer@example.com>
1473 EOF
b562a54c 1474 test_cmp expect actual &&
967dfd4d
JT
1475
1476 test_config trailer.Myfooter.ifexists add &&
460609cb
DL
1477 append_signoff <<-\EOF >actual &&
1478 subject
967dfd4d 1479
460609cb
DL
1480 Myfooter: x
1481 Some Trash
1482 EOF
1483 cat >expect <<-\EOF &&
1484 4:Subject: [PATCH] subject
1485 8:
1486 11:Signed-off-by: C O Mitter <committer@example.com>
1487 EOF
b562a54c 1488 test_cmp expect actual
79133a66
NTND
1489'
1490
1491test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
460609cb
DL
1492 append_signoff <<-\EOF >actual &&
1493 subject
79133a66 1494
460609cb 1495 body
79133a66 1496
460609cb
DL
1497 Reviewed-id: Noone
1498 Tested-by: my@house
1499 Change-id: Ideadbeef
1500 Signed-off-by: C O Mitter <committer@example.com>
1501 Bug: 1234
1502 EOF
1503 cat >expect <<-\EOF &&
1504 4:Subject: [PATCH] subject
1505 8:
1506 10:
1507 14:Signed-off-by: C O Mitter <committer@example.com>
1508 EOF
b562a54c 1509 test_cmp expect actual
79133a66
NTND
1510'
1511
787570c7
PYH
1512test_expect_success 'format patch ignores color.ui' '
1513 test_unconfig color.ui &&
1514 git format-patch --stdout -1 >expect &&
1515 test_config color.ui always &&
1516 git format-patch --stdout -1 >actual &&
1517 test_cmp expect actual
1518'
1519
bf8e65b3
DL
1520test_expect_success 'cover letter with invalid --cover-from-description and config' '
1521 test_config branch.rebuild-1.description "config subject
1522
1523body" &&
1524 test_must_fail git format-patch --cover-letter --cover-from-description garbage master &&
1525 test_config format.coverFromDescription garbage &&
1526 test_must_fail git format-patch --cover-letter master
1527'
1528
1529test_expect_success 'cover letter with format.coverFromDescription = default' '
1530 test_config branch.rebuild-1.description "config subject
1531
1532body" &&
1533 test_config format.coverFromDescription default &&
1534 git checkout rebuild-1 &&
1535 git format-patch --stdout --cover-letter master >actual &&
1536 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1537 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1538 grep "^config subject$" actual &&
1539 grep "^body$" actual
1540'
1541
1542test_expect_success 'cover letter with --cover-from-description default' '
1543 test_config branch.rebuild-1.description "config subject
1544
1545body" &&
1546 git checkout rebuild-1 &&
1547 git format-patch --stdout --cover-letter --cover-from-description default master >actual &&
1548 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1549 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1550 grep "^config subject$" actual &&
1551 grep "^body$" actual
1552'
1553
1554test_expect_success 'cover letter with format.coverFromDescription = none' '
1555 test_config branch.rebuild-1.description "config subject
1556
1557body" &&
1558 test_config format.coverFromDescription none &&
1559 git checkout rebuild-1 &&
1560 git format-patch --stdout --cover-letter master >actual &&
1561 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1562 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1563 ! grep "^config subject$" actual &&
1564 ! grep "^body$" actual
1565'
1566
1567test_expect_success 'cover letter with --cover-from-description none' '
1568 test_config branch.rebuild-1.description "config subject
1569
1570body" &&
1571 git checkout rebuild-1 &&
1572 git format-patch --stdout --cover-letter --cover-from-description none master >actual &&
1573 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1574 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1575 ! grep "^config subject$" actual &&
1576 ! grep "^body$" actual
1577'
1578
1579test_expect_success 'cover letter with format.coverFromDescription = message' '
1580 test_config branch.rebuild-1.description "config subject
1581
1582body" &&
1583 test_config format.coverFromDescription message &&
1584 git checkout rebuild-1 &&
1585 git format-patch --stdout --cover-letter master >actual &&
1586 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1587 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1588 grep "^config subject$" actual &&
1589 grep "^body$" actual
1590'
1591
1592test_expect_success 'cover letter with --cover-from-description message' '
1593 test_config branch.rebuild-1.description "config subject
1594
1595body" &&
1596 git checkout rebuild-1 &&
1597 git format-patch --stdout --cover-letter --cover-from-description message master >actual &&
1598 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1599 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1600 grep "^config subject$" actual &&
1601 grep "^body$" actual
1602'
1603
1604test_expect_success 'cover letter with format.coverFromDescription = subject' '
1605 test_config branch.rebuild-1.description "config subject
1606
1607body" &&
1608 test_config format.coverFromDescription subject &&
1609 git checkout rebuild-1 &&
1610 git format-patch --stdout --cover-letter master >actual &&
1611 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1612 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1613 ! grep "^config subject$" actual &&
1614 grep "^body$" actual
1615'
1616
1617test_expect_success 'cover letter with --cover-from-description subject' '
1618 test_config branch.rebuild-1.description "config subject
1619
1620body" &&
1621 git checkout rebuild-1 &&
1622 git format-patch --stdout --cover-letter --cover-from-description subject master >actual &&
1623 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1624 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1625 ! grep "^config subject$" actual &&
1626 grep "^body$" actual
1627'
1628
1629test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '
1630 test_config branch.rebuild-1.description "config subject
1631
1632body" &&
1633 test_config format.coverFromDescription auto &&
1634 git checkout rebuild-1 &&
1635 git format-patch --stdout --cover-letter master >actual &&
1636 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1637 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1638 ! grep "^config subject$" actual &&
1639 grep "^body$" actual
1640'
1641
1642test_expect_success 'cover letter with --cover-from-description auto (short subject line)' '
1643 test_config branch.rebuild-1.description "config subject
1644
1645body" &&
1646 git checkout rebuild-1 &&
1647 git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1648 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1649 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1650 ! grep "^config subject$" actual &&
1651 grep "^body$" actual
1652'
1653
1654test_expect_success 'cover letter with format.coverFromDescription = auto (long subject line)' '
1655 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
1656
1657body" &&
1658 test_config format.coverFromDescription auto &&
1659 git checkout rebuild-1 &&
1660 git format-patch --stdout --cover-letter master >actual &&
1661 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1662 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1663 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1664 grep "^body$" actual
1665'
1666
1667test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '
1668 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
1669
1670body" &&
1671 git checkout rebuild-1 &&
1672 git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1673 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1674 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1675 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1676 grep "^body$" actual
1677'
1678
1679test_expect_success 'cover letter with command-line --cover-from-description overrides config' '
1680 test_config branch.rebuild-1.description "config subject
1681
1682body" &&
1683 test_config format.coverFromDescription none &&
1684 git checkout rebuild-1 &&
1685 git format-patch --stdout --cover-letter --cover-from-description subject master >actual &&
1686 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1687 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1688 ! grep "^config subject$" actual &&
1689 grep "^body$" actual
1690'
1691
e216cc48
NTND
1692test_expect_success 'cover letter using branch description (1)' '
1693 git checkout rebuild-1 &&
1694 test_config branch.rebuild-1.description hello &&
1695 git format-patch --stdout --cover-letter master >actual &&
f2e2fa8f 1696 grep hello actual
e216cc48
NTND
1697'
1698
1699test_expect_success 'cover letter using branch description (2)' '
1700 git checkout rebuild-1 &&
1701 test_config branch.rebuild-1.description hello &&
1702 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
f2e2fa8f 1703 grep hello actual
e216cc48
NTND
1704'
1705
1706test_expect_success 'cover letter using branch description (3)' '
1707 git checkout rebuild-1 &&
1708 test_config branch.rebuild-1.description hello &&
1709 git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
f2e2fa8f 1710 grep hello actual
e216cc48
NTND
1711'
1712
20b630aa
NTND
1713test_expect_success 'cover letter using branch description (4)' '
1714 git checkout rebuild-1 &&
1715 test_config branch.rebuild-1.description hello &&
1716 git format-patch --stdout --cover-letter master.. >actual &&
f2e2fa8f 1717 grep hello actual
20b630aa
NTND
1718'
1719
1720test_expect_success 'cover letter using branch description (5)' '
1721 git checkout rebuild-1 &&
1722 test_config branch.rebuild-1.description hello &&
1723 git format-patch --stdout --cover-letter -2 HEAD >actual &&
f2e2fa8f 1724 grep hello actual
20b630aa
NTND
1725'
1726
5ee29aef
NTND
1727test_expect_success 'cover letter using branch description (6)' '
1728 git checkout rebuild-1 &&
1729 test_config branch.rebuild-1.description hello &&
1730 git format-patch --stdout --cover-letter -2 >actual &&
f2e2fa8f 1731 grep hello actual
5ee29aef
NTND
1732'
1733
80d35ca0
FC
1734test_expect_success 'cover letter with nothing' '
1735 git format-patch --stdout --cover-letter >actual &&
1736 test_line_count = 0 actual
1737'
1738
2a4c2607
FC
1739test_expect_success 'cover letter auto' '
1740 mkdir -p tmp &&
1741 test_when_finished "rm -rf tmp;
1742 git config --unset format.coverletter" &&
1743
1744 git config format.coverletter auto &&
1745 git format-patch -o tmp -1 >list &&
1746 test_line_count = 1 list &&
1747 git format-patch -o tmp -2 >list &&
1748 test_line_count = 3 list
1749'
1750
1751test_expect_success 'cover letter auto user override' '
1752 mkdir -p tmp &&
1753 test_when_finished "rm -rf tmp;
1754 git config --unset format.coverletter" &&
1755
1756 git config format.coverletter auto &&
1757 git format-patch -o tmp --cover-letter -1 >list &&
1758 test_line_count = 2 list &&
1759 git format-patch -o tmp --cover-letter -2 >list &&
1760 test_line_count = 3 list &&
1761 git format-patch -o tmp --no-cover-letter -1 >list &&
1762 test_line_count = 1 list &&
1763 git format-patch -o tmp --no-cover-letter -2 >list &&
1764 test_line_count = 2 list
1765'
1766
3a30aa17 1767test_expect_success 'format-patch --zero-commit' '
1768 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1769 grep "^From " patch2 | sort | uniq >actual &&
8125a58b 1770 echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
3a30aa17 1771 test_cmp expect actual
1772'
1773
06dfc9eb 1774test_expect_success 'From line has expected format' '
1775 git format-patch --stdout v2..v1 >patch2 &&
1776 grep "^From " patch2 >from &&
2ece6ad2 1777 grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
06dfc9eb 1778 test_cmp from filtered
1779'
1780
edefc318
BW
1781test_expect_success 'format-patch -o with no leading directories' '
1782 rm -fr patches &&
1783 git format-patch -o patches master..side &&
1784 count=$(git rev-list --count master..side) &&
1785 ls patches >list &&
1786 test_line_count = $count list
1787'
1788
1789test_expect_success 'format-patch -o with leading existing directories' '
19c29e53
BW
1790 rm -rf existing-dir &&
1791 mkdir existing-dir &&
1792 git format-patch -o existing-dir/patches master..side &&
edefc318 1793 count=$(git rev-list --count master..side) &&
19c29e53 1794 ls existing-dir/patches >list &&
edefc318
BW
1795 test_line_count = $count list
1796'
1797
1798test_expect_success 'format-patch -o with leading non-existing directories' '
19c29e53
BW
1799 rm -rf non-existing-dir &&
1800 git format-patch -o non-existing-dir/patches master..side &&
edefc318 1801 count=$(git rev-list --count master..side) &&
19c29e53
BW
1802 test_path_is_dir non-existing-dir &&
1803 ls non-existing-dir/patches >list &&
edefc318
BW
1804 test_line_count = $count list
1805'
1806
bc6bf2d7
AK
1807test_expect_success 'format-patch format.outputDirectory option' '
1808 test_config format.outputDirectory patches &&
1809 rm -fr patches &&
1810 git format-patch master..side &&
756fb0de
DL
1811 count=$(git rev-list --count master..side) &&
1812 ls patches >list &&
1813 test_line_count = $count list
bc6bf2d7
AK
1814'
1815
1816test_expect_success 'format-patch -o overrides format.outputDirectory' '
1817 test_config format.outputDirectory patches &&
1818 rm -fr patches patchset &&
1819 git format-patch master..side -o patchset &&
1820 test_path_is_missing patches &&
1821 test_path_is_dir patchset
1822'
1823
fa2ab86d 1824test_expect_success 'format-patch --base' '
6f93d261 1825 git checkout patchid &&
854b5cb4
DL
1826
1827 git format-patch --stdout --base=HEAD~3 -1 >patch &&
1828 tail -n 7 patch >actual1 &&
1829
1830 git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
1831 tail -n 7 patch >actual2 &&
1832
b562a54c 1833 echo >expect &&
854b5cb4
DL
1834 git rev-parse HEAD~3 >commit-id-base &&
1835 echo "base-commit: $(cat commit-id-base)" >>expect &&
1836
1837 git show --patch HEAD~2 >patch &&
1838 git patch-id --stable <patch >patch.id.raw &&
1839 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
1840
1841 git show --patch HEAD~1 >patch &&
1842 git patch-id --stable <patch >patch.id.raw &&
1843 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
1844
92014b69 1845 signature >>expect &&
b562a54c
DL
1846 test_cmp expect actual1 &&
1847 test_cmp expect actual2 &&
854b5cb4 1848
6f93d261 1849 echo >fail &&
854b5cb4
DL
1850 echo "base-commit: $(cat commit-id-base)" >>fail &&
1851
1852 git show --patch HEAD~2 >patch &&
1853 git patch-id --unstable <patch >patch.id.raw &&
1854 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
1855
1856 git show --patch HEAD~1 >patch &&
1857 git patch-id --unstable <patch >patch.id.raw &&
1858 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
1859
92014b69 1860 signature >>fail &&
6f93d261
SB
1861 ! test_cmp fail actual1 &&
1862 ! test_cmp fail actual2
fa2ab86d
XY
1863'
1864
1865test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1866 test_must_fail git format-patch --base=HEAD -2 &&
1867 test_must_fail git format-patch --base=HEAD~1 -2 &&
1868 git format-patch --stdout --base=HEAD~2 -2 >patch &&
1869 grep "^base-commit:" patch >actual &&
854b5cb4
DL
1870 git rev-parse HEAD~2 >commit-id-base &&
1871 echo "base-commit: $(cat commit-id-base)" >expect &&
b562a54c 1872 test_cmp expect actual
fa2ab86d
XY
1873'
1874
1875test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1876 # For history as below:
1877 #
1878 # ---Q---P---Z---Y---*---X
1879 # \ /
1880 # ------------W
1881 #
1882 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1883 git checkout -b topic1 master &&
1884 git rev-parse HEAD >commit-id-base &&
1885 test_commit P &&
1886 git rev-parse HEAD >commit-id-P &&
1887 test_commit Z &&
1888 git rev-parse HEAD >commit-id-Z &&
1889 test_commit Y &&
1890 git checkout -b topic2 master &&
1891 test_commit W &&
1892 git merge topic1 &&
1893 test_commit X &&
1894 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1895 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1896 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1897 grep "^base-commit:" patch >actual &&
b562a54c
DL
1898 echo "base-commit: $(cat commit-id-base)" >expect &&
1899 test_cmp expect actual
fa2ab86d
XY
1900'
1901
3de66517
XY
1902test_expect_success 'format-patch --base=auto' '
1903 git checkout -b upstream master &&
1904 git checkout -b local upstream &&
1905 git branch --set-upstream-to=upstream &&
1906 test_commit N1 &&
1907 test_commit N2 &&
1908 git format-patch --stdout --base=auto -2 >patch &&
1909 grep "^base-commit:" patch >actual &&
854b5cb4
DL
1910 git rev-parse upstream >commit-id-base &&
1911 echo "base-commit: $(cat commit-id-base)" >expect &&
b562a54c 1912 test_cmp expect actual
3de66517
XY
1913'
1914
1915test_expect_success 'format-patch errors out when history involves criss-cross' '
1916 # setup criss-cross history
1917 #
1918 # B---M1---D
1919 # / \ /
1920 # A X
1921 # \ / \
1922 # C---M2---E
1923 #
1924 git checkout master &&
1925 test_commit A &&
1926 git checkout -b xb master &&
1927 test_commit B &&
1928 git checkout -b xc master &&
1929 test_commit C &&
1930 git checkout -b xbc xb -- &&
1931 git merge xc &&
1932 git checkout -b xcb xc -- &&
1933 git branch --set-upstream-to=xbc &&
1934 git merge xb &&
1935 git checkout xbc &&
1936 test_commit D &&
1937 git checkout xcb &&
1938 test_commit E &&
1939 test_must_fail git format-patch --base=auto -1
1940'
1941
bb52995f
XY
1942test_expect_success 'format-patch format.useAutoBaseoption' '
1943 test_when_finished "git config --unset format.useAutoBase" &&
1944 git checkout local &&
1945 git config format.useAutoBase true &&
1946 git format-patch --stdout -1 >patch &&
1947 grep "^base-commit:" patch >actual &&
854b5cb4
DL
1948 git rev-parse upstream >commit-id-base &&
1949 echo "base-commit: $(cat commit-id-base)" >expect &&
b562a54c 1950 test_cmp expect actual
bb52995f
XY
1951'
1952
1953test_expect_success 'format-patch --base overrides format.useAutoBase' '
1954 test_when_finished "git config --unset format.useAutoBase" &&
1955 git config format.useAutoBase true &&
1956 git format-patch --stdout --base=HEAD~1 -1 >patch &&
1957 grep "^base-commit:" patch >actual &&
854b5cb4
DL
1958 git rev-parse HEAD~1 >commit-id-base &&
1959 echo "base-commit: $(cat commit-id-base)" >expect &&
b562a54c 1960 test_cmp expect actual
bb52995f
XY
1961'
1962
480871e0
JT
1963test_expect_success 'format-patch --base with --attach' '
1964 git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
1965 sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
1966 patch >actual &&
1967 test_write_lines 1 2 >expect &&
1968 test_cmp expect actual
1969'
50cd54ef 1970test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
1971 test_when_finished "rm -fr patches" &&
1972 git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
1973 ! egrep "^--+mimemime" patches/0000*.patch &&
1974 egrep "^--+mimemime$" patches/0001*.patch >output &&
1975 test_line_count = 2 output &&
1976 egrep "^--+mimemime--$" patches/0001*.patch >output &&
1977 test_line_count = 1 output
1978'
480871e0 1979
9f23e040
EW
1980test_expect_success 'format-patch --pretty=mboxrd' '
1981 sp=" " &&
1982 cat >msg <<-INPUT_END &&
1983 mboxrd should escape the body
1984
1985 From could trip up a loose mbox parser
1986 >From extra escape for reversibility
1987 >>From extra escape for reversibility 2
1988 from lower case not escaped
1989 Fromm bad speling not escaped
1990 From with leading space not escaped
1991
1992 F
1993 From
1994 From$sp
1995 From $sp
1996 From $sp
1997 INPUT_END
1998
1999 cat >expect <<-INPUT_END &&
2000 >From could trip up a loose mbox parser
2001 >>From extra escape for reversibility
2002 >>>From extra escape for reversibility 2
2003 from lower case not escaped
2004 Fromm bad speling not escaped
2005 From with leading space not escaped
2006
2007 F
2008 From
2009 From
2010 From
2011 From
2012 INPUT_END
2013
2014 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2015 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
2016 git grep -h --no-index -A11 \
2017 "^>From could trip up a loose mbox parser" patch >actual &&
2018 test_cmp expect actual
2019'
2020
126facf8
ES
2021test_expect_success 'interdiff: setup' '
2022 git checkout -b boop master &&
2023 test_commit fnorp blorp &&
2024 test_commit fleep blorp
2025'
2026
2027test_expect_success 'interdiff: cover-letter' '
2028 sed "y/q/ /" >expect <<-\EOF &&
2029 +fleep
2030 --q
2031 EOF
2032 git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2033 test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
ee6cbf71 2034 test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
c6ec6dad 2035 sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
126facf8
ES
2036 test_cmp expect actual
2037'
2038
5ac290f9
ES
2039test_expect_success 'interdiff: reroll-count' '
2040 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2041 test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2042'
2043
ee6cbf71
ES
2044test_expect_success 'interdiff: solo-patch' '
2045 cat >expect <<-\EOF &&
2046 +fleep
2047
2048 EOF
2049 git format-patch --interdiff=boop~2 -1 boop &&
2050 test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
c6ec6dad 2051 sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual &&
ee6cbf71
ES
2052 test_cmp expect actual
2053'
2054
ece3c67f 2055test_done