]> git.ipfire.org Git - thirdparty/git.git/blame - t/t4014-format-patch.sh
The sixth batch
[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" '
08dc2606 84 git checkout -b feature master &&
2c642ed8
RR
85 echo "Another line" >>file &&
86 test_tick &&
08dc2606 87 git commit -am "Feature branch change #1" &&
2c642ed8
RR
88 echo "Yet another line" >>file &&
89 test_tick &&
08dc2606 90 git commit -am "Feature branch change #2" &&
2c642ed8
RR
91 git checkout -b merger master &&
92 test_tick &&
08dc2606 93 git merge --no-ff feature &&
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
8164c961
DL
796test_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
92014b69
DL
828echo "fatal: --name-only does not make sense" >expect.name-only
829echo "fatal: --name-status does not make sense" >expect.name-status
830echo "fatal: --check does not make sense" >expect.check
02bc5b03 831
68b2a005 832test_expect_success 'options no longer allowed for format-patch' '
92014b69 833 test_must_fail git format-patch --name-only 2>output &&
68b2a005 834 test_i18ncmp expect.name-only output &&
92014b69 835 test_must_fail git format-patch --name-status 2>output &&
68b2a005 836 test_i18ncmp expect.name-status output &&
92014b69 837 test_must_fail git format-patch --check 2>output &&
cb46c406
DL
838 test_i18ncmp expect.check output
839'
02bc5b03
BG
840
841test_expect_success 'format-patch --numstat should produce a patch' '
92014b69 842 git format-patch --numstat --stdout master..side >output &&
6bd26f58
DL
843 grep "^diff --git a/" output >diff &&
844 test_line_count = 5 diff
cb46c406 845'
02bc5b03 846
7e93d3b9
FC
847test_expect_success 'format-patch -- <path>' '
848 git format-patch master..side -- file 2>error &&
849 ! grep "Use .--" error
850'
851
657ab61e
KB
852test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
853 git format-patch --ignore-if-in-upstream HEAD
854'
855
854b5cb4
DL
856test_expect_success 'get git version' '
857 git_version=$(git --version) &&
858 git_version=${git_version##* }
859'
480871e0
JT
860
861signature() {
862 printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
863}
864
865test_expect_success 'format-patch default signature' '
854b5cb4
DL
866 git format-patch --stdout -1 >patch &&
867 tail -n 3 patch >output &&
480871e0
JT
868 signature >expect &&
869 test_cmp expect output
870'
871
6622d9c7 872test_expect_success 'format-patch --signature' '
854b5cb4
DL
873 git format-patch --stdout --signature="my sig" -1 >patch &&
874 tail -n 3 patch >output &&
480871e0
JT
875 signature "my sig" >expect &&
876 test_cmp expect output
6622d9c7
SB
877'
878
879test_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
885test_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
892test_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 &&
cc663d14 896 check_patch output &&
6622d9c7
SB
897 ! grep "config sig" output &&
898 ! grep "my sig" output &&
899 ! grep "^-- \$" output
900'
901
902test_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 &&
6bd26f58
DL
906 grep "my sig" output >sig &&
907 test_line_count = 2 sig
6622d9c7
SB
908'
909
41ccfdd9 910test_expect_success 'format.signature="" suppresses signatures' '
6622d9c7
SB
911 git config format.signature "" &&
912 git format-patch --stdout -1 >output &&
cc663d14 913 check_patch output &&
6622d9c7
SB
914 ! grep "^-- \$" output
915'
916
41ccfdd9 917test_expect_success 'format-patch --no-signature suppresses signatures' '
6622d9c7
SB
918 git config --unset-all format.signature &&
919 git format-patch --stdout --no-signature -1 >output &&
cc663d14 920 check_patch output &&
6622d9c7
SB
921 ! grep "^-- \$" output
922'
923
41ccfdd9 924test_expect_success 'format-patch --signature="" suppresses signatures' '
2fdb5c62 925 git format-patch --stdout --signature="" -1 >output &&
cc663d14 926 check_patch output &&
6622d9c7
SB
927 ! grep "^-- \$" output
928'
929
7022650f
JM
930test_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
941test_expect_success '--signature-file=file works' '
942 git format-patch --stdout --signature-file=mail-signature -1 >output &&
943 check_patch output &&
c6ec6dad 944 sed -e "1,/^-- \$/d" output >actual &&
7022650f
JM
945 {
946 cat mail-signature && echo
947 } >expect &&
948 test_cmp expect actual
949'
950
951test_expect_success 'format.signaturefile works' '
952 test_config format.signaturefile mail-signature &&
953 git format-patch --stdout -1 >output &&
954 check_patch output &&
c6ec6dad 955 sed -e "1,/^-- \$/d" output >actual &&
7022650f
JM
956 {
957 cat mail-signature && echo
958 } >expect &&
959 test_cmp expect actual
960'
961
962test_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
969test_expect_success '--signature-file overrides format.signaturefile' '
99094a7a 970 cat >other-mail-signature <<-\EOF &&
7022650f
JM
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 &&
c6ec6dad 977 sed -e "1,/^-- \$/d" output >actual &&
7022650f
JM
978 {
979 cat other-mail-signature && echo
980 } >expect &&
981 test_cmp expect actual
982'
983
984test_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
38a94bb6
TRC
991test_expect_success TTY 'format-patch --stdout paginates' '
992 rm -f pager_used &&
512477b1 993 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
38a94bb6
TRC
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 &&
512477b1
DT
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 &&
38a94bb6
TRC
1001 test_path_is_missing pager_used &&
1002 test_path_is_missing .git/pager_used
1003'
1004
a1f6baa5
JK
1005test_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
1017test_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
1029M8="foo bar "
1030M64=$M8$M8$M8$M8$M8$M8$M8$M8
1031M512=$M64$M64$M64$M64$M64$M64$M64$M64
1032cat >expect <<'EOF'
1033Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
7a76e68a
JS
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
a1f6baa5 1040EOF
7a76e68a 1041test_expect_success 'format-patch wraps extremely long subject (ascii)' '
a1f6baa5
JK
1042 echo content >>file &&
1043 git add file &&
1044 git commit -m "$M512" &&
1045 git format-patch --stdout -1 >patch &&
c6ec6dad 1046 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
a1f6baa5
JK
1047 test_cmp expect subject
1048'
1049
1050M8="föö bar "
1051M64=$M8$M8$M8$M8$M8$M8$M8$M8
1052M512=$M64$M64$M64$M64$M64$M64$M64$M64
1053cat >expect <<'EOF'
94f6cdf6
JS
1054Subject: [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?=
6cd3c053
KS
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?=
94f6cdf6
JS
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?=
6cd3c053
KS
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?=
94f6cdf6
JS
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?=
6cd3c053
KS
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?=
a1f6baa5 1078EOF
94f6cdf6 1079test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
a1f6baa5
JK
1080 rm -rf patches/ &&
1081 echo content >>file &&
1082 git add file &&
1083 git commit -m "$M512" &&
1084 git format-patch --stdout -1 >patch &&
c6ec6dad 1085 sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject &&
a1f6baa5
JK
1086 test_cmp expect subject
1087'
1088
4d03c18a
JK
1089check_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 &&
c6ec6dad 1094 sed -n "/^From: /p; /^ /p; /^$/q" patch >actual &&
4d03c18a
JK
1095 test_cmp expect actual
1096}
1097
1098cat >expect <<'EOF'
1099From: "Foo B. Bar" <author@example.com>
1100EOF
0fcec2ce 1101test_expect_success 'format-patch quotes dot in from-headers' '
4d03c18a
JK
1102 check_author "Foo B. Bar"
1103'
1104
1105cat >expect <<'EOF'
1106From: "Foo \"The Baz\" Bar" <author@example.com>
1107EOF
0fcec2ce 1108test_expect_success 'format-patch quotes double-quote in from-headers' '
4d03c18a
JK
1109 check_author "Foo \"The Baz\" Bar"
1110'
1111
1112cat >expect <<'EOF'
0fcec2ce 1113From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
4d03c18a 1114EOF
0fcec2ce
JS
1115test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1116 check_author "Föo Bar"
1117'
1118
1119cat >expect <<'EOF'
1120From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1121EOF
41dd00ba 1122test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
4d03c18a
JK
1123 check_author "Föo B. Bar"
1124'
1125
7a76e68a
JS
1126cat >expect <<EOF
1127From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1128 <author@example.com>
1129EOF
1130test_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
1134cat >expect <<'EOF'
1135From: 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>
1138EOF
1139test_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
1143cat >expect <<'EOF'
1144From: "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>
1147EOF
1148test_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
4d03c18a 1152cat >expect <<'EOF'
94f6cdf6
JS
1153From: =?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>
1158EOF
1159test_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
19d097e3
EB
1163cat >expect <<'EOF'
1164From: 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>
1167EOF
1168test_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
1178cat >expect <<'EOF'
1179Subject: [PATCH] Foö
1180EOF
1181test_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
1190cat >expect <<'EOF'
1191Subject: [PATCH] Foö
1192EOF
1193test_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
1203cat >expect <<'EOF'
1204Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?=
1205EOF
1206test_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
94f6cdf6 1216cat >expect <<'EOF'
4d03c18a
JK
1217Subject: header with . in it
1218EOF
1219test_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
e7af8e49
JK
1228cat >expect <<'EOF'
1229Subject: [PREFIX 1/1] header with . in it
1230EOF
1231test_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
1237cat >expect <<'EOF'
1238Subject: [1/1] header with . in it
1239EOF
1240test_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
68e83a5b
JT
1246test_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
a9080475
JK
1255test_expect_success '--from=ident notices bogus ident' '
1256 test_must_fail git format-patch -1 --stdout --from=foo >patch
1257'
1258
1259test_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
c6ec6dad 1267 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
a9080475
JK
1268 test_cmp expect patch.head
1269'
1270
1271test_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
c6ec6dad 1279 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
a9080475
JK
1280 test_cmp expect patch.head
1281'
1282
662cc30c
JK
1283test_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
c6ec6dad 1289 sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head &&
662cc30c
JK
1290 test_cmp expect patch.head
1291'
1292
a9080475 1293test_expect_success 'in-body headers trigger content encoding' '
d2554c72 1294 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
a9080475
JK
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
c6ec6dad 1304 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head &&
a9080475
JK
1305 test_cmp expect patch.head
1306'
1307
79133a66
NTND
1308append_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
1316test_expect_success 'signoff: commit with no body' '
1317 append_signoff </dev/null >actual &&
460609cb
DL
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
b562a54c 1323 test_cmp expect actual
79133a66
NTND
1324'
1325
1326test_expect_success 'signoff: commit with only subject' '
1327 echo subject | append_signoff >actual &&
460609cb
DL
1328 cat >expect <<-\EOF &&
1329 4:Subject: [PATCH] subject
1330 8:
1331 9:Signed-off-by: C O Mitter <committer@example.com>
1332 EOF
b562a54c 1333 test_cmp expect actual
79133a66
NTND
1334'
1335
1336test_expect_success 'signoff: commit with only subject that does not end with NL' '
1337 printf subject | append_signoff >actual &&
460609cb
DL
1338 cat >expect <<-\EOF &&
1339 4:Subject: [PATCH] subject
1340 8:
1341 9:Signed-off-by: C O Mitter <committer@example.com>
1342 EOF
b562a54c 1343 test_cmp expect actual
79133a66
NTND
1344'
1345
1346test_expect_success 'signoff: no existing signoffs' '
460609cb
DL
1347 append_signoff <<-\EOF >actual &&
1348 subject
79133a66 1349
460609cb
DL
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
b562a54c 1358 test_cmp expect actual
79133a66
NTND
1359'
1360
1361test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1362 printf "subject\n\nbody" | append_signoff >actual &&
460609cb
DL
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
b562a54c 1369 test_cmp expect actual
79133a66
NTND
1370'
1371
1372test_expect_success 'signoff: some random signoff' '
460609cb
DL
1373 append_signoff <<-\EOF >actual &&
1374 subject
79133a66 1375
460609cb 1376 body
79133a66 1377
460609cb
DL
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
b562a54c 1387 test_cmp expect actual
79133a66
NTND
1388'
1389
959a2623 1390test_expect_success 'signoff: misc conforming footer elements' '
460609cb
DL
1391 append_signoff <<-\EOF >actual &&
1392 subject
959a2623 1393
460609cb 1394 body
959a2623 1395
460609cb
DL
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
b562a54c 1408 test_cmp expect actual
959a2623
BC
1409'
1410
1411test_expect_success 'signoff: some random signoff-alike' '
460609cb
DL
1412 append_signoff <<-\EOF >actual &&
1413 subject
79133a66 1414
460609cb
DL
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
b562a54c 1424 test_cmp expect actual
79133a66
NTND
1425'
1426
959a2623 1427test_expect_success 'signoff: not really a signoff' '
460609cb
DL
1428 append_signoff <<-\EOF >actual &&
1429 subject
79133a66 1430
460609cb
DL
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
b562a54c 1440 test_cmp expect actual
79133a66
NTND
1441'
1442
959a2623 1443test_expect_success 'signoff: not really a signoff (2)' '
460609cb
DL
1444 append_signoff <<-\EOF >actual &&
1445 subject
79133a66 1446
460609cb
DL
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
b562a54c 1456 test_cmp expect actual
79133a66
NTND
1457'
1458
959a2623 1459test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
460609cb
DL
1460 append_signoff <<-\EOF >actual &&
1461 subject
79133a66 1462
460609cb
DL
1463 Signed-off-by: my@house
1464 Signed-off-by: your@house
79133a66 1465
460609cb
DL
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
b562a54c 1477 test_cmp expect actual
79133a66
NTND
1478'
1479
1480test_expect_success 'signoff: the same signoff at the end' '
460609cb
DL
1481 append_signoff <<-\EOF >actual &&
1482 subject
79133a66 1483
460609cb 1484 body
79133a66 1485
460609cb
DL
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
b562a54c 1494 test_cmp expect actual
79133a66
NTND
1495'
1496
1497test_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 &&
460609cb
DL
1500 cat >expect <<-\EOF &&
1501 4:Subject: [PATCH] subject
1502 8:
1503 9:Signed-off-by: C O Mitter <committer@example.com>
1504 EOF
b562a54c 1505 test_cmp expect actual
79133a66
NTND
1506'
1507
1508test_expect_success 'signoff: the same signoff NOT at the end' '
460609cb
DL
1509 append_signoff <<-\EOF >actual &&
1510 subject
79133a66 1511
460609cb 1512 body
79133a66 1513
460609cb
DL
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
b562a54c 1524 test_cmp expect actual
79133a66
NTND
1525'
1526
967dfd4d 1527test_expect_success 'signoff: tolerate garbage in conforming footer' '
460609cb
DL
1528 append_signoff <<-\EOF >actual &&
1529 subject
79133a66 1530
460609cb 1531 body
79133a66 1532
460609cb
DL
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
b562a54c 1543 test_cmp expect actual
967dfd4d
JT
1544'
1545
1546test_expect_success 'signoff: respect trailer config' '
460609cb
DL
1547 append_signoff <<-\EOF >actual &&
1548 subject
967dfd4d 1549
460609cb
DL
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
b562a54c 1559 test_cmp expect actual &&
967dfd4d
JT
1560
1561 test_config trailer.Myfooter.ifexists add &&
460609cb
DL
1562 append_signoff <<-\EOF >actual &&
1563 subject
967dfd4d 1564
460609cb
DL
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
b562a54c 1573 test_cmp expect actual
79133a66
NTND
1574'
1575
1576test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
460609cb
DL
1577 append_signoff <<-\EOF >actual &&
1578 subject
79133a66 1579
460609cb 1580 body
79133a66 1581
460609cb
DL
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
b562a54c 1594 test_cmp expect actual
79133a66
NTND
1595'
1596
787570c7
PYH
1597test_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
c28ded83
LA
1605test_expect_success 'format patch respects diff.relative' '
1606 rm -rf subdir &&
1607 mkdir subdir &&
1608 echo other content >subdir/file2 &&
1609 git add subdir/file2 &&
1610 git commit -F msg &&
1611 test_unconfig diff.relative &&
1612 git format-patch --relative=subdir --stdout -1 >expect &&
1613 test_config diff.relative true &&
1614 git -C subdir format-patch --stdout -1 >actual &&
1615 test_cmp expect actual
1616'
1617
bf8e65b3
DL
1618test_expect_success 'cover letter with invalid --cover-from-description and config' '
1619 test_config branch.rebuild-1.description "config subject
1620
1621body" &&
1622 test_must_fail git format-patch --cover-letter --cover-from-description garbage master &&
1623 test_config format.coverFromDescription garbage &&
1624 test_must_fail git format-patch --cover-letter master
1625'
1626
1627test_expect_success 'cover letter with format.coverFromDescription = default' '
1628 test_config branch.rebuild-1.description "config subject
1629
1630body" &&
1631 test_config format.coverFromDescription default &&
1632 git checkout rebuild-1 &&
1633 git format-patch --stdout --cover-letter master >actual &&
1634 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1635 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1636 grep "^config subject$" actual &&
1637 grep "^body$" actual
1638'
1639
1640test_expect_success 'cover letter with --cover-from-description default' '
1641 test_config branch.rebuild-1.description "config subject
1642
1643body" &&
1644 git checkout rebuild-1 &&
1645 git format-patch --stdout --cover-letter --cover-from-description default 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
1652test_expect_success 'cover letter with format.coverFromDescription = none' '
1653 test_config branch.rebuild-1.description "config subject
1654
1655body" &&
1656 test_config format.coverFromDescription none &&
1657 git checkout rebuild-1 &&
1658 git format-patch --stdout --cover-letter master >actual &&
1659 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1660 grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1661 ! grep "^config subject$" actual &&
1662 ! grep "^body$" actual
1663'
1664
1665test_expect_success 'cover letter with --cover-from-description none' '
1666 test_config branch.rebuild-1.description "config subject
1667
1668body" &&
1669 git checkout rebuild-1 &&
1670 git format-patch --stdout --cover-letter --cover-from-description none 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
1677test_expect_success 'cover letter with format.coverFromDescription = message' '
1678 test_config branch.rebuild-1.description "config subject
1679
1680body" &&
1681 test_config format.coverFromDescription message &&
1682 git checkout rebuild-1 &&
1683 git format-patch --stdout --cover-letter master >actual &&
1684 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1685 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1686 grep "^config subject$" actual &&
1687 grep "^body$" actual
1688'
1689
1690test_expect_success 'cover letter with --cover-from-description message' '
1691 test_config branch.rebuild-1.description "config subject
1692
1693body" &&
1694 git checkout rebuild-1 &&
1695 git format-patch --stdout --cover-letter --cover-from-description message master >actual &&
1696 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1697 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1698 grep "^config subject$" actual &&
1699 grep "^body$" actual
1700'
1701
1702test_expect_success 'cover letter with format.coverFromDescription = subject' '
1703 test_config branch.rebuild-1.description "config subject
1704
1705body" &&
1706 test_config format.coverFromDescription subject &&
1707 git checkout rebuild-1 &&
1708 git format-patch --stdout --cover-letter master >actual &&
1709 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1710 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1711 ! grep "^config subject$" actual &&
1712 grep "^body$" actual
1713'
1714
1715test_expect_success 'cover letter with --cover-from-description subject' '
1716 test_config branch.rebuild-1.description "config subject
1717
1718body" &&
1719 git checkout rebuild-1 &&
1720 git format-patch --stdout --cover-letter --cover-from-description subject 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
1727test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' '
1728 test_config branch.rebuild-1.description "config subject
1729
1730body" &&
1731 test_config format.coverFromDescription auto &&
1732 git checkout rebuild-1 &&
1733 git format-patch --stdout --cover-letter master >actual &&
1734 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1735 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1736 ! grep "^config subject$" actual &&
1737 grep "^body$" actual
1738'
1739
1740test_expect_success 'cover letter with --cover-from-description auto (short subject line)' '
1741 test_config branch.rebuild-1.description "config subject
1742
1743body" &&
1744 git checkout rebuild-1 &&
1745 git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1746 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1747 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1748 ! grep "^config subject$" actual &&
1749 grep "^body$" actual
1750'
1751
1752test_expect_success 'cover letter with format.coverFromDescription = 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
1755body" &&
1756 test_config format.coverFromDescription auto &&
1757 git checkout rebuild-1 &&
1758 git format-patch --stdout --cover-letter master >actual &&
1759 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1760 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1761 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1762 grep "^body$" actual
1763'
1764
1765test_expect_success 'cover letter with --cover-from-description auto (long subject line)' '
1766 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
1767
1768body" &&
1769 git checkout rebuild-1 &&
1770 git format-patch --stdout --cover-letter --cover-from-description auto master >actual &&
1771 grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual &&
1772 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1773 grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual &&
1774 grep "^body$" actual
1775'
1776
1777test_expect_success 'cover letter with command-line --cover-from-description overrides config' '
1778 test_config branch.rebuild-1.description "config subject
1779
1780body" &&
1781 test_config format.coverFromDescription none &&
1782 git checkout rebuild-1 &&
1783 git format-patch --stdout --cover-letter --cover-from-description subject master >actual &&
1784 grep "^Subject: \[PATCH 0/2\] config subject$" actual &&
1785 ! grep "^\*\*\* BLURB HERE \*\*\*$" actual &&
1786 ! grep "^config subject$" actual &&
1787 grep "^body$" actual
1788'
1789
e216cc48
NTND
1790test_expect_success 'cover letter using branch description (1)' '
1791 git checkout rebuild-1 &&
1792 test_config branch.rebuild-1.description hello &&
1793 git format-patch --stdout --cover-letter master >actual &&
f2e2fa8f 1794 grep hello actual
e216cc48
NTND
1795'
1796
1797test_expect_success 'cover letter using branch description (2)' '
1798 git checkout rebuild-1 &&
1799 test_config branch.rebuild-1.description hello &&
1800 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
f2e2fa8f 1801 grep hello actual
e216cc48
NTND
1802'
1803
1804test_expect_success 'cover letter using branch description (3)' '
1805 git checkout rebuild-1 &&
1806 test_config branch.rebuild-1.description hello &&
1807 git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
f2e2fa8f 1808 grep hello actual
e216cc48
NTND
1809'
1810
20b630aa
NTND
1811test_expect_success 'cover letter using branch description (4)' '
1812 git checkout rebuild-1 &&
1813 test_config branch.rebuild-1.description hello &&
1814 git format-patch --stdout --cover-letter master.. >actual &&
f2e2fa8f 1815 grep hello actual
20b630aa
NTND
1816'
1817
1818test_expect_success 'cover letter using branch description (5)' '
1819 git checkout rebuild-1 &&
1820 test_config branch.rebuild-1.description hello &&
1821 git format-patch --stdout --cover-letter -2 HEAD >actual &&
f2e2fa8f 1822 grep hello actual
20b630aa
NTND
1823'
1824
5ee29aef
NTND
1825test_expect_success 'cover letter using branch description (6)' '
1826 git checkout rebuild-1 &&
1827 test_config branch.rebuild-1.description hello &&
1828 git format-patch --stdout --cover-letter -2 >actual &&
f2e2fa8f 1829 grep hello actual
5ee29aef
NTND
1830'
1831
80d35ca0
FC
1832test_expect_success 'cover letter with nothing' '
1833 git format-patch --stdout --cover-letter >actual &&
1834 test_line_count = 0 actual
1835'
1836
2a4c2607
FC
1837test_expect_success 'cover letter auto' '
1838 mkdir -p tmp &&
1839 test_when_finished "rm -rf tmp;
1840 git config --unset format.coverletter" &&
1841
1842 git config format.coverletter auto &&
1843 git format-patch -o tmp -1 >list &&
1844 test_line_count = 1 list &&
1845 git format-patch -o tmp -2 >list &&
1846 test_line_count = 3 list
1847'
1848
1849test_expect_success 'cover letter auto user override' '
1850 mkdir -p tmp &&
1851 test_when_finished "rm -rf tmp;
1852 git config --unset format.coverletter" &&
1853
1854 git config format.coverletter auto &&
1855 git format-patch -o tmp --cover-letter -1 >list &&
1856 test_line_count = 2 list &&
1857 git format-patch -o tmp --cover-letter -2 >list &&
1858 test_line_count = 3 list &&
1859 git format-patch -o tmp --no-cover-letter -1 >list &&
1860 test_line_count = 1 list &&
1861 git format-patch -o tmp --no-cover-letter -2 >list &&
1862 test_line_count = 2 list
1863'
1864
3a30aa17 1865test_expect_success 'format-patch --zero-commit' '
1866 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1867 grep "^From " patch2 | sort | uniq >actual &&
8125a58b 1868 echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
3a30aa17 1869 test_cmp expect actual
1870'
1871
06dfc9eb 1872test_expect_success 'From line has expected format' '
1873 git format-patch --stdout v2..v1 >patch2 &&
1874 grep "^From " patch2 >from &&
2ece6ad2 1875 grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
06dfc9eb 1876 test_cmp from filtered
1877'
1878
edefc318
BW
1879test_expect_success 'format-patch -o with no leading directories' '
1880 rm -fr patches &&
1881 git format-patch -o patches master..side &&
1882 count=$(git rev-list --count master..side) &&
1883 ls patches >list &&
1884 test_line_count = $count list
1885'
1886
1887test_expect_success 'format-patch -o with leading existing directories' '
19c29e53
BW
1888 rm -rf existing-dir &&
1889 mkdir existing-dir &&
1890 git format-patch -o existing-dir/patches master..side &&
edefc318 1891 count=$(git rev-list --count master..side) &&
19c29e53 1892 ls existing-dir/patches >list &&
edefc318
BW
1893 test_line_count = $count list
1894'
1895
1896test_expect_success 'format-patch -o with leading non-existing directories' '
19c29e53
BW
1897 rm -rf non-existing-dir &&
1898 git format-patch -o non-existing-dir/patches master..side &&
edefc318 1899 count=$(git rev-list --count master..side) &&
19c29e53
BW
1900 test_path_is_dir non-existing-dir &&
1901 ls non-existing-dir/patches >list &&
edefc318
BW
1902 test_line_count = $count list
1903'
1904
bc6bf2d7
AK
1905test_expect_success 'format-patch format.outputDirectory option' '
1906 test_config format.outputDirectory patches &&
1907 rm -fr patches &&
1908 git format-patch master..side &&
756fb0de
DL
1909 count=$(git rev-list --count master..side) &&
1910 ls patches >list &&
1911 test_line_count = $count list
bc6bf2d7
AK
1912'
1913
1914test_expect_success 'format-patch -o overrides format.outputDirectory' '
1915 test_config format.outputDirectory patches &&
1916 rm -fr patches patchset &&
1917 git format-patch master..side -o patchset &&
1918 test_path_is_missing patches &&
1919 test_path_is_dir patchset
1920'
1921
fa2ab86d 1922test_expect_success 'format-patch --base' '
6f93d261 1923 git checkout patchid &&
854b5cb4
DL
1924
1925 git format-patch --stdout --base=HEAD~3 -1 >patch &&
1926 tail -n 7 patch >actual1 &&
1927
1928 git format-patch --stdout --base=HEAD~3 HEAD~.. >patch &&
1929 tail -n 7 patch >actual2 &&
1930
b562a54c 1931 echo >expect &&
854b5cb4
DL
1932 git rev-parse HEAD~3 >commit-id-base &&
1933 echo "base-commit: $(cat commit-id-base)" >>expect &&
1934
1935 git show --patch HEAD~2 >patch &&
1936 git patch-id --stable <patch >patch.id.raw &&
1937 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
1938
1939 git show --patch HEAD~1 >patch &&
1940 git patch-id --stable <patch >patch.id.raw &&
1941 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect &&
1942
92014b69 1943 signature >>expect &&
b562a54c
DL
1944 test_cmp expect actual1 &&
1945 test_cmp expect actual2 &&
854b5cb4 1946
6f93d261 1947 echo >fail &&
854b5cb4
DL
1948 echo "base-commit: $(cat commit-id-base)" >>fail &&
1949
1950 git show --patch HEAD~2 >patch &&
1951 git patch-id --unstable <patch >patch.id.raw &&
1952 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
1953
1954 git show --patch HEAD~1 >patch &&
1955 git patch-id --unstable <patch >patch.id.raw &&
1956 awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail &&
1957
92014b69 1958 signature >>fail &&
6f93d261
SB
1959 ! test_cmp fail actual1 &&
1960 ! test_cmp fail actual2
fa2ab86d
XY
1961'
1962
1963test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1964 test_must_fail git format-patch --base=HEAD -2 &&
1965 test_must_fail git format-patch --base=HEAD~1 -2 &&
1966 git format-patch --stdout --base=HEAD~2 -2 >patch &&
1967 grep "^base-commit:" patch >actual &&
854b5cb4
DL
1968 git rev-parse HEAD~2 >commit-id-base &&
1969 echo "base-commit: $(cat commit-id-base)" >expect &&
b562a54c 1970 test_cmp expect actual
fa2ab86d
XY
1971'
1972
1973test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1974 # For history as below:
1975 #
1976 # ---Q---P---Z---Y---*---X
1977 # \ /
1978 # ------------W
1979 #
1980 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1981 git checkout -b topic1 master &&
1982 git rev-parse HEAD >commit-id-base &&
1983 test_commit P &&
1984 git rev-parse HEAD >commit-id-P &&
1985 test_commit Z &&
1986 git rev-parse HEAD >commit-id-Z &&
1987 test_commit Y &&
1988 git checkout -b topic2 master &&
1989 test_commit W &&
1990 git merge topic1 &&
1991 test_commit X &&
1992 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1993 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1994 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1995 grep "^base-commit:" patch >actual &&
b562a54c
DL
1996 echo "base-commit: $(cat commit-id-base)" >expect &&
1997 test_cmp expect actual
fa2ab86d
XY
1998'
1999
3de66517
XY
2000test_expect_success 'format-patch --base=auto' '
2001 git checkout -b upstream master &&
2002 git checkout -b local upstream &&
2003 git branch --set-upstream-to=upstream &&
2004 test_commit N1 &&
2005 test_commit N2 &&
2006 git format-patch --stdout --base=auto -2 >patch &&
2007 grep "^base-commit:" patch >actual &&
854b5cb4
DL
2008 git rev-parse upstream >commit-id-base &&
2009 echo "base-commit: $(cat commit-id-base)" >expect &&
b562a54c 2010 test_cmp expect actual
3de66517
XY
2011'
2012
2013test_expect_success 'format-patch errors out when history involves criss-cross' '
2014 # setup criss-cross history
2015 #
2016 # B---M1---D
2017 # / \ /
2018 # A X
2019 # \ / \
2020 # C---M2---E
2021 #
2022 git checkout master &&
2023 test_commit A &&
2024 git checkout -b xb master &&
2025 test_commit B &&
2026 git checkout -b xc master &&
2027 test_commit C &&
2028 git checkout -b xbc xb -- &&
2029 git merge xc &&
2030 git checkout -b xcb xc -- &&
2031 git branch --set-upstream-to=xbc &&
2032 git merge xb &&
2033 git checkout xbc &&
2034 test_commit D &&
2035 git checkout xcb &&
2036 test_commit E &&
2037 test_must_fail git format-patch --base=auto -1
2038'
2039
700e006c 2040test_expect_success 'format-patch format.useAutoBase option' '
bb52995f 2041 git checkout local &&
700e006c 2042 test_config format.useAutoBase true &&
bb52995f
XY
2043 git format-patch --stdout -1 >patch &&
2044 grep "^base-commit:" patch >actual &&
854b5cb4
DL
2045 git rev-parse upstream >commit-id-base &&
2046 echo "base-commit: $(cat commit-id-base)" >expect &&
b562a54c 2047 test_cmp expect actual
bb52995f
XY
2048'
2049
2050test_expect_success 'format-patch --base overrides format.useAutoBase' '
700e006c 2051 test_config format.useAutoBase true &&
bb52995f
XY
2052 git format-patch --stdout --base=HEAD~1 -1 >patch &&
2053 grep "^base-commit:" patch >actual &&
854b5cb4
DL
2054 git rev-parse HEAD~1 >commit-id-base &&
2055 echo "base-commit: $(cat commit-id-base)" >expect &&
b562a54c 2056 test_cmp expect actual
bb52995f
XY
2057'
2058
945dc55d
DL
2059test_expect_success 'format-patch --no-base overrides format.useAutoBase' '
2060 test_config format.useAutoBase true &&
2061 git format-patch --stdout --no-base -1 >patch &&
2062 ! grep "^base-commit:" patch
2063'
2064
480871e0
JT
2065test_expect_success 'format-patch --base with --attach' '
2066 git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
2067 sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
2068 patch >actual &&
2069 test_write_lines 1 2 >expect &&
2070 test_cmp expect actual
2071'
50cd54ef 2072test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
2073 test_when_finished "rm -fr patches" &&
2074 git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
2075 ! egrep "^--+mimemime" patches/0000*.patch &&
2076 egrep "^--+mimemime$" patches/0001*.patch >output &&
2077 test_line_count = 2 output &&
2078 egrep "^--+mimemime--$" patches/0001*.patch >output &&
2079 test_line_count = 1 output
2080'
480871e0 2081
9f23e040
EW
2082test_expect_success 'format-patch --pretty=mboxrd' '
2083 sp=" " &&
2084 cat >msg <<-INPUT_END &&
2085 mboxrd should escape the body
2086
2087 From could trip up a loose mbox parser
2088 >From extra escape for reversibility
2089 >>From extra escape for reversibility 2
2090 from lower case not escaped
2091 Fromm bad speling not escaped
2092 From with leading space not escaped
2093
2094 F
2095 From
2096 From$sp
2097 From $sp
2098 From $sp
2099 INPUT_END
2100
2101 cat >expect <<-INPUT_END &&
2102 >From could trip up a loose mbox parser
2103 >>From extra escape for reversibility
2104 >>>From extra escape for reversibility 2
2105 from lower case not escaped
2106 Fromm bad speling not escaped
2107 From with leading space not escaped
2108
2109 F
2110 From
2111 From
2112 From
2113 From
2114 INPUT_END
2115
2116 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
2117 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
2118 git grep -h --no-index -A11 \
2119 "^>From could trip up a loose mbox parser" patch >actual &&
2120 test_cmp expect actual
2121'
2122
126facf8
ES
2123test_expect_success 'interdiff: setup' '
2124 git checkout -b boop master &&
2125 test_commit fnorp blorp &&
2126 test_commit fleep blorp
2127'
2128
2129test_expect_success 'interdiff: cover-letter' '
2130 sed "y/q/ /" >expect <<-\EOF &&
2131 +fleep
2132 --q
2133 EOF
2134 git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
2135 test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
ee6cbf71 2136 test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
c6ec6dad 2137 sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual &&
126facf8
ES
2138 test_cmp expect actual
2139'
2140
5ac290f9
ES
2141test_expect_success 'interdiff: reroll-count' '
2142 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
2143 test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
2144'
2145
ee6cbf71
ES
2146test_expect_success 'interdiff: solo-patch' '
2147 cat >expect <<-\EOF &&
2148 +fleep
2149
2150 EOF
2151 git format-patch --interdiff=boop~2 -1 boop &&
2152 test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
c6ec6dad 2153 sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual &&
ee6cbf71
ES
2154 test_cmp expect actual
2155'
2156
ece3c67f 2157test_done