c7b625642dd57f4bcb6f7c5aa240cc9c32e15af8
1 #!/bin/sh
2 #
3 # Copyright (c) 2006 Junio C Hamano
4 #
6 test_description='various format-patch tests'
8 . ./test-lib.sh
10 test_expect_success setup '
12 for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
13 cat file >elif &&
14 git add file elif &&
15 git commit -m Initial &&
16 git checkout -b side &&
18 for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
19 test_chmod +x elif &&
20 git commit -m "Side changes #1" &&
22 for i in D E F; do echo "$i"; done >>file &&
23 git update-index file &&
24 git commit -m "Side changes #2" &&
25 git tag C2 &&
27 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
28 git update-index file &&
29 git commit -m "Side changes #3 with \\n backslash-n in it." &&
31 git checkout master &&
32 git diff-tree -p C2 | git apply --index &&
33 git commit -m "Master accepts moral equivalent of #2"
35 '
37 test_expect_success "format-patch --ignore-if-in-upstream" '
39 git format-patch --stdout master..side >patch0 &&
40 cnt=`grep "^From " patch0 | wc -l` &&
41 test $cnt = 3
43 '
45 test_expect_success "format-patch --ignore-if-in-upstream" '
47 git format-patch --stdout \
48 --ignore-if-in-upstream master..side >patch1 &&
49 cnt=`grep "^From " patch1 | wc -l` &&
50 test $cnt = 2
52 '
54 test_expect_success "format-patch result applies" '
56 git checkout -b rebuild-0 master &&
57 git am -3 patch0 &&
58 cnt=`git rev-list master.. | wc -l` &&
59 test $cnt = 2
60 '
62 test_expect_success "format-patch --ignore-if-in-upstream result applies" '
64 git checkout -b rebuild-1 master &&
65 git am -3 patch1 &&
66 cnt=`git rev-list master.. | wc -l` &&
67 test $cnt = 2
68 '
70 test_expect_success 'commit did not screw up the log message' '
72 git cat-file commit side | grep "^Side .* with .* backslash-n"
74 '
76 test_expect_success 'format-patch did not screw up the log message' '
78 grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
79 grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
81 '
83 test_expect_success 'replay did not screw up the log message' '
85 git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
87 '
89 test_expect_success 'extra headers' '
91 git config format.headers "To: R. E. Cipient <rcipient@example.com>
92 " &&
93 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>
94 " &&
95 git format-patch --stdout master..side > patch2 &&
96 sed -e "/^\$/q" patch2 > hdrs2 &&
97 grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs2 &&
98 grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs2
100 '
102 test_expect_success 'extra headers without newlines' '
104 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
105 git config --add format.headers "Cc: S. E. Cipient <scipient@example.com>" &&
106 git format-patch --stdout master..side >patch3 &&
107 sed -e "/^\$/q" patch3 > hdrs3 &&
108 grep "^To: R. E. Cipient <rcipient@example.com>\$" hdrs3 &&
109 grep "^Cc: S. E. Cipient <scipient@example.com>\$" hdrs3
111 '
113 test_expect_success 'extra headers with multiple To:s' '
115 git config --replace-all format.headers "To: R. E. Cipient <rcipient@example.com>" &&
116 git config --add format.headers "To: S. E. Cipient <scipient@example.com>" &&
117 git format-patch --stdout master..side > patch4 &&
118 sed -e "/^\$/q" patch4 > hdrs4 &&
119 grep "^To: R. E. Cipient <rcipient@example.com>,\$" hdrs4 &&
120 grep "^ *S. E. Cipient <scipient@example.com>\$" hdrs4
121 '
123 test_expect_success 'additional command line cc' '
125 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
126 git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 &&
127 grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch5 &&
128 grep "^ *S. E. Cipient <scipient@example.com>\$" patch5
129 '
131 test_expect_success 'command line headers' '
133 git config --unset-all format.headers &&
134 git format-patch --add-header="Cc: R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 &&
135 grep "^Cc: R. E. Cipient <rcipient@example.com>\$" patch6
136 '
138 test_expect_success 'configuration headers and command line headers' '
140 git config --replace-all format.headers "Cc: R. E. Cipient <rcipient@example.com>" &&
141 git format-patch --add-header="Cc: S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 &&
142 grep "^Cc: R. E. Cipient <rcipient@example.com>,\$" patch7 &&
143 grep "^ *S. E. Cipient <scipient@example.com>\$" patch7
144 '
146 test_expect_success 'command line To: header' '
148 git config --unset-all format.headers &&
149 git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 &&
150 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch8
151 '
153 test_expect_success 'configuration To: header' '
155 git config format.to "R. E. Cipient <rcipient@example.com>" &&
156 git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 &&
157 grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9
158 '
160 test_expect_success '--no-to overrides config.to' '
162 git config --replace-all format.to \
163 "R. E. Cipient <rcipient@example.com>" &&
164 git format-patch --no-to --stdout master..side |
165 sed -e "/^\$/q" >patch10 &&
166 ! grep "^To: R. E. Cipient <rcipient@example.com>\$" patch10
167 '
169 test_expect_success '--no-to and --to replaces config.to' '
171 git config --replace-all format.to \
172 "Someone <someone@out.there>" &&
173 git format-patch --no-to --to="Someone Else <else@out.there>" \
174 --stdout master..side |
175 sed -e "/^\$/q" >patch11 &&
176 ! grep "^To: Someone <someone@out.there>\$" patch11 &&
177 grep "^To: Someone Else <else@out.there>\$" patch11
178 '
180 test_expect_success '--no-cc overrides config.cc' '
182 git config --replace-all format.cc \
183 "C. E. Cipient <rcipient@example.com>" &&
184 git format-patch --no-cc --stdout master..side |
185 sed -e "/^\$/q" >patch12 &&
186 ! grep "^Cc: C. E. Cipient <rcipient@example.com>\$" patch12
187 '
189 test_expect_success '--no-add-headers overrides config.headers' '
191 git config --replace-all format.headers \
192 "Header1: B. E. Cipient <rcipient@example.com>" &&
193 git format-patch --no-add-headers --stdout master..side |
194 sed -e "/^\$/q" >patch13 &&
195 ! grep "^Header1: B. E. Cipient <rcipient@example.com>\$" patch13
196 '
198 test_expect_success 'multiple files' '
200 rm -rf patches/ &&
201 git checkout side &&
202 git format-patch -o patches/ master &&
203 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
204 '
206 check_threading () {
207 expect="$1" &&
208 shift &&
209 (git format-patch --stdout "$@"; echo $? > status.out) |
210 # Prints everything between the Message-ID and In-Reply-To,
211 # and replaces all Message-ID-lookalikes by a sequence number
212 perl -ne '
213 if (/^(message-id|references|in-reply-to)/i) {
214 $printing = 1;
215 } elsif (/^\S/) {
216 $printing = 0;
217 }
218 if ($printing) {
219 $h{$1}=$i++ if (/<([^>]+)>/ and !exists $h{$1});
220 for $k (keys %h) {s/$k/$h{$k}/};
221 print;
222 }
223 print "---\n" if /^From /i;
224 ' > actual &&
225 test 0 = "$(cat status.out)" &&
226 test_cmp "$expect" actual
227 }
229 cat >> expect.no-threading <<EOF
230 ---
231 ---
232 ---
233 EOF
235 test_expect_success 'no threading' '
236 git checkout side &&
237 check_threading expect.no-threading master
238 '
240 cat > expect.thread <<EOF
241 ---
242 Message-Id: <0>
243 ---
244 Message-Id: <1>
245 In-Reply-To: <0>
246 References: <0>
247 ---
248 Message-Id: <2>
249 In-Reply-To: <0>
250 References: <0>
251 EOF
253 test_expect_success 'thread' '
254 check_threading expect.thread --thread master
255 '
257 cat > expect.in-reply-to <<EOF
258 ---
259 Message-Id: <0>
260 In-Reply-To: <1>
261 References: <1>
262 ---
263 Message-Id: <2>
264 In-Reply-To: <1>
265 References: <1>
266 ---
267 Message-Id: <3>
268 In-Reply-To: <1>
269 References: <1>
270 EOF
272 test_expect_success 'thread in-reply-to' '
273 check_threading expect.in-reply-to --in-reply-to="<test.message>" \
274 --thread master
275 '
277 cat > expect.cover-letter <<EOF
278 ---
279 Message-Id: <0>
280 ---
281 Message-Id: <1>
282 In-Reply-To: <0>
283 References: <0>
284 ---
285 Message-Id: <2>
286 In-Reply-To: <0>
287 References: <0>
288 ---
289 Message-Id: <3>
290 In-Reply-To: <0>
291 References: <0>
292 EOF
294 test_expect_success 'thread cover-letter' '
295 check_threading expect.cover-letter --cover-letter --thread master
296 '
298 cat > expect.cl-irt <<EOF
299 ---
300 Message-Id: <0>
301 In-Reply-To: <1>
302 References: <1>
303 ---
304 Message-Id: <2>
305 In-Reply-To: <0>
306 References: <1>
307 <0>
308 ---
309 Message-Id: <3>
310 In-Reply-To: <0>
311 References: <1>
312 <0>
313 ---
314 Message-Id: <4>
315 In-Reply-To: <0>
316 References: <1>
317 <0>
318 EOF
320 test_expect_success 'thread cover-letter in-reply-to' '
321 check_threading expect.cl-irt --cover-letter \
322 --in-reply-to="<test.message>" --thread master
323 '
325 test_expect_success 'thread explicit shallow' '
326 check_threading expect.cl-irt --cover-letter \
327 --in-reply-to="<test.message>" --thread=shallow master
328 '
330 cat > expect.deep <<EOF
331 ---
332 Message-Id: <0>
333 ---
334 Message-Id: <1>
335 In-Reply-To: <0>
336 References: <0>
337 ---
338 Message-Id: <2>
339 In-Reply-To: <1>
340 References: <0>
341 <1>
342 EOF
344 test_expect_success 'thread deep' '
345 check_threading expect.deep --thread=deep master
346 '
348 cat > expect.deep-irt <<EOF
349 ---
350 Message-Id: <0>
351 In-Reply-To: <1>
352 References: <1>
353 ---
354 Message-Id: <2>
355 In-Reply-To: <0>
356 References: <1>
357 <0>
358 ---
359 Message-Id: <3>
360 In-Reply-To: <2>
361 References: <1>
362 <0>
363 <2>
364 EOF
366 test_expect_success 'thread deep in-reply-to' '
367 check_threading expect.deep-irt --thread=deep \
368 --in-reply-to="<test.message>" master
369 '
371 cat > expect.deep-cl <<EOF
372 ---
373 Message-Id: <0>
374 ---
375 Message-Id: <1>
376 In-Reply-To: <0>
377 References: <0>
378 ---
379 Message-Id: <2>
380 In-Reply-To: <1>
381 References: <0>
382 <1>
383 ---
384 Message-Id: <3>
385 In-Reply-To: <2>
386 References: <0>
387 <1>
388 <2>
389 EOF
391 test_expect_success 'thread deep cover-letter' '
392 check_threading expect.deep-cl --cover-letter --thread=deep master
393 '
395 cat > expect.deep-cl-irt <<EOF
396 ---
397 Message-Id: <0>
398 In-Reply-To: <1>
399 References: <1>
400 ---
401 Message-Id: <2>
402 In-Reply-To: <0>
403 References: <1>
404 <0>
405 ---
406 Message-Id: <3>
407 In-Reply-To: <2>
408 References: <1>
409 <0>
410 <2>
411 ---
412 Message-Id: <4>
413 In-Reply-To: <3>
414 References: <1>
415 <0>
416 <2>
417 <3>
418 EOF
420 test_expect_success 'thread deep cover-letter in-reply-to' '
421 check_threading expect.deep-cl-irt --cover-letter \
422 --in-reply-to="<test.message>" --thread=deep master
423 '
425 test_expect_success 'thread via config' '
426 git config format.thread true &&
427 check_threading expect.thread master
428 '
430 test_expect_success 'thread deep via config' '
431 git config format.thread deep &&
432 check_threading expect.deep master
433 '
435 test_expect_success 'thread config + override' '
436 git config format.thread deep &&
437 check_threading expect.thread --thread master
438 '
440 test_expect_success 'thread config + --no-thread' '
441 git config format.thread deep &&
442 check_threading expect.no-threading --no-thread master
443 '
445 test_expect_success 'excessive subject' '
447 rm -rf patches/ &&
448 git checkout side &&
449 for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >>file &&
450 git update-index file &&
451 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." &&
452 git format-patch -o patches/ master..side &&
453 ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
454 '
456 test_expect_success 'cover-letter inherits diff options' '
458 git mv file foo &&
459 git commit -m foo &&
460 git format-patch --cover-letter -1 &&
461 ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
462 git format-patch --cover-letter -1 -M &&
463 grep "file => foo .* 0 *\$" 0000-cover-letter.patch
465 '
467 cat > expect << EOF
468 This is an excessively long subject line for a message due to the
469 habit some projects have of not having a short, one-line subject at
470 the start of the commit message, but rather sticking a whole
471 paragraph right at the start as the only thing in the commit
472 message. It had better not become the filename for the patch.
473 foo
475 EOF
477 test_expect_success 'shortlog of cover-letter wraps overly-long onelines' '
479 git format-patch --cover-letter -2 &&
480 sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output &&
481 test_cmp expect output
483 '
485 cat > expect << EOF
486 ---
487 file | 16 ++++++++++++++++
488 1 files changed, 16 insertions(+), 0 deletions(-)
490 diff --git a/file b/file
491 index 40f36c6..2dc5c23 100644
492 --- a/file
493 +++ b/file
494 @@ -13,4 +13,20 @@ C
495 10
496 D
497 E
498 F
499 +5
500 EOF
502 test_expect_success 'format-patch respects -U' '
504 git format-patch -U4 -2 &&
505 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
506 test_cmp expect output
508 '
510 cat > expect << EOF
512 diff --git a/file b/file
513 index 40f36c6..2dc5c23 100644
514 --- a/file
515 +++ b/file
516 @@ -14,3 +14,19 @@ C
517 D
518 E
519 F
520 +5
521 EOF
523 test_expect_success 'format-patch -p suppresses stat' '
525 git format-patch -p -2 &&
526 sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output &&
527 test_cmp expect output
529 '
531 test_expect_success 'format-patch from a subdirectory (1)' '
532 filename=$(
533 rm -rf sub &&
534 mkdir -p sub/dir &&
535 cd sub/dir &&
536 git format-patch -1
537 ) &&
538 case "$filename" in
539 0*)
540 ;; # ok
541 *)
542 echo "Oops? $filename"
543 false
544 ;;
545 esac &&
546 test -f "$filename"
547 '
549 test_expect_success 'format-patch from a subdirectory (2)' '
550 filename=$(
551 rm -rf sub &&
552 mkdir -p sub/dir &&
553 cd sub/dir &&
554 git format-patch -1 -o ..
555 ) &&
556 case "$filename" in
557 ../0*)
558 ;; # ok
559 *)
560 echo "Oops? $filename"
561 false
562 ;;
563 esac &&
564 basename=$(expr "$filename" : ".*/\(.*\)") &&
565 test -f "sub/$basename"
566 '
568 test_expect_success 'format-patch from a subdirectory (3)' '
569 rm -f 0* &&
570 filename=$(
571 rm -rf sub &&
572 mkdir -p sub/dir &&
573 cd sub/dir &&
574 git format-patch -1 -o "$TRASH_DIRECTORY"
575 ) &&
576 basename=$(expr "$filename" : ".*/\(.*\)") &&
577 test -f "$basename"
578 '
580 test_expect_success 'format-patch --in-reply-to' '
581 git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 &&
582 grep "^In-Reply-To: <baz@foo.bar>" patch8 &&
583 grep "^References: <baz@foo.bar>" patch8
584 '
586 test_expect_success 'format-patch --signoff' '
587 git format-patch -1 --signoff --stdout |
588 grep "^Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
589 '
591 echo "fatal: --name-only does not make sense" > expect.name-only
592 echo "fatal: --name-status does not make sense" > expect.name-status
593 echo "fatal: --check does not make sense" > expect.check
595 test_expect_success 'options no longer allowed for format-patch' '
596 test_must_fail git format-patch --name-only 2> output &&
597 test_cmp expect.name-only output &&
598 test_must_fail git format-patch --name-status 2> output &&
599 test_cmp expect.name-status output &&
600 test_must_fail git format-patch --check 2> output &&
601 test_cmp expect.check output'
603 test_expect_success 'format-patch --numstat should produce a patch' '
604 git format-patch --numstat --stdout master..side > output &&
605 test 6 = $(grep "^diff --git a/" output | wc -l)'
607 test_expect_success 'format-patch -- <path>' '
608 git format-patch master..side -- file 2>error &&
609 ! grep "Use .--" error
610 '
612 test_done