format-patch: inform user that patch-id generation is unstable
[git/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 '
12
13 for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
cd894ee9
JH
14 cat file >elif &&
15 git add file elif &&
6426f2d2 16 test_tick &&
ece3c67f
JH
17 git commit -m Initial &&
18 git checkout -b side &&
19
20 for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
1f553918 21 test_chmod +x elif &&
6426f2d2 22 test_tick &&
816366e2 23 git commit -m "Side changes #1" &&
ece3c67f
JH
24
25 for i in D E F; do echo "$i"; done >>file &&
26 git update-index file &&
6426f2d2 27 test_tick &&
816366e2 28 git commit -m "Side changes #2" &&
982b64e4 29 git tag C2 &&
ece3c67f
JH
30
31 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
32 git update-index file &&
6426f2d2 33 test_tick &&
816366e2 34 git commit -m "Side changes #3 with \\n backslash-n in it." &&
ece3c67f
JH
35
36 git checkout master &&
982b64e4 37 git diff-tree -p C2 | git apply --index &&
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
62test_expect_success "format-patch --ignore-if-in-upstream" '
63
64 git format-patch --stdout master..side >patch0 &&
54835fc5 65 cnt=$(grep "^From " patch0 | wc -l) &&
8780bd8f 66 test $cnt = 3
ece3c67f
JH
67
68'
69
70test_expect_success "format-patch --ignore-if-in-upstream" '
71
72 git format-patch --stdout \
73 --ignore-if-in-upstream master..side >patch1 &&
54835fc5 74 cnt=$(grep "^From " patch1 | wc -l) &&
8780bd8f 75 test $cnt = 2
ece3c67f
JH
76
77'
78
9b7a61d7
JH
79test_expect_success "format-patch --ignore-if-in-upstream handles tags" '
80 git tag -a v1 -m tag side &&
81 git tag -a v2 -m tag master &&
82 git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
83 cnt=$(grep "^From " patch1 | wc -l) &&
84 test $cnt = 2
85'
86
2c642ed8
RR
87test_expect_success "format-patch doesn't consider merge commits" '
88
89 git checkout -b slave master &&
90 echo "Another line" >>file &&
91 test_tick &&
92 git commit -am "Slave change #1" &&
93 echo "Yet another line" >>file &&
94 test_tick &&
95 git commit -am "Slave change #2" &&
96 git checkout -b merger master &&
97 test_tick &&
98 git merge --no-ff slave &&
54835fc5 99 cnt=$(git format-patch -3 --stdout | grep "^From " | wc -l) &&
2c642ed8
RR
100 test $cnt = 3
101'
102
ece3c67f
JH
103test_expect_success "format-patch result applies" '
104
105 git checkout -b rebuild-0 master &&
106 git am -3 patch0 &&
54835fc5 107 cnt=$(git rev-list master.. | wc -l) &&
8780bd8f 108 test $cnt = 2
ece3c67f
JH
109'
110
111test_expect_success "format-patch --ignore-if-in-upstream result applies" '
112
113 git checkout -b rebuild-1 master &&
114 git am -3 patch1 &&
54835fc5 115 cnt=$(git rev-list master.. | wc -l) &&
8780bd8f 116 test $cnt = 2
ece3c67f
JH
117'
118
816366e2
JH
119test_expect_success 'commit did not screw up the log message' '
120
121 git cat-file commit side | grep "^Side .* with .* backslash-n"
122
123'
124
125test_expect_success 'format-patch did not screw up the log message' '
126
127 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
128 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
129
130'
131
132test_expect_success 'replay did not screw up the log message' '
133
134 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
135
136'
137
a8d8173e
DB
138test_expect_success 'extra headers' '
139
25dc8dad 140 git config format.headers "To: R E Cipient <rcipient@example.com>
a8d8173e 141" &&
25dc8dad 142 git config --add format.headers "Cc: S E Cipient <scipient@example.com>
a8d8173e
DB
143" &&
144 git format-patch --stdout master..side > patch2 &&
9524cf29 145 sed -e "/^\$/q" patch2 > hdrs2 &&
25dc8dad
JS
146 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 &&
147 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2
3b2eb186 148
a8d8173e
DB
149'
150
7d22708b 151test_expect_success 'extra headers without newlines' '
a8d8173e 152
25dc8dad
JS
153 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
154 git config --add format.headers "Cc: S E Cipient <scipient@example.com>" &&
a8d8173e 155 git format-patch --stdout master..side >patch3 &&
9524cf29 156 sed -e "/^\$/q" patch3 > hdrs3 &&
25dc8dad
JS
157 grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 &&
158 grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3
3b2eb186 159
a8d8173e
DB
160'
161
3ee79d9f 162test_expect_success 'extra headers with multiple To:s' '
a8d8173e 163
25dc8dad
JS
164 git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" &&
165 git config --add format.headers "To: S E Cipient <scipient@example.com>" &&
a8d8173e 166 git format-patch --stdout master..side > patch4 &&
9524cf29 167 sed -e "/^\$/q" patch4 > hdrs4 &&
25dc8dad
JS
168 grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 &&
169 grep "^ *S E Cipient <scipient@example.com>\$" hdrs4
a8d8173e
DB
170'
171
25dc8dad 172test_expect_success 'additional command line cc (ascii)' '
736cc67d 173
25dc8dad
JS
174 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
175 git format-patch --cc="S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
176 grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
177 grep "^ *S E Cipient <scipient@example.com>\$" patch5
178'
179
180test_expect_failure 'additional command line cc (rfc822)' '
181
182 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
9524cf29 183 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
25dc8dad 184 grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 &&
27f6342f 185 grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" patch5
736cc67d
DB
186'
187
d7d9c2d0
MH
188test_expect_success 'command line headers' '
189
190 git config --unset-all format.headers &&
25dc8dad
JS
191 git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
192 grep "^Cc: R E Cipient <rcipient@example.com>\$" patch6
d7d9c2d0
MH
193'
194
195test_expect_success 'configuration headers and command line headers' '
196
25dc8dad
JS
197 git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" &&
198 git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
199 grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch7 &&
200 grep "^ *S E Cipient <scipient@example.com>\$" patch7
d7d9c2d0
MH
201'
202
25dc8dad 203test_expect_success 'command line To: header (ascii)' '
ae6c098f
SD
204
205 git config --unset-all format.headers &&
25dc8dad
JS
206 git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
207 grep "^To: R E Cipient <rcipient@example.com>\$" patch8
208'
209
210test_expect_failure 'command line To: header (rfc822)' '
211
ae6c098f 212 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
27f6342f 213 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch8
25dc8dad
JS
214'
215
216test_expect_failure 'command line To: header (rfc2047)' '
217
218 git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
219 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch8
ae6c098f
SD
220'
221
25dc8dad
JS
222test_expect_success 'configuration To: header (ascii)' '
223
224 git config format.to "R E Cipient <rcipient@example.com>" &&
225 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
226 grep "^To: R E Cipient <rcipient@example.com>\$" patch9
227'
228
229test_expect_failure 'configuration To: header (rfc822)' '
ae6c098f
SD
230
231 git config format.to "R. E. Cipient <rcipient@example.com>" &&
232 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
27f6342f 233 grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch9
25dc8dad
JS
234'
235
236test_expect_failure 'configuration To: header (rfc2047)' '
237
238 git config format.to "R Ä Cipient <rcipient@example.com>" &&
239 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
240 grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch9
ae6c098f
SD
241'
242
cc663d14
TR
243# check_patch <patch>: Verify that <patch> looks like a half-sane
244# patch email to avoid a false positive with !grep
245check_patch () {
246 grep -e "^From:" "$1" &&
247 grep -e "^Date:" "$1" &&
248 grep -e "^Subject:" "$1"
249}
250
6bc6b6c0
JT
251test_expect_success 'format.from=false' '
252
253 git -c format.from=false format-patch --stdout master..side |
254 sed -e "/^\$/q" >patch &&
255 check_patch patch &&
256 ! grep "^From: C O Mitter <committer@example.com>\$" patch
257'
258
259test_expect_success 'format.from=true' '
260
261 git -c format.from=true format-patch --stdout master..side |
262 sed -e "/^\$/q" >patch &&
263 check_patch patch &&
264 grep "^From: C O Mitter <committer@example.com>\$" patch
265'
266
267test_expect_success 'format.from with address' '
268
269 git -c format.from="F R Om <from@example.com>" format-patch --stdout master..side |
270 sed -e "/^\$/q" >patch &&
271 check_patch patch &&
272 grep "^From: F R Om <from@example.com>\$" patch
273'
274
275test_expect_success '--no-from overrides format.from' '
276
277 git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout master..side |
278 sed -e "/^\$/q" >patch &&
279 check_patch patch &&
280 ! grep "^From: F R Om <from@example.com>\$" patch
281'
282
283test_expect_success '--from overrides format.from' '
284
285 git -c format.from="F R Om <from@example.com>" format-patch --from --stdout master..side |
286 sed -e "/^\$/q" >patch &&
287 check_patch patch &&
288 ! grep "^From: F R Om <from@example.com>\$" patch
289'
290
c4260034
SB
291test_expect_success '--no-to overrides config.to' '
292
293 git config --replace-all format.to \
25dc8dad 294 "R E Cipient <rcipient@example.com>" &&
c4260034
SB
295 git format-patch --no-to --stdout master..side |
296 sed -e "/^\$/q" >patch10 &&
cc663d14 297 check_patch patch10 &&
25dc8dad 298 ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10
c4260034
SB
299'
300
301test_expect_success '--no-to and --to replaces config.to' '
302
303 git config --replace-all format.to \
304 "Someone <someone@out.there>" &&
305 git format-patch --no-to --to="Someone Else <else@out.there>" \
306 --stdout master..side |
307 sed -e "/^\$/q" >patch11 &&
cc663d14 308 check_patch patch11 &&
c4260034
SB
309 ! grep "^To: Someone <someone@out.there>\$" patch11 &&
310 grep "^To: Someone Else <else@out.there>\$" patch11
311'
312
313test_expect_success '--no-cc overrides config.cc' '
314
315 git config --replace-all format.cc \
25dc8dad 316 "C E Cipient <rcipient@example.com>" &&
c4260034
SB
317 git format-patch --no-cc --stdout master..side |
318 sed -e "/^\$/q" >patch12 &&
cc663d14 319 check_patch patch12 &&
25dc8dad 320 ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12
c4260034
SB
321'
322
688f4f2f 323test_expect_success '--no-add-header overrides config.headers' '
c4260034
SB
324
325 git config --replace-all format.headers \
25dc8dad 326 "Header1: B E Cipient <rcipient@example.com>" &&
688f4f2f 327 git format-patch --no-add-header --stdout master..side |
c4260034 328 sed -e "/^\$/q" >patch13 &&
cc663d14 329 check_patch patch13 &&
25dc8dad 330 ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13
c4260034
SB
331'
332
7d812145
DB
333test_expect_success 'multiple files' '
334
335 rm -rf patches/ &&
336 git checkout side &&
337 git format-patch -o patches/ master &&
338 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
339'
340
4aad08e0
JH
341test_expect_success 'reroll count' '
342 rm -fr patches &&
343 git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
344 ! grep -v "^patches/v4-000[0-3]-" list &&
345 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
346 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
347'
348
7952ea66
JH
349test_expect_success 'reroll count (-v)' '
350 rm -fr patches &&
351 git format-patch -o patches --cover-letter -v4 master..side >list &&
352 ! grep -v "^patches/v4-000[0-3]-" list &&
353 sed -n -e "/^Subject: /p" $(cat list) >subjects &&
354 ! grep -v "^Subject: \[PATCH v4 [0-3]/3\] " subjects
355'
356
484cf6c3
TR
357check_threading () {
358 expect="$1" &&
359 shift &&
360 (git format-patch --stdout "$@"; echo $? > status.out) |
361 # Prints everything between the Message-ID and In-Reply-To,
362 # and replaces all Message-ID-lookalikes by a sequence number
94221d22 363 perl -ne '
484cf6c3
TR
364 if (/^(message-id|references|in-reply-to)/i) {
365 $printing = 1;
366 } elsif (/^\S/) {
367 $printing = 0;
368 }
369 if ($printing) {
370 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
371 for $k (keys %h) {s/$k/$h{$k}/};
372 print;
373 }
374 print "---\n" if /^From /i;
375 ' > actual &&
376 test 0 = "$(cat status.out)" &&
377 test_cmp "$expect" actual
378}
379
380cat >> expect.no-threading <<EOF
381---
382---
383---
384EOF
385
386test_expect_success 'no threading' '
7d812145 387 git checkout side &&
484cf6c3 388 check_threading expect.no-threading master
7d812145
DB
389'
390
484cf6c3
TR
391cat > expect.thread <<EOF
392---
393Message-Id: <0>
394---
395Message-Id: <1>
396In-Reply-To: <0>
397References: <0>
398---
399Message-Id: <2>
400In-Reply-To: <0>
401References: <0>
402EOF
7d812145 403
484cf6c3
TR
404test_expect_success 'thread' '
405 check_threading expect.thread --thread master
7d812145
DB
406'
407
484cf6c3
TR
408cat > expect.in-reply-to <<EOF
409---
410Message-Id: <0>
411In-Reply-To: <1>
412References: <1>
413---
414Message-Id: <2>
415In-Reply-To: <1>
416References: <1>
417---
418Message-Id: <3>
419In-Reply-To: <1>
420References: <1>
421EOF
a5a27c79 422
484cf6c3
TR
423test_expect_success 'thread in-reply-to' '
424 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
425 --thread master
a5a27c79
DB
426'
427
484cf6c3
TR
428cat > expect.cover-letter <<EOF
429---
430Message-Id: <0>
431---
432Message-Id: <1>
433In-Reply-To: <0>
434References: <0>
435---
436Message-Id: <2>
437In-Reply-To: <0>
438References: <0>
439---
440Message-Id: <3>
441In-Reply-To: <0>
442References: <0>
443EOF
a5a27c79 444
484cf6c3
TR
445test_expect_success 'thread cover-letter' '
446 check_threading expect.cover-letter --cover-letter --thread master
447'
448
449cat > expect.cl-irt <<EOF
450---
451Message-Id: <0>
452In-Reply-To: <1>
453References: <1>
454---
455Message-Id: <2>
2175c10d 456In-Reply-To: <0>
484cf6c3 457References: <1>
2175c10d 458 <0>
484cf6c3
TR
459---
460Message-Id: <3>
2175c10d 461In-Reply-To: <0>
484cf6c3 462References: <1>
2175c10d 463 <0>
484cf6c3
TR
464---
465Message-Id: <4>
2175c10d 466In-Reply-To: <0>
484cf6c3 467References: <1>
2175c10d 468 <0>
484cf6c3
TR
469EOF
470
471test_expect_success 'thread cover-letter in-reply-to' '
472 check_threading expect.cl-irt --cover-letter \
473 --in-reply-to="<test.message>" --thread master
a5a27c79
DB
474'
475
30984ed2
TR
476test_expect_success 'thread explicit shallow' '
477 check_threading expect.cl-irt --cover-letter \
478 --in-reply-to="<test.message>" --thread=shallow master
479'
480
481cat > expect.deep <<EOF
482---
483Message-Id: <0>
484---
485Message-Id: <1>
486In-Reply-To: <0>
487References: <0>
488---
489Message-Id: <2>
490In-Reply-To: <1>
491References: <0>
492 <1>
493EOF
494
495test_expect_success 'thread deep' '
496 check_threading expect.deep --thread=deep master
497'
498
499cat > expect.deep-irt <<EOF
500---
501Message-Id: <0>
502In-Reply-To: <1>
503References: <1>
504---
505Message-Id: <2>
506In-Reply-To: <0>
507References: <1>
508 <0>
509---
510Message-Id: <3>
511In-Reply-To: <2>
512References: <1>
513 <0>
514 <2>
515EOF
516
517test_expect_success 'thread deep in-reply-to' '
518 check_threading expect.deep-irt --thread=deep \
519 --in-reply-to="<test.message>" master
520'
521
522cat > expect.deep-cl <<EOF
523---
524Message-Id: <0>
525---
526Message-Id: <1>
527In-Reply-To: <0>
528References: <0>
529---
530Message-Id: <2>
531In-Reply-To: <1>
532References: <0>
533 <1>
534---
535Message-Id: <3>
536In-Reply-To: <2>
537References: <0>
538 <1>
539 <2>
540EOF
541
542test_expect_success 'thread deep cover-letter' '
543 check_threading expect.deep-cl --cover-letter --thread=deep master
544'
545
546cat > expect.deep-cl-irt <<EOF
547---
548Message-Id: <0>
549In-Reply-To: <1>
550References: <1>
551---
552Message-Id: <2>
553In-Reply-To: <0>
554References: <1>
555 <0>
556---
557Message-Id: <3>
558In-Reply-To: <2>
559References: <1>
560 <0>
561 <2>
562---
563Message-Id: <4>
564In-Reply-To: <3>
565References: <1>
566 <0>
567 <2>
568 <3>
569EOF
570
571test_expect_success 'thread deep cover-letter in-reply-to' '
572 check_threading expect.deep-cl-irt --cover-letter \
573 --in-reply-to="<test.message>" --thread=deep master
574'
575
576test_expect_success 'thread via config' '
e8107155 577 test_config format.thread true &&
30984ed2
TR
578 check_threading expect.thread master
579'
580
581test_expect_success 'thread deep via config' '
e8107155 582 test_config format.thread deep &&
30984ed2
TR
583 check_threading expect.deep master
584'
585
586test_expect_success 'thread config + override' '
e8107155 587 test_config format.thread deep &&
30984ed2
TR
588 check_threading expect.thread --thread master
589'
590
591test_expect_success 'thread config + --no-thread' '
e8107155 592 test_config format.thread deep &&
30984ed2
TR
593 check_threading expect.no-threading --no-thread master
594'
595
7d812145
DB
596test_expect_success 'excessive subject' '
597
598 rm -rf patches/ &&
599 git checkout side &&
bdee9cd6 600 before=$(git hash-object file) &&
601 before=$(git rev-parse --short $before) &&
7d812145 602 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 603 after=$(git hash-object file) &&
604 after=$(git rev-parse --short $after) &&
7d812145
DB
605 git update-index file &&
606 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." &&
607 git format-patch -o patches/ master..side &&
608 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
609'
610
2fe95f49
JH
611test_expect_success 'failure to write cover-letter aborts gracefully' '
612 test_when_finished "rmdir 0000-cover-letter.patch" &&
613 mkdir 0000-cover-letter.patch &&
614 test_must_fail git format-patch --no-renames --cover-letter -1
615'
616
5d02294c 617test_expect_success 'cover-letter inherits diff options' '
5d02294c
JS
618 git mv file foo &&
619 git commit -m foo &&
5404c116 620 git format-patch --no-renames --cover-letter -1 &&
cc663d14 621 check_patch 0000-cover-letter.patch &&
9524cf29 622 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
5d02294c 623 git format-patch --cover-letter -1 -M &&
9524cf29 624 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
5d02294c
JS
625
626'
859c4fbe
JS
627
628cat > expect << EOF
629 This is an excessively long subject line for a message due to the
630 habit some projects have of not having a short, one-line subject at
631 the start of the commit message, but rather sticking a whole
632 paragraph right at the start as the only thing in the commit
633 message. It had better not become the filename for the patch.
634 foo
635
636EOF
637
638test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
639
640 git format-patch --cover-letter -2 &&
9524cf29 641 sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
3af82863 642 test_cmp expect output
859c4fbe
JS
643
644'
645
68daa64d 646cat > expect << EOF
bdee9cd6 647index $before..$after 100644
68daa64d
JK
648--- a/file
649+++ b/file
650@@ -13,4 +13,20 @@ C
651 10
652 D
653 E
654 F
655+5
656EOF
657
658test_expect_success 'format-patch respects -U' '
659
660 git format-patch -U4 -2 &&
6dd88832
JN
661 sed -e "1,/^diff/d" -e "/^+5/q" \
662 <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \
663 >output &&
68daa64d
JK
664 test_cmp expect output
665
666'
667
1d46f2ea
JK
668cat > expect << EOF
669
670diff --git a/file b/file
bdee9cd6 671index $before..$after 100644
1d46f2ea
JK
672--- a/file
673+++ b/file
674@@ -14,3 +14,19 @@ C
675 D
676 E
677 F
678+5
679EOF
680
681test_expect_success 'format-patch -p suppresses stat' '
682
683 git format-patch -p -2 &&
9524cf29 684 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
1d46f2ea
JK
685 test_cmp expect output
686
687'
688
9800a754
JH
689test_expect_success 'format-patch from a subdirectory (1)' '
690 filename=$(
691 rm -rf sub &&
692 mkdir -p sub/dir &&
693 cd sub/dir &&
694 git format-patch -1
695 ) &&
696 case "$filename" in
697 0*)
698 ;; # ok
699 *)
700 echo "Oops? $filename"
701 false
702 ;;
703 esac &&
704 test -f "$filename"
705'
706
707test_expect_success 'format-patch from a subdirectory (2)' '
708 filename=$(
709 rm -rf sub &&
710 mkdir -p sub/dir &&
711 cd sub/dir &&
712 git format-patch -1 -o ..
713 ) &&
714 case "$filename" in
715 ../0*)
716 ;; # ok
717 *)
718 echo "Oops? $filename"
719 false
720 ;;
721 esac &&
722 basename=$(expr "$filename" : ".*/\(.*\)") &&
723 test -f "sub/$basename"
724'
725
726test_expect_success 'format-patch from a subdirectory (3)' '
9800a754
JH
727 rm -f 0* &&
728 filename=$(
729 rm -rf sub &&
730 mkdir -p sub/dir &&
731 cd sub/dir &&
91c8b825 732 git format-patch -1 -o "$TRASH_DIRECTORY"
9800a754
JH
733 ) &&
734 basename=$(expr "$filename" : ".*/\(.*\)") &&
735 test -f "$basename"
736'
737
f044fe2d
SB
738test_expect_success 'format-patch --in-reply-to' '
739 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
740 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
741 grep "^References: <baz@foo.bar>" patch8
742'
743
744test_expect_success 'format-patch --signoff' '
212620fe
JH
745 git format-patch -1 --signoff --stdout >out &&
746 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" out
747'
748
749test_expect_success 'format-patch --notes --signoff' '
750 git notes --ref test add -m "test message" HEAD &&
751 git format-patch -1 --signoff --stdout --notes=test >out &&
bd1470b8 752 # Three dashes must come after S-o-b
212620fe 753 ! sed "/^Signed-off-by: /q" out | grep "test message" &&
bd1470b8
JH
754 sed "1,/^Signed-off-by: /d" out | grep "test message" &&
755 # Notes message must come after three dashes
756 ! sed "/^---$/q" out | grep "test message" &&
757 sed "1,/^---$/d" out | grep "test message"
f044fe2d
SB
758'
759
02bc5b03
BG
760echo "fatal: --name-only does not make sense" > expect.name-only
761echo "fatal: --name-status does not make sense" > expect.name-status
762echo "fatal: --check does not make sense" > expect.check
763
68b2a005 764test_expect_success 'options no longer allowed for format-patch' '
02bc5b03 765 test_must_fail git format-patch --name-only 2> output &&
68b2a005 766 test_i18ncmp expect.name-only output &&
02bc5b03 767 test_must_fail git format-patch --name-status 2> output &&
68b2a005 768 test_i18ncmp expect.name-status output &&
02bc5b03 769 test_must_fail git format-patch --check 2> output &&
68b2a005 770 test_i18ncmp expect.check output'
02bc5b03
BG
771
772test_expect_success 'format-patch --numstat should produce a patch' '
4fa80cf0 773 git format-patch --numstat --stdout master..side > output &&
5404c116 774 test 5 = $(grep "^diff --git a/" output | wc -l)'
02bc5b03 775
7e93d3b9
FC
776test_expect_success 'format-patch -- <path>' '
777 git format-patch master..side -- file 2>error &&
778 ! grep "Use .--" error
779'
780
657ab61e
KB
781test_expect_success 'format-patch --ignore-if-in-upstream HEAD' '
782 git format-patch --ignore-if-in-upstream HEAD
783'
784
480871e0
JT
785git_version="$(git --version | sed "s/.* //")"
786
787signature() {
788 printf "%s\n%s\n\n" "-- " "${1:-$git_version}"
789}
790
791test_expect_success 'format-patch default signature' '
792 git format-patch --stdout -1 | tail -n 3 >output &&
793 signature >expect &&
794 test_cmp expect output
795'
796
6622d9c7 797test_expect_success 'format-patch --signature' '
480871e0
JT
798 git format-patch --stdout --signature="my sig" -1 | tail -n 3 >output &&
799 signature "my sig" >expect &&
800 test_cmp expect output
6622d9c7
SB
801'
802
803test_expect_success 'format-patch with format.signature config' '
804 git config format.signature "config sig" &&
805 git format-patch --stdout -1 >output &&
806 grep "config sig" output
807'
808
809test_expect_success 'format-patch --signature overrides format.signature' '
810 git config format.signature "config sig" &&
811 git format-patch --stdout --signature="overrides" -1 >output &&
812 ! grep "config sig" output &&
813 grep "overrides" output
814'
815
816test_expect_success 'format-patch --no-signature ignores format.signature' '
817 git config format.signature "config sig" &&
818 git format-patch --stdout --signature="my sig" --no-signature \
819 -1 >output &&
cc663d14 820 check_patch output &&
6622d9c7
SB
821 ! grep "config sig" output &&
822 ! grep "my sig" output &&
823 ! grep "^-- \$" output
824'
825
826test_expect_success 'format-patch --signature --cover-letter' '
827 git config --unset-all format.signature &&
828 git format-patch --stdout --signature="my sig" --cover-letter \
829 -1 >output &&
830 grep "my sig" output &&
831 test 2 = $(grep "my sig" output | wc -l)
832'
833
41ccfdd9 834test_expect_success 'format.signature="" suppresses signatures' '
6622d9c7
SB
835 git config format.signature "" &&
836 git format-patch --stdout -1 >output &&
cc663d14 837 check_patch output &&
6622d9c7
SB
838 ! grep "^-- \$" output
839'
840
41ccfdd9 841test_expect_success 'format-patch --no-signature suppresses signatures' '
6622d9c7
SB
842 git config --unset-all format.signature &&
843 git format-patch --stdout --no-signature -1 >output &&
cc663d14 844 check_patch output &&
6622d9c7
SB
845 ! grep "^-- \$" output
846'
847
41ccfdd9 848test_expect_success 'format-patch --signature="" suppresses signatures' '
2fdb5c62 849 git format-patch --stdout --signature="" -1 >output &&
cc663d14 850 check_patch output &&
6622d9c7
SB
851 ! grep "^-- \$" output
852'
853
7022650f
JM
854test_expect_success 'prepare mail-signature input' '
855 cat >mail-signature <<-\EOF
856
857 Test User <test.email@kernel.org>
858 http://git.kernel.org/cgit/git/git.git
859
860 git.kernel.org/?p=git/git.git;a=summary
861
862 EOF
863'
864
865test_expect_success '--signature-file=file works' '
866 git format-patch --stdout --signature-file=mail-signature -1 >output &&
867 check_patch output &&
868 sed -e "1,/^-- \$/d" <output >actual &&
869 {
870 cat mail-signature && echo
871 } >expect &&
872 test_cmp expect actual
873'
874
875test_expect_success 'format.signaturefile works' '
876 test_config format.signaturefile mail-signature &&
877 git format-patch --stdout -1 >output &&
878 check_patch output &&
879 sed -e "1,/^-- \$/d" <output >actual &&
880 {
881 cat mail-signature && echo
882 } >expect &&
883 test_cmp expect actual
884'
885
886test_expect_success '--no-signature suppresses format.signaturefile ' '
887 test_config format.signaturefile mail-signature &&
888 git format-patch --stdout --no-signature -1 >output &&
889 check_patch output &&
890 ! grep "^-- \$" output
891'
892
893test_expect_success '--signature-file overrides format.signaturefile' '
99094a7a 894 cat >other-mail-signature <<-\EOF &&
7022650f
JM
895 Use this other signature instead of mail-signature.
896 EOF
897 test_config format.signaturefile mail-signature &&
898 git format-patch --stdout \
899 --signature-file=other-mail-signature -1 >output &&
900 check_patch output &&
901 sed -e "1,/^-- \$/d" <output >actual &&
902 {
903 cat other-mail-signature && echo
904 } >expect &&
905 test_cmp expect actual
906'
907
908test_expect_success '--signature overrides format.signaturefile' '
909 test_config format.signaturefile mail-signature &&
910 git format-patch --stdout --signature="my sig" -1 >output &&
911 check_patch output &&
912 grep "my sig" output
913'
914
38a94bb6
TRC
915test_expect_success TTY 'format-patch --stdout paginates' '
916 rm -f pager_used &&
512477b1 917 test_terminal env GIT_PAGER="wc >pager_used" git format-patch --stdout --all &&
38a94bb6
TRC
918 test_path_is_file pager_used
919'
920
921 test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
922 rm -f pager_used &&
512477b1
DT
923 test_terminal env GIT_PAGER="wc >pager_used" git --no-pager format-patch --stdout --all &&
924 test_terminal env GIT_PAGER="wc >pager_used" git -c "pager.format-patch=false" format-patch --stdout --all &&
38a94bb6
TRC
925 test_path_is_missing pager_used &&
926 test_path_is_missing .git/pager_used
927'
928
a1f6baa5
JK
929test_expect_success 'format-patch handles multi-line subjects' '
930 rm -rf patches/ &&
931 echo content >>file &&
932 for i in one two three; do echo $i; done >msg &&
933 git add file &&
934 git commit -F msg &&
935 git format-patch -o patches -1 &&
936 grep ^Subject: patches/0001-one.patch >actual &&
937 echo "Subject: [PATCH] one two three" >expect &&
938 test_cmp expect actual
939'
940
941test_expect_success 'format-patch handles multi-line encoded subjects' '
942 rm -rf patches/ &&
943 echo content >>file &&
944 for i in en två tre; do echo $i; done >msg &&
945 git add file &&
946 git commit -F msg &&
947 git format-patch -o patches -1 &&
948 grep ^Subject: patches/0001-en.patch >actual &&
949 echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
950 test_cmp expect actual
951'
952
953M8="foo bar "
954M64=$M8$M8$M8$M8$M8$M8$M8$M8
955M512=$M64$M64$M64$M64$M64$M64$M64$M64
956cat >expect <<'EOF'
957Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
7a76e68a
JS
958 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
959 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
960 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
961 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
962 bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
963 foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
a1f6baa5 964EOF
7a76e68a 965test_expect_success 'format-patch wraps extremely long subject (ascii)' '
a1f6baa5
JK
966 echo content >>file &&
967 git add file &&
968 git commit -m "$M512" &&
969 git format-patch --stdout -1 >patch &&
970 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
971 test_cmp expect subject
972'
973
974M8="föö bar "
975M64=$M8$M8$M8$M8$M8$M8$M8$M8
976M512=$M64$M64$M64$M64$M64$M64$M64$M64
977cat >expect <<'EOF'
94f6cdf6
JS
978Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
979 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
980 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
981 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
6cd3c053
KS
982 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
983 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
94f6cdf6
JS
984 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
985 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
986 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
6cd3c053
KS
987 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
988 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
94f6cdf6
JS
989 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
990 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
991 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
6cd3c053
KS
992 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
993 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
994 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
995 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
996 =?UTF-8?q?bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6?=
997 =?UTF-8?q?=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
998 =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f?=
999 =?UTF-8?q?=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
1000 =?UTF-8?q?=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20?=
1001 =?UTF-8?q?bar?=
a1f6baa5 1002EOF
94f6cdf6 1003test_expect_success 'format-patch wraps extremely long subject (rfc2047)' '
a1f6baa5
JK
1004 rm -rf patches/ &&
1005 echo content >>file &&
1006 git add file &&
1007 git commit -m "$M512" &&
1008 git format-patch --stdout -1 >patch &&
1009 sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
1010 test_cmp expect subject
1011'
1012
4d03c18a
JK
1013check_author() {
1014 echo content >>file &&
1015 git add file &&
1016 GIT_AUTHOR_NAME=$1 git commit -m author-check &&
1017 git format-patch --stdout -1 >patch &&
7a76e68a 1018 sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual &&
4d03c18a
JK
1019 test_cmp expect actual
1020}
1021
1022cat >expect <<'EOF'
1023From: "Foo B. Bar" <author@example.com>
1024EOF
0fcec2ce 1025test_expect_success 'format-patch quotes dot in from-headers' '
4d03c18a
JK
1026 check_author "Foo B. Bar"
1027'
1028
1029cat >expect <<'EOF'
1030From: "Foo \"The Baz\" Bar" <author@example.com>
1031EOF
0fcec2ce 1032test_expect_success 'format-patch quotes double-quote in from-headers' '
4d03c18a
JK
1033 check_author "Foo \"The Baz\" Bar"
1034'
1035
1036cat >expect <<'EOF'
0fcec2ce 1037From: =?UTF-8?q?F=C3=B6o=20Bar?= <author@example.com>
4d03c18a 1038EOF
0fcec2ce
JS
1039test_expect_success 'format-patch uses rfc2047-encoded from-headers when necessary' '
1040 check_author "Föo Bar"
1041'
1042
1043cat >expect <<'EOF'
1044From: =?UTF-8?q?F=C3=B6o=20B=2E=20Bar?= <author@example.com>
1045EOF
41dd00ba 1046test_expect_success 'rfc2047-encoded from-headers leave no rfc822 specials' '
4d03c18a
JK
1047 check_author "Föo B. Bar"
1048'
1049
7a76e68a
JS
1050cat >expect <<EOF
1051From: foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_
1052 <author@example.com>
1053EOF
1054test_expect_success 'format-patch wraps moderately long from-header (ascii)' '
1055 check_author "foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_foo_bar_"
1056'
1057
1058cat >expect <<'EOF'
1059From: Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1060 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1061 Bar Foo Bar Foo Bar Foo Bar <author@example.com>
1062EOF
1063test_expect_success 'format-patch wraps extremely long from-header (ascii)' '
1064 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"
1065'
1066
1067cat >expect <<'EOF'
1068From: "Foo.Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar
1069 Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo
1070 Bar Foo Bar Foo Bar Foo Bar" <author@example.com>
1071EOF
1072test_expect_success 'format-patch wraps extremely long from-header (rfc822)' '
1073 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"
1074'
1075
4d03c18a 1076cat >expect <<'EOF'
94f6cdf6
JS
1077From: =?UTF-8?q?Fo=C3=B6=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo?=
1078 =?UTF-8?q?=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20?=
1079 =?UTF-8?q?Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar?=
1080 =?UTF-8?q?=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20Foo=20Bar=20?=
1081 =?UTF-8?q?Foo=20Bar=20Foo=20Bar?= <author@example.com>
1082EOF
1083test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' '
1084 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"
1085'
1086
1087cat >expect <<'EOF'
4d03c18a
JK
1088Subject: header with . in it
1089EOF
1090test_expect_success 'subject lines do not have 822 atom-quoting' '
1091 echo content >>file &&
1092 git add file &&
1093 git commit -m "header with . in it" &&
1094 git format-patch -k -1 --stdout >patch &&
1095 grep ^Subject: patch >actual &&
1096 test_cmp expect actual
1097'
1098
e7af8e49
JK
1099cat >expect <<'EOF'
1100Subject: [PREFIX 1/1] header with . in it
1101EOF
1102test_expect_success 'subject prefixes have space prepended' '
1103 git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
1104 grep ^Subject: patch >actual &&
1105 test_cmp expect actual
1106'
1107
1108cat >expect <<'EOF'
1109Subject: [1/1] header with . in it
1110EOF
1111test_expect_success 'empty subject prefix does not have extra space' '
1112 git format-patch -n -1 --stdout --subject-prefix= >patch &&
1113 grep ^Subject: patch >actual &&
1114 test_cmp expect actual
1115'
1116
68e83a5b
JT
1117test_expect_success '--rfc' '
1118 cat >expect <<-\EOF &&
1119 Subject: [RFC PATCH 1/1] header with . in it
1120 EOF
1121 git format-patch -n -1 --stdout --rfc >patch &&
1122 grep ^Subject: patch >actual &&
1123 test_cmp expect actual
1124'
1125
a9080475
JK
1126test_expect_success '--from=ident notices bogus ident' '
1127 test_must_fail git format-patch -1 --stdout --from=foo >patch
1128'
1129
1130test_expect_success '--from=ident replaces author' '
1131 git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
1132 cat >expect <<-\EOF &&
1133 From: Me <me@example.com>
1134
1135 From: A U Thor <author@example.com>
1136
1137 EOF
1138 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1139 test_cmp expect patch.head
1140'
1141
1142test_expect_success '--from uses committer ident' '
1143 git format-patch -1 --stdout --from >patch &&
1144 cat >expect <<-\EOF &&
1145 From: C O Mitter <committer@example.com>
1146
1147 From: A U Thor <author@example.com>
1148
1149 EOF
1150 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1151 test_cmp expect patch.head
1152'
1153
662cc30c
JK
1154test_expect_success '--from omits redundant in-body header' '
1155 git format-patch -1 --stdout --from="A U Thor <author@example.com>" >patch &&
1156 cat >expect <<-\EOF &&
1157 From: A U Thor <author@example.com>
1158
1159 EOF
1160 sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
1161 test_cmp expect patch.head
1162'
1163
a9080475 1164test_expect_success 'in-body headers trigger content encoding' '
d2554c72 1165 test_env GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
a9080475
JK
1166 test_when_finished "git reset --hard HEAD^" &&
1167 git format-patch -1 --stdout --from >patch &&
1168 cat >expect <<-\EOF &&
1169 From: C O Mitter <committer@example.com>
1170 Content-Type: text/plain; charset=UTF-8
1171
1172 From: éxötìc <author@example.com>
1173
1174 EOF
1175 sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
1176 test_cmp expect patch.head
1177'
1178
79133a66
NTND
1179append_signoff()
1180{
1181 C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
1182 git format-patch --stdout --signoff $C^..$C >append_signoff.patch &&
1183 sed -n -e "1,/^---$/p" append_signoff.patch |
1184 egrep -n "^Subject|Sign|^$"
1185}
1186
1187test_expect_success 'signoff: commit with no body' '
1188 append_signoff </dev/null >actual &&
1189 cat <<\EOF | sed "s/EOL$//" >expected &&
11904:Subject: [PATCH] EOL
11918:
11929:Signed-off-by: C O Mitter <committer@example.com>
1193EOF
1194 test_cmp expected actual
1195'
1196
1197test_expect_success 'signoff: commit with only subject' '
1198 echo subject | append_signoff >actual &&
1199 cat >expected <<\EOF &&
12004:Subject: [PATCH] subject
12018:
12029:Signed-off-by: C O Mitter <committer@example.com>
1203EOF
1204 test_cmp expected actual
1205'
1206
1207test_expect_success 'signoff: commit with only subject that does not end with NL' '
1208 printf subject | append_signoff >actual &&
1209 cat >expected <<\EOF &&
12104:Subject: [PATCH] subject
12118:
12129:Signed-off-by: C O Mitter <committer@example.com>
1213EOF
1214 test_cmp expected actual
1215'
1216
1217test_expect_success 'signoff: no existing signoffs' '
1218 append_signoff <<\EOF >actual &&
1219subject
1220
1221body
1222EOF
1223 cat >expected <<\EOF &&
12244:Subject: [PATCH] subject
12258:
122610:
122711:Signed-off-by: C O Mitter <committer@example.com>
1228EOF
1229 test_cmp expected actual
1230'
1231
1232test_expect_success 'signoff: no existing signoffs and no trailing NL' '
1233 printf "subject\n\nbody" | append_signoff >actual &&
1234 cat >expected <<\EOF &&
12354:Subject: [PATCH] subject
12368:
123710:
123811:Signed-off-by: C O Mitter <committer@example.com>
1239EOF
1240 test_cmp expected actual
1241'
1242
1243test_expect_success 'signoff: some random signoff' '
1244 append_signoff <<\EOF >actual &&
1245subject
1246
1247body
1248
1249Signed-off-by: my@house
1250EOF
1251 cat >expected <<\EOF &&
12524:Subject: [PATCH] subject
12538:
125410:
125511:Signed-off-by: my@house
125612:Signed-off-by: C O Mitter <committer@example.com>
1257EOF
1258 test_cmp expected actual
1259'
1260
959a2623
BC
1261test_expect_success 'signoff: misc conforming footer elements' '
1262 append_signoff <<\EOF >actual &&
1263subject
1264
1265body
1266
1267Signed-off-by: my@house
1268(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709)
1269Tested-by: Some One <someone@example.com>
1270Bug: 1234
1271EOF
1272 cat >expected <<\EOF &&
12734:Subject: [PATCH] subject
12748:
127510:
127611:Signed-off-by: my@house
127715:Signed-off-by: C O Mitter <committer@example.com>
1278EOF
1279 test_cmp expected actual
1280'
1281
1282test_expect_success 'signoff: some random signoff-alike' '
79133a66
NTND
1283 append_signoff <<\EOF >actual &&
1284subject
1285
1286body
1287Fooled-by-me: my@house
1288EOF
1289 cat >expected <<\EOF &&
12904:Subject: [PATCH] subject
12918:
129211:
129312:Signed-off-by: C O Mitter <committer@example.com>
1294EOF
1295 test_cmp expected actual
1296'
1297
959a2623 1298test_expect_success 'signoff: not really a signoff' '
79133a66
NTND
1299 append_signoff <<\EOF >actual &&
1300subject
1301
1302I want to mention about Signed-off-by: here.
1303EOF
1304 cat >expected <<\EOF &&
13054:Subject: [PATCH] subject
13068:
13079:I want to mention about Signed-off-by: here.
130810:
130911:Signed-off-by: C O Mitter <committer@example.com>
1310EOF
1311 test_cmp expected actual
1312'
1313
959a2623 1314test_expect_success 'signoff: not really a signoff (2)' '
79133a66
NTND
1315 append_signoff <<\EOF >actual &&
1316subject
1317
1318My unfortunate
1319Signed-off-by: example happens to be wrapped here.
1320EOF
1321 cat >expected <<\EOF &&
13224:Subject: [PATCH] subject
13238:
132410:Signed-off-by: example happens to be wrapped here.
967dfd4d 132511:Signed-off-by: C O Mitter <committer@example.com>
79133a66
NTND
1326EOF
1327 test_cmp expected actual
1328'
1329
959a2623 1330test_expect_success 'signoff: valid S-o-b paragraph in the middle' '
79133a66
NTND
1331 append_signoff <<\EOF >actual &&
1332subject
1333
1334Signed-off-by: my@house
1335Signed-off-by: your@house
1336
1337A lot of houses.
1338EOF
1339 cat >expected <<\EOF &&
13404:Subject: [PATCH] subject
13418:
13429:Signed-off-by: my@house
134310:Signed-off-by: your@house
134411:
134513:
134614:Signed-off-by: C O Mitter <committer@example.com>
1347EOF
1348 test_cmp expected actual
1349'
1350
1351test_expect_success 'signoff: the same signoff at the end' '
1352 append_signoff <<\EOF >actual &&
1353subject
1354
1355body
1356
1357Signed-off-by: C O Mitter <committer@example.com>
1358EOF
1359 cat >expected <<\EOF &&
13604:Subject: [PATCH] subject
13618:
136210:
136311:Signed-off-by: C O Mitter <committer@example.com>
1364EOF
1365 test_cmp expected actual
1366'
1367
1368test_expect_success 'signoff: the same signoff at the end, no trailing NL' '
1369 printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" |
1370 append_signoff >actual &&
1371 cat >expected <<\EOF &&
13724:Subject: [PATCH] subject
13738:
13749:Signed-off-by: C O Mitter <committer@example.com>
1375EOF
1376 test_cmp expected actual
1377'
1378
1379test_expect_success 'signoff: the same signoff NOT at the end' '
1380 append_signoff <<\EOF >actual &&
1381subject
1382
1383body
1384
1385Signed-off-by: C O Mitter <committer@example.com>
1386Signed-off-by: my@house
1387EOF
1388 cat >expected <<\EOF &&
13894:Subject: [PATCH] subject
13908:
139110:
139211:Signed-off-by: C O Mitter <committer@example.com>
139312:Signed-off-by: my@house
1394EOF
1395 test_cmp expected actual
1396'
1397
967dfd4d 1398test_expect_success 'signoff: tolerate garbage in conforming footer' '
79133a66
NTND
1399 append_signoff <<\EOF >actual &&
1400subject
1401
1402body
1403
1404Tested-by: my@house
1405Some Trash
1406Signed-off-by: C O Mitter <committer@example.com>
1407EOF
1408 cat >expected <<\EOF &&
14094:Subject: [PATCH] subject
14108:
141110:
141213:Signed-off-by: C O Mitter <committer@example.com>
967dfd4d
JT
1413EOF
1414 test_cmp expected actual
1415'
1416
1417test_expect_success 'signoff: respect trailer config' '
1418 append_signoff <<\EOF >actual &&
1419subject
1420
1421Myfooter: x
1422Some Trash
1423EOF
1424 cat >expected <<\EOF &&
14254:Subject: [PATCH] subject
14268:
142711:
142812:Signed-off-by: C O Mitter <committer@example.com>
1429EOF
1430 test_cmp expected actual &&
1431
1432 test_config trailer.Myfooter.ifexists add &&
1433 append_signoff <<\EOF >actual &&
1434subject
1435
1436Myfooter: x
1437Some Trash
1438EOF
1439 cat >expected <<\EOF &&
14404:Subject: [PATCH] subject
14418:
144211:Signed-off-by: C O Mitter <committer@example.com>
79133a66
NTND
1443EOF
1444 test_cmp expected actual
1445'
1446
1447test_expect_success 'signoff: footer begins with non-signoff without @ sign' '
1448 append_signoff <<\EOF >actual &&
1449subject
1450
1451body
1452
1453Reviewed-id: Noone
1454Tested-by: my@house
1455Change-id: Ideadbeef
1456Signed-off-by: C O Mitter <committer@example.com>
1457Bug: 1234
1458EOF
1459 cat >expected <<\EOF &&
14604:Subject: [PATCH] subject
14618:
146210:
146314:Signed-off-by: C O Mitter <committer@example.com>
1464EOF
1465 test_cmp expected actual
1466'
1467
787570c7
PYH
1468test_expect_success 'format patch ignores color.ui' '
1469 test_unconfig color.ui &&
1470 git format-patch --stdout -1 >expect &&
1471 test_config color.ui always &&
1472 git format-patch --stdout -1 >actual &&
1473 test_cmp expect actual
1474'
1475
e216cc48
NTND
1476test_expect_success 'cover letter using branch description (1)' '
1477 git checkout rebuild-1 &&
1478 test_config branch.rebuild-1.description hello &&
1479 git format-patch --stdout --cover-letter master >actual &&
1480 grep hello actual >/dev/null
1481'
1482
1483test_expect_success 'cover letter using branch description (2)' '
1484 git checkout rebuild-1 &&
1485 test_config branch.rebuild-1.description hello &&
1486 git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual &&
1487 grep hello actual >/dev/null
1488'
1489
1490test_expect_success 'cover letter using branch description (3)' '
1491 git checkout rebuild-1 &&
1492 test_config branch.rebuild-1.description hello &&
1493 git format-patch --stdout --cover-letter ^master rebuild-1 >actual &&
1494 grep hello actual >/dev/null
1495'
1496
20b630aa
NTND
1497test_expect_success 'cover letter using branch description (4)' '
1498 git checkout rebuild-1 &&
1499 test_config branch.rebuild-1.description hello &&
1500 git format-patch --stdout --cover-letter master.. >actual &&
1501 grep hello actual >/dev/null
1502'
1503
1504test_expect_success 'cover letter using branch description (5)' '
1505 git checkout rebuild-1 &&
1506 test_config branch.rebuild-1.description hello &&
1507 git format-patch --stdout --cover-letter -2 HEAD >actual &&
1508 grep hello actual >/dev/null
1509'
1510
5ee29aef
NTND
1511test_expect_success 'cover letter using branch description (6)' '
1512 git checkout rebuild-1 &&
1513 test_config branch.rebuild-1.description hello &&
1514 git format-patch --stdout --cover-letter -2 >actual &&
1515 grep hello actual >/dev/null
1516'
1517
80d35ca0
FC
1518test_expect_success 'cover letter with nothing' '
1519 git format-patch --stdout --cover-letter >actual &&
1520 test_line_count = 0 actual
1521'
1522
2a4c2607
FC
1523test_expect_success 'cover letter auto' '
1524 mkdir -p tmp &&
1525 test_when_finished "rm -rf tmp;
1526 git config --unset format.coverletter" &&
1527
1528 git config format.coverletter auto &&
1529 git format-patch -o tmp -1 >list &&
1530 test_line_count = 1 list &&
1531 git format-patch -o tmp -2 >list &&
1532 test_line_count = 3 list
1533'
1534
1535test_expect_success 'cover letter auto user override' '
1536 mkdir -p tmp &&
1537 test_when_finished "rm -rf tmp;
1538 git config --unset format.coverletter" &&
1539
1540 git config format.coverletter auto &&
1541 git format-patch -o tmp --cover-letter -1 >list &&
1542 test_line_count = 2 list &&
1543 git format-patch -o tmp --cover-letter -2 >list &&
1544 test_line_count = 3 list &&
1545 git format-patch -o tmp --no-cover-letter -1 >list &&
1546 test_line_count = 1 list &&
1547 git format-patch -o tmp --no-cover-letter -2 >list &&
1548 test_line_count = 2 list
1549'
1550
3a30aa17 1551test_expect_success 'format-patch --zero-commit' '
1552 git format-patch --zero-commit --stdout v2..v1 >patch2 &&
1553 grep "^From " patch2 | sort | uniq >actual &&
8125a58b 1554 echo "From $ZERO_OID Mon Sep 17 00:00:00 2001" >expect &&
3a30aa17 1555 test_cmp expect actual
1556'
1557
06dfc9eb 1558test_expect_success 'From line has expected format' '
1559 git format-patch --stdout v2..v1 >patch2 &&
1560 grep "^From " patch2 >from &&
2ece6ad2 1561 grep "^From $OID_REGEX Mon Sep 17 00:00:00 2001$" patch2 >filtered &&
06dfc9eb 1562 test_cmp from filtered
1563'
1564
bc6bf2d7
AK
1565test_expect_success 'format-patch format.outputDirectory option' '
1566 test_config format.outputDirectory patches &&
1567 rm -fr patches &&
1568 git format-patch master..side &&
1569 test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
1570'
1571
1572test_expect_success 'format-patch -o overrides format.outputDirectory' '
1573 test_config format.outputDirectory patches &&
1574 rm -fr patches patchset &&
1575 git format-patch master..side -o patchset &&
1576 test_path_is_missing patches &&
1577 test_path_is_dir patchset
1578'
1579
fa2ab86d 1580test_expect_success 'format-patch --base' '
6f93d261 1581 git checkout patchid &&
15b76c1f
XY
1582 git format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 &&
1583 git format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 &&
480871e0
JT
1584 echo >expected &&
1585 echo "base-commit: $(git rev-parse HEAD~3)" >>expected &&
6f93d261
SB
1586 echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk "{print \$1}")" >>expected &&
1587 echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk "{print \$1}")" >>expected &&
480871e0 1588 signature >> expected &&
15b76c1f 1589 test_cmp expected actual1 &&
6f93d261
SB
1590 test_cmp expected actual2 &&
1591 echo >fail &&
1592 echo "base-commit: $(git rev-parse HEAD~3)" >>fail &&
1593 echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>fail &&
1594 echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>fail &&
1595 signature >> fail &&
1596 ! test_cmp fail actual1 &&
1597 ! test_cmp fail actual2
fa2ab86d
XY
1598'
1599
1600test_expect_success 'format-patch --base errors out when base commit is in revision list' '
1601 test_must_fail git format-patch --base=HEAD -2 &&
1602 test_must_fail git format-patch --base=HEAD~1 -2 &&
1603 git format-patch --stdout --base=HEAD~2 -2 >patch &&
1604 grep "^base-commit:" patch >actual &&
1605 echo "base-commit: $(git rev-parse HEAD~2)" >expected &&
1606 test_cmp expected actual
1607'
1608
1609test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' '
1610 # For history as below:
1611 #
1612 # ---Q---P---Z---Y---*---X
1613 # \ /
1614 # ------------W
1615 #
1616 # If "format-patch Z..X" is given, P and Z can not be specified as the base commit
1617 git checkout -b topic1 master &&
1618 git rev-parse HEAD >commit-id-base &&
1619 test_commit P &&
1620 git rev-parse HEAD >commit-id-P &&
1621 test_commit Z &&
1622 git rev-parse HEAD >commit-id-Z &&
1623 test_commit Y &&
1624 git checkout -b topic2 master &&
1625 test_commit W &&
1626 git merge topic1 &&
1627 test_commit X &&
1628 test_must_fail git format-patch --base=$(cat commit-id-P) -3 &&
1629 test_must_fail git format-patch --base=$(cat commit-id-Z) -3 &&
1630 git format-patch --stdout --base=$(cat commit-id-base) -3 >patch &&
1631 grep "^base-commit:" patch >actual &&
1632 echo "base-commit: $(cat commit-id-base)" >expected &&
1633 test_cmp expected actual
1634'
1635
3de66517
XY
1636test_expect_success 'format-patch --base=auto' '
1637 git checkout -b upstream master &&
1638 git checkout -b local upstream &&
1639 git branch --set-upstream-to=upstream &&
1640 test_commit N1 &&
1641 test_commit N2 &&
1642 git format-patch --stdout --base=auto -2 >patch &&
1643 grep "^base-commit:" patch >actual &&
1644 echo "base-commit: $(git rev-parse upstream)" >expected &&
1645 test_cmp expected actual
1646'
1647
1648test_expect_success 'format-patch errors out when history involves criss-cross' '
1649 # setup criss-cross history
1650 #
1651 # B---M1---D
1652 # / \ /
1653 # A X
1654 # \ / \
1655 # C---M2---E
1656 #
1657 git checkout master &&
1658 test_commit A &&
1659 git checkout -b xb master &&
1660 test_commit B &&
1661 git checkout -b xc master &&
1662 test_commit C &&
1663 git checkout -b xbc xb -- &&
1664 git merge xc &&
1665 git checkout -b xcb xc -- &&
1666 git branch --set-upstream-to=xbc &&
1667 git merge xb &&
1668 git checkout xbc &&
1669 test_commit D &&
1670 git checkout xcb &&
1671 test_commit E &&
1672 test_must_fail git format-patch --base=auto -1
1673'
1674
bb52995f
XY
1675test_expect_success 'format-patch format.useAutoBaseoption' '
1676 test_when_finished "git config --unset format.useAutoBase" &&
1677 git checkout local &&
1678 git config format.useAutoBase true &&
1679 git format-patch --stdout -1 >patch &&
1680 grep "^base-commit:" patch >actual &&
1681 echo "base-commit: $(git rev-parse upstream)" >expected &&
1682 test_cmp expected actual
1683'
1684
1685test_expect_success 'format-patch --base overrides format.useAutoBase' '
1686 test_when_finished "git config --unset format.useAutoBase" &&
1687 git config format.useAutoBase true &&
1688 git format-patch --stdout --base=HEAD~1 -1 >patch &&
1689 grep "^base-commit:" patch >actual &&
1690 echo "base-commit: $(git rev-parse HEAD~1)" >expected &&
1691 test_cmp expected actual
1692'
1693
480871e0
JT
1694test_expect_success 'format-patch --base with --attach' '
1695 git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch &&
1696 sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \
1697 patch >actual &&
1698 test_write_lines 1 2 >expect &&
1699 test_cmp expect actual
1700'
50cd54ef 1701test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
1702 test_when_finished "rm -fr patches" &&
1703 git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
1704 ! egrep "^--+mimemime" patches/0000*.patch &&
1705 egrep "^--+mimemime$" patches/0001*.patch >output &&
1706 test_line_count = 2 output &&
1707 egrep "^--+mimemime--$" patches/0001*.patch >output &&
1708 test_line_count = 1 output
1709'
480871e0 1710
9f23e040
EW
1711test_expect_success 'format-patch --pretty=mboxrd' '
1712 sp=" " &&
1713 cat >msg <<-INPUT_END &&
1714 mboxrd should escape the body
1715
1716 From could trip up a loose mbox parser
1717 >From extra escape for reversibility
1718 >>From extra escape for reversibility 2
1719 from lower case not escaped
1720 Fromm bad speling not escaped
1721 From with leading space not escaped
1722
1723 F
1724 From
1725 From$sp
1726 From $sp
1727 From $sp
1728 INPUT_END
1729
1730 cat >expect <<-INPUT_END &&
1731 >From could trip up a loose mbox parser
1732 >>From extra escape for reversibility
1733 >>>From extra escape for reversibility 2
1734 from lower case not escaped
1735 Fromm bad speling not escaped
1736 From with leading space not escaped
1737
1738 F
1739 From
1740 From
1741 From
1742 From
1743 INPUT_END
1744
1745 C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
1746 git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
1747 git grep -h --no-index -A11 \
1748 "^>From could trip up a loose mbox parser" patch >actual &&
1749 test_cmp expect actual
1750'
1751
126facf8
ES
1752test_expect_success 'interdiff: setup' '
1753 git checkout -b boop master &&
1754 test_commit fnorp blorp &&
1755 test_commit fleep blorp
1756'
1757
1758test_expect_success 'interdiff: cover-letter' '
1759 sed "y/q/ /" >expect <<-\EOF &&
1760 +fleep
1761 --q
1762 EOF
1763 git format-patch --cover-letter --interdiff=boop~2 -1 boop &&
1764 test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch &&
ee6cbf71 1765 test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch &&
126facf8
ES
1766 sed "1,/^@@ /d; /^-- $/q" <0000-cover-letter.patch >actual &&
1767 test_cmp expect actual
1768'
1769
5ac290f9
ES
1770test_expect_success 'interdiff: reroll-count' '
1771 git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop &&
1772 test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch
1773'
1774
ee6cbf71
ES
1775test_expect_success 'interdiff: solo-patch' '
1776 cat >expect <<-\EOF &&
1777 +fleep
1778
1779 EOF
1780 git format-patch --interdiff=boop~2 -1 boop &&
1781 test_i18ngrep "^Interdiff:$" 0001-fleep.patch &&
1782 sed "1,/^ @@ /d; /^$/q" <0001-fleep.patch >actual &&
1783 test_cmp expect actual
1784'
1785
ece3c67f 1786test_done