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