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