Merge branch 'en/ort-perf-batch-10'
[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_cmp 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