]> git.ipfire.org Git - thirdparty/git.git/blob - t/t4150-am.sh
hashmap: use *_entry APIs for iteration
[thirdparty/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 >msg-without-scissors-line <<-\EOF &&
73 Test that git-am --scissors cuts at the scissors line
74
75 This line should be included in the commit message.
76 EOF
77
78 printf "Subject: " >subject-prefix &&
79
80 cat - subject-prefix msg-without-scissors-line >msg-with-scissors-line <<-\EOF
81 This line should not be included in the commit message with --scissors enabled.
82
83 - - >8 - - remove everything above this line - - >8 - -
84
85 EOF
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 $ZERO_OID" &&
144 echo "# Parent $ZERO_OID" &&
145 cat msg &&
146 echo &&
147 git diff-tree --no-commit-id -p second
148 } >patch1-hg.eml &&
149
150
151 echo file >file &&
152 git add file &&
153 git commit -F msg-without-scissors-line &&
154 git tag expected-for-scissors &&
155 git reset --hard HEAD^ &&
156
157 echo file >file &&
158 git add file &&
159 git commit -F msg-with-scissors-line &&
160 git tag expected-for-no-scissors &&
161 git format-patch --stdout expected-for-no-scissors^ >patch-with-scissors-line.eml &&
162 git reset --hard HEAD^ &&
163
164 sed -n -e "3,\$p" msg >file &&
165 git add file &&
166 test_tick &&
167 git commit -m third &&
168
169 git format-patch --stdout first >patch2 &&
170
171 git checkout -b lorem &&
172 sed -n -e "11,\$p" msg >file &&
173 head -n 9 msg >>file &&
174 test_tick &&
175 git commit -a -m "moved stuff" &&
176
177 echo goodbye >another &&
178 git add another &&
179 test_tick &&
180 git commit -m "added another file" &&
181
182 git format-patch --stdout master >lorem-move.patch &&
183 git format-patch --no-prefix --stdout master >lorem-zero.patch &&
184
185 git checkout -b rename &&
186 git mv file renamed &&
187 git commit -m "renamed a file" &&
188
189 git format-patch -M --stdout lorem >rename.patch &&
190
191 git reset --soft lorem^ &&
192 git commit -m "renamed a file and added another" &&
193
194 git format-patch -M --stdout lorem^ >rename-add.patch &&
195
196 # reset time
197 sane_unset test_tick &&
198 test_tick
199 '
200
201 test_expect_success 'am applies patch correctly' '
202 rm -fr .git/rebase-apply &&
203 git reset --hard &&
204 git checkout first &&
205 test_tick &&
206 git am <patch1 &&
207 test_path_is_missing .git/rebase-apply &&
208 git diff --exit-code second &&
209 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
210 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
211 '
212
213 test_expect_success 'am fails if index is dirty' '
214 test_when_finished "rm -f dirtyfile" &&
215 rm -fr .git/rebase-apply &&
216 git reset --hard &&
217 git checkout first &&
218 echo dirtyfile >dirtyfile &&
219 git add dirtyfile &&
220 test_must_fail git am patch1 &&
221 test_path_is_dir .git/rebase-apply &&
222 test_cmp_rev first HEAD
223 '
224
225 test_expect_success 'am applies patch e-mail not in a mbox' '
226 rm -fr .git/rebase-apply &&
227 git reset --hard &&
228 git checkout first &&
229 git am patch1.eml &&
230 test_path_is_missing .git/rebase-apply &&
231 git diff --exit-code second &&
232 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
233 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
234 '
235
236 test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
237 rm -fr .git/rebase-apply &&
238 git reset --hard &&
239 git checkout first &&
240 git am patch1-crlf.eml &&
241 test_path_is_missing .git/rebase-apply &&
242 git diff --exit-code second &&
243 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
244 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
245 '
246
247 test_expect_success 'am applies patch e-mail with preceding whitespace' '
248 rm -fr .git/rebase-apply &&
249 git reset --hard &&
250 git checkout first &&
251 git am patch1-ws.eml &&
252 test_path_is_missing .git/rebase-apply &&
253 git diff --exit-code second &&
254 test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
255 test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
256 '
257
258 test_expect_success 'am applies stgit patch' '
259 rm -fr .git/rebase-apply &&
260 git checkout -f first &&
261 git am patch1-stgit.eml &&
262 test_path_is_missing .git/rebase-apply &&
263 git diff --exit-code second &&
264 test_cmp_rev second HEAD &&
265 test_cmp_rev second^ HEAD^
266 '
267
268 test_expect_success 'am --patch-format=stgit applies stgit patch' '
269 rm -fr .git/rebase-apply &&
270 git checkout -f first &&
271 git am --patch-format=stgit <patch1-stgit.eml &&
272 test_path_is_missing .git/rebase-apply &&
273 git diff --exit-code second &&
274 test_cmp_rev second HEAD &&
275 test_cmp_rev second^ HEAD^
276 '
277
278 test_expect_success 'am applies stgit series' '
279 rm -fr .git/rebase-apply &&
280 git checkout -f first &&
281 git am stgit-series/series &&
282 test_path_is_missing .git/rebase-apply &&
283 git diff --exit-code second &&
284 test_cmp_rev second HEAD &&
285 test_cmp_rev second^ HEAD^
286 '
287
288 test_expect_success 'am applies hg patch' '
289 rm -fr .git/rebase-apply &&
290 git checkout -f first &&
291 git am patch1-hg.eml &&
292 test_path_is_missing .git/rebase-apply &&
293 git diff --exit-code second &&
294 test_cmp_rev second HEAD &&
295 test_cmp_rev second^ HEAD^
296 '
297
298 test_expect_success 'am --patch-format=hg applies hg patch' '
299 rm -fr .git/rebase-apply &&
300 git checkout -f first &&
301 git am --patch-format=hg <patch1-hg.eml &&
302 test_path_is_missing .git/rebase-apply &&
303 git diff --exit-code second &&
304 test_cmp_rev second HEAD &&
305 test_cmp_rev second^ HEAD^
306 '
307
308 test_expect_success 'am with applypatch-msg hook' '
309 test_when_finished "rm -f .git/hooks/applypatch-msg" &&
310 rm -fr .git/rebase-apply &&
311 git reset --hard &&
312 git checkout first &&
313 mkdir -p .git/hooks &&
314 write_script .git/hooks/applypatch-msg <<-\EOF &&
315 cat "$1" >actual-msg &&
316 echo hook-message >"$1"
317 EOF
318 git am patch1 &&
319 test_path_is_missing .git/rebase-apply &&
320 git diff --exit-code second &&
321 echo hook-message >expected &&
322 git log -1 --format=format:%B >actual &&
323 test_cmp expected actual &&
324 git log -1 --format=format:%B second >expected &&
325 test_cmp expected actual-msg
326 '
327
328 test_expect_success 'am with failing applypatch-msg hook' '
329 test_when_finished "rm -f .git/hooks/applypatch-msg" &&
330 rm -fr .git/rebase-apply &&
331 git reset --hard &&
332 git checkout first &&
333 mkdir -p .git/hooks &&
334 write_script .git/hooks/applypatch-msg <<-\EOF &&
335 exit 1
336 EOF
337 test_must_fail git am patch1 &&
338 test_path_is_dir .git/rebase-apply &&
339 git diff --exit-code first &&
340 test_cmp_rev first HEAD
341 '
342
343 test_expect_success 'am with pre-applypatch hook' '
344 test_when_finished "rm -f .git/hooks/pre-applypatch" &&
345 rm -fr .git/rebase-apply &&
346 git reset --hard &&
347 git checkout first &&
348 mkdir -p .git/hooks &&
349 write_script .git/hooks/pre-applypatch <<-\EOF &&
350 git diff first >diff.actual
351 exit 0
352 EOF
353 git am patch1 &&
354 test_path_is_missing .git/rebase-apply &&
355 git diff --exit-code second &&
356 test_cmp_rev second HEAD &&
357 git diff first..second >diff.expected &&
358 test_cmp diff.expected diff.actual
359 '
360
361 test_expect_success 'am with failing pre-applypatch hook' '
362 test_when_finished "rm -f .git/hooks/pre-applypatch" &&
363 rm -fr .git/rebase-apply &&
364 git reset --hard &&
365 git checkout first &&
366 mkdir -p .git/hooks &&
367 write_script .git/hooks/pre-applypatch <<-\EOF &&
368 exit 1
369 EOF
370 test_must_fail git am patch1 &&
371 test_path_is_dir .git/rebase-apply &&
372 git diff --exit-code second &&
373 test_cmp_rev first HEAD
374 '
375
376 test_expect_success 'am with post-applypatch hook' '
377 test_when_finished "rm -f .git/hooks/post-applypatch" &&
378 rm -fr .git/rebase-apply &&
379 git reset --hard &&
380 git checkout first &&
381 mkdir -p .git/hooks &&
382 write_script .git/hooks/post-applypatch <<-\EOF &&
383 git rev-parse HEAD >head.actual
384 git diff second >diff.actual
385 exit 0
386 EOF
387 git am patch1 &&
388 test_path_is_missing .git/rebase-apply &&
389 test_cmp_rev second HEAD &&
390 git rev-parse second >head.expected &&
391 test_cmp head.expected head.actual &&
392 git diff second >diff.expected &&
393 test_cmp diff.expected diff.actual
394 '
395
396 test_expect_success 'am with failing post-applypatch hook' '
397 test_when_finished "rm -f .git/hooks/post-applypatch" &&
398 rm -fr .git/rebase-apply &&
399 git reset --hard &&
400 git checkout first &&
401 mkdir -p .git/hooks &&
402 write_script .git/hooks/post-applypatch <<-\EOF &&
403 git rev-parse HEAD >head.actual
404 exit 1
405 EOF
406 git am patch1 &&
407 test_path_is_missing .git/rebase-apply &&
408 git diff --exit-code second &&
409 test_cmp_rev second HEAD &&
410 git rev-parse second >head.expected &&
411 test_cmp head.expected head.actual
412 '
413
414 test_expect_success 'am --scissors cuts the message at the scissors line' '
415 rm -fr .git/rebase-apply &&
416 git reset --hard &&
417 git checkout second &&
418 git am --scissors patch-with-scissors-line.eml &&
419 test_path_is_missing .git/rebase-apply &&
420 git diff --exit-code expected-for-scissors &&
421 test_cmp_rev expected-for-scissors HEAD
422 '
423
424 test_expect_success 'am --no-scissors overrides mailinfo.scissors' '
425 rm -fr .git/rebase-apply &&
426 git reset --hard &&
427 git checkout second &&
428 test_config mailinfo.scissors true &&
429 git am --no-scissors patch-with-scissors-line.eml &&
430 test_path_is_missing .git/rebase-apply &&
431 git diff --exit-code expected-for-no-scissors &&
432 test_cmp_rev expected-for-no-scissors HEAD
433 '
434
435 test_expect_success 'setup: new author and committer' '
436 GIT_AUTHOR_NAME="Another Thor" &&
437 GIT_AUTHOR_EMAIL="a.thor@example.com" &&
438 GIT_COMMITTER_NAME="Co M Miter" &&
439 GIT_COMMITTER_EMAIL="c.miter@example.com" &&
440 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
441 '
442
443 compare () {
444 a=$(git cat-file commit "$2" | grep "^$1 ") &&
445 b=$(git cat-file commit "$3" | grep "^$1 ") &&
446 test "$a" = "$b"
447 }
448
449 test_expect_success 'am changes committer and keeps author' '
450 test_tick &&
451 rm -fr .git/rebase-apply &&
452 git reset --hard &&
453 git checkout first &&
454 git am patch2 &&
455 test_path_is_missing .git/rebase-apply &&
456 test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
457 git diff --exit-code master..HEAD &&
458 git diff --exit-code master^..HEAD^ &&
459 compare author master HEAD &&
460 compare author master^ HEAD^ &&
461 test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
462 "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
463 '
464
465 test_expect_success 'am --signoff adds Signed-off-by: line' '
466 rm -fr .git/rebase-apply &&
467 git reset --hard &&
468 git checkout -b master2 first &&
469 git am --signoff <patch2 &&
470 {
471 printf "third\n\nSigned-off-by: %s <%s>\n\n" \
472 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
473 cat msg &&
474 printf "Signed-off-by: %s <%s>\n\n" \
475 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
476 } >expected-log &&
477 git log --pretty=%B -2 HEAD >actual &&
478 test_cmp expected-log actual
479 '
480
481 test_expect_success 'am stays in branch' '
482 echo refs/heads/master2 >expected &&
483 git symbolic-ref HEAD >actual &&
484 test_cmp expected actual
485 '
486
487 test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
488 git format-patch --stdout first >patch3 &&
489 git reset --hard first &&
490 git am --signoff <patch3 &&
491 git log --pretty=%B -2 HEAD >actual &&
492 test_cmp expected-log actual
493 '
494
495 test_expect_success 'am --signoff adds Signed-off-by: if another author is preset' '
496 NAME="A N Other" &&
497 EMAIL="a.n.other@example.com" &&
498 {
499 printf "third\n\nSigned-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
500 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
501 "$NAME" "$EMAIL" &&
502 cat msg &&
503 printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
504 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
505 "$NAME" "$EMAIL"
506 } >expected-log &&
507 git reset --hard first &&
508 GIT_COMMITTER_NAME="$NAME" GIT_COMMITTER_EMAIL="$EMAIL" \
509 git am --signoff <patch3 &&
510 git log --pretty=%B -2 HEAD >actual &&
511 test_cmp expected-log actual
512 '
513
514 test_expect_success 'am --signoff duplicates Signed-off-by: if it is not the last one' '
515 NAME="A N Other" &&
516 EMAIL="a.n.other@example.com" &&
517 {
518 printf "third\n\nSigned-off-by: %s <%s>\n\
519 Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\n" \
520 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
521 "$NAME" "$EMAIL" \
522 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" &&
523 cat msg &&
524 printf "Signed-off-by: %s <%s>\nSigned-off-by: %s <%s>\n\
525 Signed-off-by: %s <%s>\n\n" \
526 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL" \
527 "$NAME" "$EMAIL" \
528 "$GIT_COMMITTER_NAME" "$GIT_COMMITTER_EMAIL"
529 } >expected-log &&
530 git format-patch --stdout first >patch3 &&
531 git reset --hard first &&
532 git am --signoff <patch3 &&
533 git log --pretty=%B -2 HEAD >actual &&
534 test_cmp expected-log actual
535 '
536
537 test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
538 git format-patch --stdout HEAD^ >tmp &&
539 sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," tmp >patch4 &&
540 git reset --hard HEAD^ &&
541 git am <patch4 &&
542 git rev-parse HEAD >expected &&
543 git rev-parse master2 >actual &&
544 test_cmp expected actual
545 '
546
547 test_expect_success 'am --keep really keeps the subject' '
548 rm -fr .git/rebase-apply &&
549 git reset --hard &&
550 git checkout HEAD^ &&
551 git am --keep patch4 &&
552 test_path_is_missing .git/rebase-apply &&
553 git cat-file commit HEAD >actual &&
554 grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
555 '
556
557 test_expect_success 'am --keep-non-patch really keeps the non-patch part' '
558 rm -fr .git/rebase-apply &&
559 git reset --hard &&
560 git checkout HEAD^ &&
561 git am --keep-non-patch patch4 &&
562 test_path_is_missing .git/rebase-apply &&
563 git cat-file commit HEAD >actual &&
564 grep "^\[foo\] third" actual
565 '
566
567 test_expect_success 'setup am -3' '
568 rm -fr .git/rebase-apply &&
569 git reset --hard &&
570 git checkout -b base3way master2 &&
571 sed -n -e "3,\$p" msg >file &&
572 head -n 9 msg >>file &&
573 git add file &&
574 test_tick &&
575 git commit -m "copied stuff"
576 '
577
578 test_expect_success 'am -3 falls back to 3-way merge' '
579 rm -fr .git/rebase-apply &&
580 git reset --hard &&
581 git checkout -b lorem2 base3way &&
582 git am -3 lorem-move.patch &&
583 test_path_is_missing .git/rebase-apply &&
584 git diff --exit-code lorem
585 '
586
587 test_expect_success 'am -3 -p0 can read --no-prefix patch' '
588 rm -fr .git/rebase-apply &&
589 git reset --hard &&
590 git checkout -b lorem3 base3way &&
591 git am -3 -p0 lorem-zero.patch &&
592 test_path_is_missing .git/rebase-apply &&
593 git diff --exit-code lorem
594 '
595
596 test_expect_success 'am with config am.threeWay falls back to 3-way merge' '
597 rm -fr .git/rebase-apply &&
598 git reset --hard &&
599 git checkout -b lorem4 base3way &&
600 test_config am.threeWay 1 &&
601 git am lorem-move.patch &&
602 test_path_is_missing .git/rebase-apply &&
603 git diff --exit-code lorem
604 '
605
606 test_expect_success 'am with config am.threeWay overridden by --no-3way' '
607 rm -fr .git/rebase-apply &&
608 git reset --hard &&
609 git checkout -b lorem5 base3way &&
610 test_config am.threeWay 1 &&
611 test_must_fail git am --no-3way lorem-move.patch &&
612 test_path_is_dir .git/rebase-apply
613 '
614
615 test_expect_success 'am can rename a file' '
616 grep "^rename from" rename.patch &&
617 rm -fr .git/rebase-apply &&
618 git reset --hard &&
619 git checkout lorem^0 &&
620 git am rename.patch &&
621 test_path_is_missing .git/rebase-apply &&
622 git update-index --refresh &&
623 git diff --exit-code rename
624 '
625
626 test_expect_success 'am -3 can rename a file' '
627 grep "^rename from" rename.patch &&
628 rm -fr .git/rebase-apply &&
629 git reset --hard &&
630 git checkout lorem^0 &&
631 git am -3 rename.patch &&
632 test_path_is_missing .git/rebase-apply &&
633 git update-index --refresh &&
634 git diff --exit-code rename
635 '
636
637 test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
638 grep "^rename from" rename-add.patch &&
639 rm -fr .git/rebase-apply &&
640 git reset --hard &&
641 git checkout lorem^0 &&
642 git am -3 rename-add.patch &&
643 test_path_is_missing .git/rebase-apply &&
644 git update-index --refresh &&
645 git diff --exit-code rename
646 '
647
648 test_expect_success 'am -3 -q is quiet' '
649 rm -fr .git/rebase-apply &&
650 git checkout -f lorem2 &&
651 git reset base3way --hard &&
652 git am -3 -q lorem-move.patch >output.out 2>&1 &&
653 test_must_be_empty output.out
654 '
655
656 test_expect_success 'am pauses on conflict' '
657 rm -fr .git/rebase-apply &&
658 git reset --hard &&
659 git checkout lorem2^^ &&
660 test_must_fail git am lorem-move.patch &&
661 test -d .git/rebase-apply
662 '
663
664 test_expect_success 'am --show-current-patch' '
665 git am --show-current-patch >actual.patch &&
666 test_cmp .git/rebase-apply/0001 actual.patch
667 '
668
669 test_expect_success 'am --skip works' '
670 echo goodbye >expected &&
671 git am --skip &&
672 test_path_is_missing .git/rebase-apply &&
673 git diff --exit-code lorem2^^ -- file &&
674 test_cmp expected another
675 '
676
677 test_expect_success 'am --abort removes a stray directory' '
678 mkdir .git/rebase-apply &&
679 git am --abort &&
680 test_path_is_missing .git/rebase-apply
681 '
682
683 test_expect_success 'am refuses patches when paused' '
684 rm -fr .git/rebase-apply &&
685 git reset --hard &&
686 git checkout lorem2^^ &&
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 test_must_fail git am <lorem-move.patch &&
693 test_path_is_dir .git/rebase-apply &&
694 test_cmp_rev lorem2^^ HEAD
695 '
696
697 test_expect_success 'am --resolved works' '
698 echo goodbye >expected &&
699 rm -fr .git/rebase-apply &&
700 git reset --hard &&
701 git checkout lorem2^^ &&
702 test_must_fail git am lorem-move.patch &&
703 test -d .git/rebase-apply &&
704 echo resolved >>file &&
705 git add file &&
706 git am --resolved &&
707 test_path_is_missing .git/rebase-apply &&
708 test_cmp expected another
709 '
710
711 test_expect_success 'am --resolved fails if index has no changes' '
712 rm -fr .git/rebase-apply &&
713 git reset --hard &&
714 git checkout lorem2^^ &&
715 test_must_fail git am lorem-move.patch &&
716 test_path_is_dir .git/rebase-apply &&
717 test_cmp_rev lorem2^^ HEAD &&
718 test_must_fail git am --resolved &&
719 test_path_is_dir .git/rebase-apply &&
720 test_cmp_rev lorem2^^ HEAD
721 '
722
723 test_expect_success 'am --resolved fails if index has unmerged entries' '
724 rm -fr .git/rebase-apply &&
725 git reset --hard &&
726 git checkout second &&
727 test_must_fail git am -3 lorem-move.patch &&
728 test_path_is_dir .git/rebase-apply &&
729 test_cmp_rev second HEAD &&
730 test_must_fail git am --resolved >err &&
731 test_path_is_dir .git/rebase-apply &&
732 test_cmp_rev second HEAD &&
733 test_i18ngrep "still have unmerged paths" err
734 '
735
736 test_expect_success 'am takes patches from a Pine mailbox' '
737 rm -fr .git/rebase-apply &&
738 git reset --hard &&
739 git checkout first &&
740 cat pine patch1 | git am &&
741 test_path_is_missing .git/rebase-apply &&
742 git diff --exit-code master^..HEAD
743 '
744
745 test_expect_success 'am fails on mail without patch' '
746 rm -fr .git/rebase-apply &&
747 git reset --hard &&
748 test_must_fail git am <failmail &&
749 git am --abort &&
750 test_path_is_missing .git/rebase-apply
751 '
752
753 test_expect_success 'am fails on empty patch' '
754 rm -fr .git/rebase-apply &&
755 git reset --hard &&
756 echo "---" >>failmail &&
757 test_must_fail git am <failmail &&
758 git am --skip &&
759 test_path_is_missing .git/rebase-apply
760 '
761
762 test_expect_success 'am works from stdin in subdirectory' '
763 rm -fr subdir &&
764 rm -fr .git/rebase-apply &&
765 git reset --hard &&
766 git checkout first &&
767 (
768 mkdir -p subdir &&
769 cd subdir &&
770 git am <../patch1
771 ) &&
772 git diff --exit-code second
773 '
774
775 test_expect_success 'am works from file (relative path given) in subdirectory' '
776 rm -fr subdir &&
777 rm -fr .git/rebase-apply &&
778 git reset --hard &&
779 git checkout first &&
780 (
781 mkdir -p subdir &&
782 cd subdir &&
783 git am ../patch1
784 ) &&
785 git diff --exit-code second
786 '
787
788 test_expect_success 'am works from file (absolute path given) in subdirectory' '
789 rm -fr subdir &&
790 rm -fr .git/rebase-apply &&
791 git reset --hard &&
792 git checkout first &&
793 P=$(pwd) &&
794 (
795 mkdir -p subdir &&
796 cd subdir &&
797 git am "$P/patch1"
798 ) &&
799 git diff --exit-code second
800 '
801
802 test_expect_success 'am --committer-date-is-author-date' '
803 rm -fr .git/rebase-apply &&
804 git reset --hard &&
805 git checkout first &&
806 test_tick &&
807 git am --committer-date-is-author-date patch1 &&
808 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
809 sed -ne "/^author /s/.*> //p" head1 >at &&
810 sed -ne "/^committer /s/.*> //p" head1 >ct &&
811 test_cmp at ct
812 '
813
814 test_expect_success 'am without --committer-date-is-author-date' '
815 rm -fr .git/rebase-apply &&
816 git reset --hard &&
817 git checkout first &&
818 test_tick &&
819 git am patch1 &&
820 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
821 sed -ne "/^author /s/.*> //p" head1 >at &&
822 sed -ne "/^committer /s/.*> //p" head1 >ct &&
823 ! test_cmp at ct
824 '
825
826 # This checks for +0000 because TZ is set to UTC and that should
827 # show up when the current time is used. The date in message is set
828 # by test_tick that uses -0700 timezone; if this feature does not
829 # work, we will see that instead of +0000.
830 test_expect_success 'am --ignore-date' '
831 rm -fr .git/rebase-apply &&
832 git reset --hard &&
833 git checkout first &&
834 test_tick &&
835 git am --ignore-date patch1 &&
836 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
837 sed -ne "/^author /s/.*> //p" head1 >at &&
838 grep "+0000" at
839 '
840
841 test_expect_success 'am into an unborn branch' '
842 git rev-parse first^{tree} >expected &&
843 rm -fr .git/rebase-apply &&
844 git reset --hard &&
845 rm -fr subdir &&
846 mkdir subdir &&
847 git format-patch --numbered-files -o subdir -1 first &&
848 (
849 cd subdir &&
850 git init &&
851 git am 1
852 ) &&
853 (
854 cd subdir &&
855 git rev-parse HEAD^{tree} >../actual
856 ) &&
857 test_cmp expected actual
858 '
859
860 test_expect_success 'am newline in subject' '
861 rm -fr .git/rebase-apply &&
862 git reset --hard &&
863 git checkout first &&
864 test_tick &&
865 sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
866 git am <patchnl >output.out 2>&1 &&
867 test_i18ngrep "^Applying: second \\\n foo$" output.out
868 '
869
870 test_expect_success 'am -q is quiet' '
871 rm -fr .git/rebase-apply &&
872 git reset --hard &&
873 git checkout first &&
874 test_tick &&
875 git am -q <patch1 >output.out 2>&1 &&
876 test_must_be_empty output.out
877 '
878
879 test_expect_success 'am empty-file does not infloop' '
880 rm -fr .git/rebase-apply &&
881 git reset --hard &&
882 touch empty-file &&
883 test_tick &&
884 test_must_fail git am empty-file 2>actual &&
885 echo Patch format detection failed. >expected &&
886 test_i18ncmp expected actual
887 '
888
889 test_expect_success 'am --message-id really adds the message id' '
890 rm -fr .git/rebase-apply &&
891 git reset --hard &&
892 git checkout HEAD^ &&
893 git am --message-id patch1.eml &&
894 test_path_is_missing .git/rebase-apply &&
895 git cat-file commit HEAD | tail -n1 >actual &&
896 grep Message-Id patch1.eml >expected &&
897 test_cmp expected actual
898 '
899
900 test_expect_success 'am.messageid really adds the message id' '
901 rm -fr .git/rebase-apply &&
902 git reset --hard &&
903 git checkout HEAD^ &&
904 test_config am.messageid true &&
905 git am patch1.eml &&
906 test_path_is_missing .git/rebase-apply &&
907 git cat-file commit HEAD | tail -n1 >actual &&
908 grep Message-Id patch1.eml >expected &&
909 test_cmp expected actual
910 '
911
912 test_expect_success 'am --message-id -s signs off after the message id' '
913 rm -fr .git/rebase-apply &&
914 git reset --hard &&
915 git checkout HEAD^ &&
916 git am -s --message-id patch1.eml &&
917 test_path_is_missing .git/rebase-apply &&
918 git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
919 grep Message-Id patch1.eml >expected &&
920 test_cmp expected actual
921 '
922
923 test_expect_success 'am -3 works with rerere' '
924 rm -fr .git/rebase-apply &&
925 git reset --hard &&
926
927 # make patches one->two and two->three...
928 test_commit one file &&
929 test_commit two file &&
930 test_commit three file &&
931 git format-patch -2 --stdout >seq.patch &&
932
933 # and create a situation that conflicts...
934 git reset --hard one &&
935 test_commit other file &&
936
937 # enable rerere...
938 test_config rerere.enabled true &&
939 test_when_finished "rm -rf .git/rr-cache" &&
940
941 # ...and apply. Our resolution is to skip the first
942 # patch, and the rerere the second one.
943 test_must_fail git am -3 seq.patch &&
944 test_must_fail git am --skip &&
945 echo resolved >file &&
946 git add file &&
947 git am --resolved &&
948
949 # now apply again, and confirm that rerere engaged (we still
950 # expect failure from am because rerere does not auto-commit
951 # for us).
952 git reset --hard other &&
953 test_must_fail git am -3 seq.patch &&
954 test_must_fail git am --skip &&
955 echo resolved >expect &&
956 test_cmp expect file
957 '
958
959 test_expect_success 'am -s unexpected trailer block' '
960 rm -fr .git/rebase-apply &&
961 git reset --hard &&
962 echo signed >file &&
963 git add file &&
964 cat >msg <<-EOF &&
965 subject here
966
967 Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
968 [jc: tweaked log message]
969 Signed-off-by: J C H <j@c.h>
970 EOF
971 git commit -F msg &&
972 git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
973 git format-patch --stdout -1 >patch &&
974
975 git reset --hard HEAD^ &&
976 git am -s patch &&
977 (
978 cat original &&
979 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
980 ) >expect &&
981 git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
982 test_cmp expect actual &&
983
984 cat >msg <<-\EOF &&
985 subject here
986
987 We make sure that there is a blank line between the log
988 message proper and Signed-off-by: line added.
989 EOF
990 git reset HEAD^ &&
991 git commit -F msg file &&
992 git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
993 git format-patch --stdout -1 >patch &&
994
995 git reset --hard HEAD^ &&
996 git am -s patch &&
997
998 (
999 cat original &&
1000 echo &&
1001 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
1002 ) >expect &&
1003 git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
1004 test_cmp expect actual
1005 '
1006
1007 test_expect_success 'am --patch-format=mboxrd handles mboxrd' '
1008 rm -fr .git/rebase-apply &&
1009 git checkout -f first &&
1010 echo mboxrd >>file &&
1011 git add file &&
1012 cat >msg <<-\INPUT_END &&
1013 mboxrd should escape the body
1014
1015 From could trip up a loose mbox parser
1016 >From extra escape for reversibility
1017 INPUT_END
1018 git commit -F msg &&
1019 git format-patch --pretty=mboxrd --stdout -1 >mboxrd1 &&
1020 grep "^>From could trip up a loose mbox parser" mboxrd1 &&
1021 git checkout -f first &&
1022 git am --patch-format=mboxrd mboxrd1 &&
1023 git cat-file commit HEAD | tail -n4 >out &&
1024 test_cmp msg out
1025 '
1026
1027 test_expect_success 'am works with multi-line in-body headers' '
1028 FORTY="String that has a length of more than forty characters" &&
1029 LONG="$FORTY $FORTY" &&
1030 rm -fr .git/rebase-apply &&
1031 git checkout -f first &&
1032 echo one >> file &&
1033 git commit -am "$LONG
1034
1035 Body test" --author="$LONG <long@example.com>" &&
1036 git format-patch --stdout -1 >patch &&
1037 # bump from, date, and subject down to in-body header
1038 perl -lpe "
1039 if (/^From:/) {
1040 print \"From: x <x\@example.com>\";
1041 print \"Date: Sat, 1 Jan 2000 00:00:00 +0000\";
1042 print \"Subject: x\n\";
1043 }
1044 " patch >msg &&
1045 git checkout HEAD^ &&
1046 git am msg &&
1047 # Ensure that the author and full message are present
1048 git cat-file commit HEAD | grep "^author.*long@example.com" &&
1049 git cat-file commit HEAD | grep "^$LONG$"
1050 '
1051
1052 test_expect_success 'am --quit keeps HEAD where it is' '
1053 mkdir .git/rebase-apply &&
1054 >.git/rebase-apply/last &&
1055 >.git/rebase-apply/next &&
1056 git rev-parse HEAD^ >.git/ORIG_HEAD &&
1057 git rev-parse HEAD >expected &&
1058 git am --quit &&
1059 test_path_is_missing .git/rebase-apply &&
1060 git rev-parse HEAD >actual &&
1061 test_cmp expected actual
1062 '
1063
1064 test_done