am: fix signoff when other trailers are present
[git/git.git] / t / t4150-am.sh
1 #!/bin/sh
2
3 test_description='git am running'
4
5 . ./test-lib.sh
6
7 test_expect_success 'setup: messages' '
8 cat >msg <<-\EOF &&
9 second
10
11 Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy
12 eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
13 voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
14 kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem
15 ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
16 tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
17 vero eos et accusam et justo duo dolores et ea rebum.
18
19 EOF
20 qz_to_tab_space <<-\EOF >>msg &&
21 QDuis autem vel eum iriure dolor in hendrerit in vulputate velit
22 Qesse molestie consequat, vel illum dolore eu feugiat nulla facilisis
23 Qat vero eros et accumsan et iusto odio dignissim qui blandit
24 Qpraesent luptatum zzril delenit augue duis dolore te feugait nulla
25 Qfacilisi.
26 EOF
27 cat >>msg <<-\EOF &&
28
29 Lorem ipsum dolor sit amet,
30 consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
31 laoreet dolore magna aliquam erat volutpat.
32
33 git
34 ---
35 +++
36
37 Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
38 lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure
39 dolor in hendrerit in vulputate velit esse molestie consequat, vel illum
40 dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
41 dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te
42 feugait nulla facilisi.
43
44 Reported-by: A N Other <a.n.other@example.com>
45 EOF
46
47 cat >failmail <<-\EOF &&
48 From foo@example.com Fri May 23 10:43:49 2008
49 From: foo@example.com
50 To: bar@example.com
51 Subject: Re: [RFC/PATCH] git-foo.sh
52 Date: Fri, 23 May 2008 05:23:42 +0200
53
54 Sometimes we have to find out that there'\''s nothing left.
55
56 EOF
57
58 cat >pine <<-\EOF &&
59 From MAILER-DAEMON Fri May 23 10:43:49 2008
60 Date: 23 May 2008 05:23:42 +0200
61 From: Mail System Internal Data <MAILER-DAEMON@example.com>
62 Subject: DON'\''T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
63 Message-ID: <foo-0001@example.com>
64
65 This text is part of the internal format of your mail folder, and is not
66 a real message. It is created automatically by the mail system software.
67 If deleted, important folder data will be lost, and it will be re-created
68 with the data reset to initial values.
69
70 EOF
71
72 cat >scissors-msg <<-\EOF &&
73 Test git-am with scissors line
74
75 This line should be included in the commit message.
76 EOF
77
78 cat - scissors-msg >no-scissors-msg <<-\EOF &&
79 This line should not be included in the commit message with --scissors enabled.
80
81 - - >8 - - remove everything above this line - - >8 - -
82
83 EOF
84
85 signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
86 '
87
88 test_expect_success setup '
89 echo hello >file &&
90 git add file &&
91 test_tick &&
92 git commit -m first &&
93 git tag first &&
94
95 echo world >>file &&
96 git add file &&
97 test_tick &&
98 git commit -F msg &&
99 git tag second &&
100
101 git format-patch --stdout first >patch1 &&
102 {
103 echo "Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" &&
104 echo "X-Fake-Field: Line One" &&
105 echo "X-Fake-Field: Line Two" &&
106 echo "X-Fake-Field: Line Three" &&
107 git format-patch --stdout first | sed -e "1d"
108 } > patch1.eml &&
109 {
110 echo "X-Fake-Field: Line One" &&
111 echo "X-Fake-Field: Line Two" &&
112 echo "X-Fake-Field: Line Three" &&
113 git format-patch --stdout first | sed -e "1d"
114 } | append_cr >patch1-crlf.eml &&
115 {
116 printf "%255s\\n" ""
117 echo "X-Fake-Field: Line One" &&
118 echo "X-Fake-Field: Line Two" &&
119 echo "X-Fake-Field: Line Three" &&
120 git format-patch --stdout first | sed -e "1d"
121 } > patch1-ws.eml &&
122 {
123 sed -ne "1p" msg &&
124 echo &&
125 echo "From: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" &&
126 echo "Date: $GIT_AUTHOR_DATE" &&
127 echo &&
128 sed -e "1,2d" msg &&
129 echo "---" &&
130 git diff-tree --no-commit-id --stat -p second
131 } >patch1-stgit.eml &&
132 mkdir stgit-series &&
133 cp patch1-stgit.eml stgit-series/patch &&
134 {
135 echo "# This series applies on GIT commit $(git rev-parse first)" &&
136 echo "patch"
137 } >stgit-series/series &&
138 {
139 echo "# HG changeset patch" &&
140 echo "# User $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" &&
141 echo "# Date $test_tick 25200" &&
142 echo "# $(git show --pretty="%aD" -s second)" &&
143 echo "# Node ID $_z40" &&
144 echo "# Parent $_z40" &&
145 cat msg &&
146 echo &&
147 git diff-tree --no-commit-id -p second
148 } >patch1-hg.eml &&
149
150
151 echo scissors-file >scissors-file &&
152 git add scissors-file &&
153 git commit -F scissors-msg &&
154 git tag scissors &&
155 git format-patch --stdout scissors^ >scissors-patch.eml &&
156 git reset --hard HEAD^ &&
157
158 echo no-scissors-file >no-scissors-file &&
159 git add no-scissors-file &&
160 git commit -F no-scissors-msg &&
161 git tag no-scissors &&
162 git format-patch --stdout no-scissors^ >no-scissors-patch.eml &&
163 git reset --hard HEAD^ &&
164
165 sed -n -e "3,\$p" msg >file &&
166 git add file &&
167 test_tick &&
168 git commit -m third &&
169
170 git format-patch --stdout first >patch2 &&
171
172 git checkout -b lorem &&
173 sed -n -e "11,\$p" msg >file &&
174 head -n 9 msg >>file &&
175 test_tick &&
176 git commit -a -m "moved stuff" &&
177
178 echo goodbye >another &&
179 git add another &&
180 test_tick &&
181 git commit -m "added another file" &&
182
183 git format-patch --stdout master >lorem-move.patch &&
184 git format-patch --no-prefix --stdout master >lorem-zero.patch &&
185
186 git checkout -b rename &&
187 git mv file renamed &&
188 git commit -m "renamed a file" &&
189
190 git format-patch -M --stdout lorem >rename.patch &&
191
192 git reset --soft lorem^ &&
193 git commit -m "renamed a file and added another" &&
194
195 git format-patch -M --stdout lorem^ >rename-add.patch &&
196
197 # reset time
198 sane_unset test_tick &&
199 test_tick
200 '
201
202 test_expect_success 'am applies patch correctly' '
203 rm -fr .git/rebase-apply &&
204 git reset --hard &&
205 git checkout first &&
206 test_tick &&
207 git am <patch1 &&
208 test_path_is_missing .git/rebase-apply &&
209 git diff --exit-code second &&
210 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
211 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
212 '
213
214 test_expect_success 'am fails if index is dirty' '
215 test_when_finished "rm -f dirtyfile" &&
216 rm -fr .git/rebase-apply &&
217 git reset --hard &&
218 git checkout first &&
219 echo dirtyfile >dirtyfile &&
220 git add dirtyfile &&
221 test_must_fail git am patch1 &&
222 test_path_is_dir .git/rebase-apply &&
223 test_cmp_rev first HEAD
224 '
225
226 test_expect_success 'am applies patch e-mail not in a mbox' '
227 rm -fr .git/rebase-apply &&
228 git reset --hard &&
229 git checkout first &&
230 git am patch1.eml &&
231 test_path_is_missing .git/rebase-apply &&
232 git diff --exit-code second &&
233 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
234 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
235 '
236
237 test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
238 rm -fr .git/rebase-apply &&
239 git reset --hard &&
240 git checkout first &&
241 git am patch1-crlf.eml &&
242 test_path_is_missing .git/rebase-apply &&
243 git diff --exit-code second &&
244 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
245 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
246 '
247
248 test_expect_success 'am applies patch e-mail with preceding whitespace' '
249 rm -fr .git/rebase-apply &&
250 git reset --hard &&
251 git checkout first &&
252 git am patch1-ws.eml &&
253 test_path_is_missing .git/rebase-apply &&
254 git diff --exit-code second &&
255 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
256 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
257 '
258
259 test_expect_success 'am applies stgit patch' '
260 rm -fr .git/rebase-apply &&
261 git checkout -f first &&
262 git am patch1-stgit.eml &&
263 test_path_is_missing .git/rebase-apply &&
264 git diff --exit-code second &&
265 test_cmp_rev second HEAD &&
266 test_cmp_rev second^ HEAD^
267 '
268
269 test_expect_success 'am --patch-format=stgit applies stgit patch' '
270 rm -fr .git/rebase-apply &&
271 git checkout -f first &&
272 git am --patch-format=stgit <patch1-stgit.eml &&
273 test_path_is_missing .git/rebase-apply &&
274 git diff --exit-code second &&
275 test_cmp_rev second HEAD &&
276 test_cmp_rev second^ HEAD^
277 '
278
279 test_expect_success 'am applies stgit series' '
280 rm -fr .git/rebase-apply &&
281 git checkout -f first &&
282 git am stgit-series/series &&
283 test_path_is_missing .git/rebase-apply &&
284 git diff --exit-code second &&
285 test_cmp_rev second HEAD &&
286 test_cmp_rev second^ HEAD^
287 '
288
289 test_expect_success 'am applies hg patch' '
290 rm -fr .git/rebase-apply &&
291 git checkout -f first &&
292 git am patch1-hg.eml &&
293 test_path_is_missing .git/rebase-apply &&
294 git diff --exit-code second &&
295 test_cmp_rev second HEAD &&
296 test_cmp_rev second^ HEAD^
297 '
298
299 test_expect_success 'am --patch-format=hg applies hg patch' '
300 rm -fr .git/rebase-apply &&
301 git checkout -f first &&
302 git am --patch-format=hg <patch1-hg.eml &&
303 test_path_is_missing .git/rebase-apply &&
304 git diff --exit-code second &&
305 test_cmp_rev second HEAD &&
306 test_cmp_rev second^ HEAD^
307 '
308
309 test_expect_success 'am with applypatch-msg hook' '
310 test_when_finished "rm -f .git/hooks/applypatch-msg" &&
311 rm -fr .git/rebase-apply &&
312 git reset --hard &&
313 git checkout first &&
314 mkdir -p .git/hooks &&
315 write_script .git/hooks/applypatch-msg <<-\EOF &&
316 cat "$1" >actual-msg &&
317 echo hook-message >"$1"
318 EOF
319 git am patch1 &&
320 test_path_is_missing .git/rebase-apply &&
321 git diff --exit-code second &&
322 echo hook-message >expected &&
323 git log -1 --format=format:%B >actual &&
324 test_cmp expected actual &&
325 git log -1 --format=format:%B second >expected &&
326 test_cmp expected actual-msg
327 '
328
329 test_expect_success 'am with failing applypatch-msg hook' '
330 test_when_finished "rm -f .git/hooks/applypatch-msg" &&
331 rm -fr .git/rebase-apply &&
332 git reset --hard &&
333 git checkout first &&
334 mkdir -p .git/hooks &&
335 write_script .git/hooks/applypatch-msg <<-\EOF &&
336 exit 1
337 EOF
338 test_must_fail git am patch1 &&
339 test_path_is_dir .git/rebase-apply &&
340 git diff --exit-code first &&
341 test_cmp_rev first HEAD
342 '
343
344 test_expect_success 'am with pre-applypatch hook' '
345 test_when_finished "rm -f .git/hooks/pre-applypatch" &&
346 rm -fr .git/rebase-apply &&
347 git reset --hard &&
348 git checkout first &&
349 mkdir -p .git/hooks &&
350 write_script .git/hooks/pre-applypatch <<-\EOF &&
351 git diff first >diff.actual
352 exit 0
353 EOF
354 git am patch1 &&
355 test_path_is_missing .git/rebase-apply &&
356 git diff --exit-code second &&
357 test_cmp_rev second HEAD &&
358 git diff first..second >diff.expected &&
359 test_cmp diff.expected diff.actual
360 '
361
362 test_expect_success 'am with failing pre-applypatch hook' '
363 test_when_finished "rm -f .git/hooks/pre-applypatch" &&
364 rm -fr .git/rebase-apply &&
365 git reset --hard &&
366 git checkout first &&
367 mkdir -p .git/hooks &&
368 write_script .git/hooks/pre-applypatch <<-\EOF &&
369 exit 1
370 EOF
371 test_must_fail git am patch1 &&
372 test_path_is_dir .git/rebase-apply &&
373 git diff --exit-code second &&
374 test_cmp_rev first HEAD
375 '
376
377 test_expect_success 'am with post-applypatch hook' '
378 test_when_finished "rm -f .git/hooks/post-applypatch" &&
379 rm -fr .git/rebase-apply &&
380 git reset --hard &&
381 git checkout first &&
382 mkdir -p .git/hooks &&
383 write_script .git/hooks/post-applypatch <<-\EOF &&
384 git rev-parse HEAD >head.actual
385 git diff second >diff.actual
386 exit 0
387 EOF
388 git am patch1 &&
389 test_path_is_missing .git/rebase-apply &&
390 test_cmp_rev second HEAD &&
391 git rev-parse second >head.expected &&
392 test_cmp head.expected head.actual &&
393 git diff second >diff.expected &&
394 test_cmp diff.expected diff.actual
395 '
396
397 test_expect_success 'am with failing post-applypatch hook' '
398 test_when_finished "rm -f .git/hooks/post-applypatch" &&
399 rm -fr .git/rebase-apply &&
400 git reset --hard &&
401 git checkout first &&
402 mkdir -p .git/hooks &&
403 write_script .git/hooks/post-applypatch <<-\EOF &&
404 git rev-parse HEAD >head.actual
405 exit 1
406 EOF
407 git am patch1 &&
408 test_path_is_missing .git/rebase-apply &&
409 git diff --exit-code second &&
410 test_cmp_rev second HEAD &&
411 git rev-parse second >head.expected &&
412 test_cmp head.expected head.actual
413 '
414
415 test_expect_success 'am --scissors cuts the message at the scissors line' '
416 rm -fr .git/rebase-apply &&
417 git reset --hard &&
418 git checkout second &&
419 git am --scissors scissors-patch.eml &&
420 test_path_is_missing .git/rebase-apply &&
421 git diff --exit-code scissors &&
422 test_cmp_rev scissors HEAD
423 '
424
425 test_expect_success 'am --no-scissors overrides mailinfo.scissors' '
426 rm -fr .git/rebase-apply &&
427 git reset --hard &&
428 git checkout second &&
429 test_config mailinfo.scissors true &&
430 git am --no-scissors no-scissors-patch.eml &&
431 test_path_is_missing .git/rebase-apply &&
432 git diff --exit-code no-scissors &&
433 test_cmp_rev no-scissors HEAD
434 '
435
436 test_expect_success 'setup: new author and committer' '
437 GIT_AUTHOR_NAME="Another Thor" &&
438 GIT_AUTHOR_EMAIL="a.thor@example.com" &&
439 GIT_COMMITTER_NAME="Co M Miter" &&
440 GIT_COMMITTER_EMAIL="c.miter@example.com" &&
441 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
442 '
443
444 compare () {
445 a=$(git cat-file commit "$2" | grep "^$1 ") &&
446 b=$(git cat-file commit "$3" | grep "^$1 ") &&
447 test "$a" = "$b"
448 }
449
450 test_expect_success 'am changes committer and keeps author' '
451 test_tick &&
452 rm -fr .git/rebase-apply &&
453 git reset --hard &&
454 git checkout first &&
455 git am patch2 &&
456 test_path_is_missing .git/rebase-apply &&
457 test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
458 git diff --exit-code master..HEAD &&
459 git diff --exit-code master^..HEAD^ &&
460 compare author master HEAD &&
461 compare author master^ HEAD^ &&
462 test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
463 "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
464 '
465
466 test_expect_success 'am --signoff adds Signed-off-by: line' '
467 rm -fr .git/rebase-apply &&
468 git reset --hard &&
469 git checkout -b master2 first &&
470 git am --signoff <patch2 &&
471 {
472 printf "third\n\nSigned-off-by: %s <%s>\n\n" \
473 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
474 cat msg &&
475 printf "Signed-off-by: %s <%s>\n\n" \
476 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
477 } >expected-log &&
478 git log --pretty=%B -2 HEAD >actual &&
479 test_cmp expected-log actual
480 '
481
482 test_expect_success 'am stays in branch' '
483 echo refs/heads/master2 >expected &&
484 git symbolic-ref HEAD >actual &&
485 test_cmp expected actual
486 '
487
488 test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
489 git format-patch --stdout first >patch3 &&
490 git reset --hard first &&
491 git am --signoff <patch3 &&
492 git log --pretty=%B -2 HEAD >actual &&
493 test_cmp expected-log actual
494 '
495
496 test_expect_success 'am --signoff adds Signed-off-by: if another author is preset' '
497 NAME="A N Other" &&
498 EMAIL="a.n.other@example.com" &&
499 {
500 printf "third\n\nSigned-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
501 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
502 "$NAME" "$EMAIL" &&
503 cat msg &&
504 printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
505 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
506 "$NAME" "$EMAIL"
507 } >expected-log &&
508 git reset --hard first &&
509 GIT_COMMITTER_NAME="$NAME" GIT_COMMITTER_EMAIL="$EMAIL" \
510 git am --signoff <patch3 &&
511 git log --pretty=%B -2 HEAD >actual &&
512 test_cmp expected-log actual
513 '
514
515 test_expect_success 'am --signoff duplicates Signed-off-by: if it is not the last one' '
516 NAME="A N Other" &&
517 EMAIL="a.n.other@example.com" &&
518 {
519 printf "third\n\nSigned-off-by: %s <%s>\n\
520 Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
521 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
522 "$NAME" "$EMAIL" \
523 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
524 cat msg &&
525 printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\
526 Signed-off-by: %s <%s>\n\n" \
527 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
528 "$NAME" "$EMAIL" \
529 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
530 } >expected-log &&
531 git format-patch --stdout first >patch3 &&
532 git reset --hard first &&
533 git am --signoff <patch3 &&
534 git log --pretty=%B -2 HEAD >actual &&
535 test_cmp expected-log actual
536 '
537
538 test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
539 git format-patch --stdout HEAD^ >tmp &&
540 sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," tmp >patch4 &&
541 git reset --hard HEAD^ &&
542 git am <patch4 &&
543 git rev-parse HEAD >expected &&
544 git rev-parse master2 >actual &&
545 test_cmp expected actual
546 '
547
548 test_expect_success 'am --keep really keeps the subject' '
549 rm -fr .git/rebase-apply &&
550 git reset --hard &&
551 git checkout HEAD^ &&
552 git am --keep patch4 &&
553 test_path_is_missing .git/rebase-apply &&
554 git cat-file commit HEAD >actual &&
555 grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
556 '
557
558 test_expect_success 'am --keep-non-patch really keeps the non-patch part' '
559 rm -fr .git/rebase-apply &&
560 git reset --hard &&
561 git checkout HEAD^ &&
562 git am --keep-non-patch patch4 &&
563 test_path_is_missing .git/rebase-apply &&
564 git cat-file commit HEAD >actual &&
565 grep "^\[foo\] third" actual
566 '
567
568 test_expect_success 'setup am -3' '
569 rm -fr .git/rebase-apply &&
570 git reset --hard &&
571 git checkout -b base3way master2 &&
572 sed -n -e "3,\$p" msg >file &&
573 head -n 9 msg >>file &&
574 git add file &&
575 test_tick &&
576 git commit -m "copied stuff"
577 '
578
579 test_expect_success 'am -3 falls back to 3-way merge' '
580 rm -fr .git/rebase-apply &&
581 git reset --hard &&
582 git checkout -b lorem2 base3way &&
583 git am -3 lorem-move.patch &&
584 test_path_is_missing .git/rebase-apply &&
585 git diff --exit-code lorem
586 '
587
588 test_expect_success 'am -3 -p0 can read --no-prefix patch' '
589 rm -fr .git/rebase-apply &&
590 git reset --hard &&
591 git checkout -b lorem3 base3way &&
592 git am -3 -p0 lorem-zero.patch &&
593 test_path_is_missing .git/rebase-apply &&
594 git diff --exit-code lorem
595 '
596
597 test_expect_success 'am with config am.threeWay falls back to 3-way merge' '
598 rm -fr .git/rebase-apply &&
599 git reset --hard &&
600 git checkout -b lorem4 base3way &&
601 test_config am.threeWay 1 &&
602 git am lorem-move.patch &&
603 test_path_is_missing .git/rebase-apply &&
604 git diff --exit-code lorem
605 '
606
607 test_expect_success 'am with config am.threeWay overridden by --no-3way' '
608 rm -fr .git/rebase-apply &&
609 git reset --hard &&
610 git checkout -b lorem5 base3way &&
611 test_config am.threeWay 1 &&
612 test_must_fail git am --no-3way lorem-move.patch &&
613 test_path_is_dir .git/rebase-apply
614 '
615
616 test_expect_success 'am can rename a file' '
617 grep "^rename from" rename.patch &&
618 rm -fr .git/rebase-apply &&
619 git reset --hard &&
620 git checkout lorem^0 &&
621 git am rename.patch &&
622 test_path_is_missing .git/rebase-apply &&
623 git update-index --refresh &&
624 git diff --exit-code rename
625 '
626
627 test_expect_success 'am -3 can rename a file' '
628 grep "^rename from" rename.patch &&
629 rm -fr .git/rebase-apply &&
630 git reset --hard &&
631 git checkout lorem^0 &&
632 git am -3 rename.patch &&
633 test_path_is_missing .git/rebase-apply &&
634 git update-index --refresh &&
635 git diff --exit-code rename
636 '
637
638 test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
639 grep "^rename from" rename-add.patch &&
640 rm -fr .git/rebase-apply &&
641 git reset --hard &&
642 git checkout lorem^0 &&
643 git am -3 rename-add.patch &&
644 test_path_is_missing .git/rebase-apply &&
645 git update-index --refresh &&
646 git diff --exit-code rename
647 '
648
649 test_expect_success 'am -3 -q is quiet' '
650 rm -fr .git/rebase-apply &&
651 git checkout -f lorem2 &&
652 git reset base3way --hard &&
653 git am -3 -q lorem-move.patch >output.out 2>&1 &&
654 ! test -s output.out
655 '
656
657 test_expect_success 'am pauses on conflict' '
658 rm -fr .git/rebase-apply &&
659 git reset --hard &&
660 git checkout lorem2^^ &&
661 test_must_fail git am lorem-move.patch &&
662 test -d .git/rebase-apply
663 '
664
665 test_expect_success 'am --skip works' '
666 echo goodbye >expected &&
667 git am --skip &&
668 test_path_is_missing .git/rebase-apply &&
669 git diff --exit-code lorem2^^ -- file &&
670 test_cmp expected another
671 '
672
673 test_expect_success 'am --abort removes a stray directory' '
674 mkdir .git/rebase-apply &&
675 git am --abort &&
676 test_path_is_missing .git/rebase-apply
677 '
678
679 test_expect_success 'am refuses patches when paused' '
680 rm -fr .git/rebase-apply &&
681 git reset --hard &&
682 git checkout lorem2^^ &&
683
684 test_must_fail git am lorem-move.patch &&
685 test_path_is_dir .git/rebase-apply &&
686 test_cmp_rev lorem2^^ HEAD &&
687
688 test_must_fail git am <lorem-move.patch &&
689 test_path_is_dir .git/rebase-apply &&
690 test_cmp_rev lorem2^^ HEAD
691 '
692
693 test_expect_success 'am --resolved works' '
694 echo goodbye >expected &&
695 rm -fr .git/rebase-apply &&
696 git reset --hard &&
697 git checkout lorem2^^ &&
698 test_must_fail git am lorem-move.patch &&
699 test -d .git/rebase-apply &&
700 echo resolved >>file &&
701 git add file &&
702 git am --resolved &&
703 test_path_is_missing .git/rebase-apply &&
704 test_cmp expected another
705 '
706
707 test_expect_success 'am --resolved fails if index has no changes' '
708 rm -fr .git/rebase-apply &&
709 git reset --hard &&
710 git checkout lorem2^^ &&
711 test_must_fail git am lorem-move.patch &&
712 test_path_is_dir .git/rebase-apply &&
713 test_cmp_rev lorem2^^ HEAD &&
714 test_must_fail git am --resolved &&
715 test_path_is_dir .git/rebase-apply &&
716 test_cmp_rev lorem2^^ HEAD
717 '
718
719 test_expect_success 'am --resolved fails if index has unmerged entries' '
720 rm -fr .git/rebase-apply &&
721 git reset --hard &&
722 git checkout second &&
723 test_must_fail git am -3 lorem-move.patch &&
724 test_path_is_dir .git/rebase-apply &&
725 test_cmp_rev second HEAD &&
726 test_must_fail git am --resolved >err &&
727 test_path_is_dir .git/rebase-apply &&
728 test_cmp_rev second HEAD &&
729 test_i18ngrep "still have unmerged paths" err
730 '
731
732 test_expect_success 'am takes patches from a Pine mailbox' '
733 rm -fr .git/rebase-apply &&
734 git reset --hard &&
735 git checkout first &&
736 cat pine patch1 | git am &&
737 test_path_is_missing .git/rebase-apply &&
738 git diff --exit-code master^..HEAD
739 '
740
741 test_expect_success 'am fails on mail without patch' '
742 rm -fr .git/rebase-apply &&
743 git reset --hard &&
744 test_must_fail git am <failmail &&
745 git am --abort &&
746 test_path_is_missing .git/rebase-apply
747 '
748
749 test_expect_success 'am fails on empty patch' '
750 rm -fr .git/rebase-apply &&
751 git reset --hard &&
752 echo "---" >>failmail &&
753 test_must_fail git am <failmail &&
754 git am --skip &&
755 test_path_is_missing .git/rebase-apply
756 '
757
758 test_expect_success 'am works from stdin in subdirectory' '
759 rm -fr subdir &&
760 rm -fr .git/rebase-apply &&
761 git reset --hard &&
762 git checkout first &&
763 (
764 mkdir -p subdir &&
765 cd subdir &&
766 git am <../patch1
767 ) &&
768 git diff --exit-code second
769 '
770
771 test_expect_success 'am works from file (relative path given) in subdirectory' '
772 rm -fr subdir &&
773 rm -fr .git/rebase-apply &&
774 git reset --hard &&
775 git checkout first &&
776 (
777 mkdir -p subdir &&
778 cd subdir &&
779 git am ../patch1
780 ) &&
781 git diff --exit-code second
782 '
783
784 test_expect_success 'am works from file (absolute path given) in subdirectory' '
785 rm -fr subdir &&
786 rm -fr .git/rebase-apply &&
787 git reset --hard &&
788 git checkout first &&
789 P=$(pwd) &&
790 (
791 mkdir -p subdir &&
792 cd subdir &&
793 git am "$P/patch1"
794 ) &&
795 git diff --exit-code second
796 '
797
798 test_expect_success 'am --committer-date-is-author-date' '
799 rm -fr .git/rebase-apply &&
800 git reset --hard &&
801 git checkout first &&
802 test_tick &&
803 git am --committer-date-is-author-date patch1 &&
804 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
805 sed -ne "/^author /s/.*> //p" head1 >at &&
806 sed -ne "/^committer /s/.*> //p" head1 >ct &&
807 test_cmp at ct
808 '
809
810 test_expect_success 'am without --committer-date-is-author-date' '
811 rm -fr .git/rebase-apply &&
812 git reset --hard &&
813 git checkout first &&
814 test_tick &&
815 git am patch1 &&
816 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
817 sed -ne "/^author /s/.*> //p" head1 >at &&
818 sed -ne "/^committer /s/.*> //p" head1 >ct &&
819 ! test_cmp at ct
820 '
821
822 # This checks for +0000 because TZ is set to UTC and that should
823 # show up when the current time is used. The date in message is set
824 # by test_tick that uses -0700 timezone; if this feature does not
825 # work, we will see that instead of +0000.
826 test_expect_success 'am --ignore-date' '
827 rm -fr .git/rebase-apply &&
828 git reset --hard &&
829 git checkout first &&
830 test_tick &&
831 git am --ignore-date patch1 &&
832 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
833 sed -ne "/^author /s/.*> //p" head1 >at &&
834 grep "+0000" at
835 '
836
837 test_expect_success 'am into an unborn branch' '
838 git rev-parse first^{tree} >expected &&
839 rm -fr .git/rebase-apply &&
840 git reset --hard &&
841 rm -fr subdir &&
842 mkdir subdir &&
843 git format-patch --numbered-files -o subdir -1 first &&
844 (
845 cd subdir &&
846 git init &&
847 git am 1
848 ) &&
849 (
850 cd subdir &&
851 git rev-parse HEAD^{tree} >../actual
852 ) &&
853 test_cmp expected actual
854 '
855
856 test_expect_success 'am newline in subject' '
857 rm -fr .git/rebase-apply &&
858 git reset --hard &&
859 git checkout first &&
860 test_tick &&
861 sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
862 git am <patchnl >output.out 2>&1 &&
863 test_i18ngrep "^Applying: second \\\n foo$" output.out
864 '
865
866 test_expect_success 'am -q is quiet' '
867 rm -fr .git/rebase-apply &&
868 git reset --hard &&
869 git checkout first &&
870 test_tick &&
871 git am -q <patch1 >output.out 2>&1 &&
872 ! test -s output.out
873 '
874
875 test_expect_success 'am empty-file does not infloop' '
876 rm -fr .git/rebase-apply &&
877 git reset --hard &&
878 touch empty-file &&
879 test_tick &&
880 test_must_fail git am empty-file 2>actual &&
881 echo Patch format detection failed. >expected &&
882 test_i18ncmp expected actual
883 '
884
885 test_expect_success 'am --message-id really adds the message id' '
886 rm -fr .git/rebase-apply &&
887 git reset --hard &&
888 git checkout HEAD^ &&
889 git am --message-id patch1.eml &&
890 test_path_is_missing .git/rebase-apply &&
891 git cat-file commit HEAD | tail -n1 >actual &&
892 grep Message-Id patch1.eml >expected &&
893 test_cmp expected actual
894 '
895
896 test_expect_success 'am.messageid really adds the message id' '
897 rm -fr .git/rebase-apply &&
898 git reset --hard &&
899 git checkout HEAD^ &&
900 test_config am.messageid true &&
901 git am patch1.eml &&
902 test_path_is_missing .git/rebase-apply &&
903 git cat-file commit HEAD | tail -n1 >actual &&
904 grep Message-Id patch1.eml >expected &&
905 test_cmp expected actual
906 '
907
908 test_expect_success 'am --message-id -s signs off after the message id' '
909 rm -fr .git/rebase-apply &&
910 git reset --hard &&
911 git checkout HEAD^ &&
912 git am -s --message-id patch1.eml &&
913 test_path_is_missing .git/rebase-apply &&
914 git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
915 grep Message-Id patch1.eml >expected &&
916 test_cmp expected actual
917 '
918
919 test_expect_success 'am -3 works with rerere' '
920 rm -fr .git/rebase-apply &&
921 git reset --hard &&
922
923 # make patches one->two and two->three...
924 test_commit one file &&
925 test_commit two file &&
926 test_commit three file &&
927 git format-patch -2 --stdout >seq.patch &&
928
929 # and create a situation that conflicts...
930 git reset --hard one &&
931 test_commit other file &&
932
933 # enable rerere...
934 test_config rerere.enabled true &&
935 test_when_finished "rm -rf .git/rr-cache" &&
936
937 # ...and apply. Our resolution is to skip the first
938 # patch, and the rerere the second one.
939 test_must_fail git am -3 seq.patch &&
940 test_must_fail git am --skip &&
941 echo resolved >file &&
942 git add file &&
943 git am --resolved &&
944
945 # now apply again, and confirm that rerere engaged (we still
946 # expect failure from am because rerere does not auto-commit
947 # for us).
948 git reset --hard other &&
949 test_must_fail git am -3 seq.patch &&
950 test_must_fail git am --skip &&
951 echo resolved >expect &&
952 test_cmp expect file
953 '
954
955 test_expect_success 'am -s unexpected trailer block' '
956 rm -fr .git/rebase-apply &&
957 git reset --hard &&
958 echo signed >file &&
959 git add file &&
960 cat >msg <<-EOF &&
961 subject here
962
963 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
964 [jc: tweaked log message]
965 Signed-off-by: J C H <j@c.h>
966 EOF
967 git commit -F msg &&
968 git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
969 git format-patch --stdout -1 >patch &&
970
971 git reset --hard HEAD^ &&
972 git am -s patch &&
973 (
974 cat original &&
975 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
976 ) >expect &&
977 git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
978 test_cmp expect actual &&
979
980 cat >msg <<-\EOF &&
981 subject here
982
983 We make sure that there is a blank line between the log
984 message proper and Signed-off-by: line added.
985 EOF
986 git reset HEAD^ &&
987 git commit -F msg file &&
988 git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
989 git format-patch --stdout -1 >patch &&
990
991 git reset --hard HEAD^ &&
992 git am -s patch &&
993
994 (
995 cat original &&
996 echo &&
997 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
998 ) >expect &&
999 git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
1000 test_cmp expect actual
1001 '
1002
1003 test_expect_success 'am --patch-format=mboxrd handles mboxrd' '
1004 rm -fr .git/rebase-apply &&
1005 git checkout -f first &&
1006 echo mboxrd >>file &&
1007 git add file &&
1008 cat >msg <<-\INPUT_END &&
1009 mboxrd should escape the body
1010
1011 From could trip up a loose mbox parser
1012 >From extra escape for reversibility
1013 INPUT_END
1014 git commit -F msg &&
1015 git format-patch --pretty=mboxrd --stdout -1 >mboxrd1 &&
1016 grep "^>From could trip up a loose mbox parser" mboxrd1 &&
1017 git checkout -f first &&
1018 git am --patch-format=mboxrd mboxrd1 &&
1019 git cat-file commit HEAD | tail -n4 >out &&
1020 test_cmp msg out
1021 '
1022
1023 test_expect_success 'am works with multi-line in-body headers' '
1024 FORTY="String that has a length of more than forty characters" &&
1025 LONG="$FORTY $FORTY" &&
1026 rm -fr .git/rebase-apply &&
1027 git checkout -f first &&
1028 echo one >> file &&
1029 git commit -am "$LONG
1030
1031 Body test" --author="$LONG <long@example.com>" &&
1032 git format-patch --stdout -1 >patch &&
1033 # bump from, date, and subject down to in-body header
1034 perl -lpe "
1035 if (/^From:/) {
1036 print \"From: x <x\@example.com>\";
1037 print \"Date: Sat, 1 Jan 2000 00:00:00 +0000\";
1038 print \"Subject: x\n\";
1039 }
1040 " patch >msg &&
1041 git checkout HEAD^ &&
1042 git am msg &&
1043 # Ensure that the author and full message are present
1044 git cat-file commit HEAD | grep "^author.*long@example.com" &&
1045 git cat-file commit HEAD | grep "^$LONG$"
1046 '
1047
1048 test_done