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