Merge branch 'jk/stash-options'
[git] / t / t4150-am.sh
1 #!/bin/sh
2
3 test_description='git am running'
4
5 . ./test-lib.sh
6
7 test_expect_success 'setup: messages' '
8         cat >msg <<-\EOF &&
9         second
10
11         Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy
12         eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
13         voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
14         kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem
15         ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
16         tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
17         vero eos et accusam et justo duo dolores et ea rebum.
18
19         EOF
20         qz_to_tab_space <<-\EOF >>msg &&
21         QDuis autem vel eum iriure dolor in hendrerit in vulputate velit
22         Qesse molestie consequat, vel illum dolore eu feugiat nulla facilisis
23         Qat vero eros et accumsan et iusto odio dignissim qui blandit
24         Qpraesent luptatum zzril delenit augue duis dolore te feugait nulla
25         Qfacilisi.
26         EOF
27         cat >>msg <<-\EOF &&
28
29         Lorem ipsum dolor sit amet,
30         consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
31         laoreet dolore magna aliquam erat volutpat.
32
33           git
34           ---
35           +++
36
37         Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
38         lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure
39         dolor in hendrerit in vulputate velit esse molestie consequat, vel illum
40         dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
41         dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te
42         feugait nulla facilisi.
43         EOF
44
45         cat >failmail <<-\EOF &&
46         From foo@example.com Fri May 23 10:43:49 2008
47         From:   foo@example.com
48         To:     bar@example.com
49         Subject: Re: [RFC/PATCH] git-foo.sh
50         Date:   Fri, 23 May 2008 05:23:42 +0200
51
52         Sometimes we have to find out that there'\''s nothing left.
53
54         EOF
55
56         cat >pine <<-\EOF &&
57         From MAILER-DAEMON Fri May 23 10:43:49 2008
58         Date: 23 May 2008 05:23:42 +0200
59         From: Mail System Internal Data <MAILER-DAEMON@example.com>
60         Subject: DON'\''T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
61         Message-ID: <foo-0001@example.com>
62
63         This text is part of the internal format of your mail folder, and is not
64         a real message.  It is created automatically by the mail system software.
65         If deleted, important folder data will be lost, and it will be re-created
66         with the data reset to initial values.
67
68         EOF
69
70         signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
71 '
72
73 test_expect_success setup '
74         echo hello >file &&
75         git add file &&
76         test_tick &&
77         git commit -m first &&
78         git tag first &&
79
80         echo world >>file &&
81         git add file &&
82         test_tick &&
83         git commit -s -F msg &&
84         git tag second &&
85
86         git format-patch --stdout first >patch1 &&
87         {
88                 echo "Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" &&
89                 echo "X-Fake-Field: Line One" &&
90                 echo "X-Fake-Field: Line Two" &&
91                 echo "X-Fake-Field: Line Three" &&
92                 git format-patch --stdout first | sed -e "1d"
93         } > patch1.eml &&
94         {
95                 echo "X-Fake-Field: Line One" &&
96                 echo "X-Fake-Field: Line Two" &&
97                 echo "X-Fake-Field: Line Three" &&
98                 git format-patch --stdout first | sed -e "1d"
99         } | append_cr >patch1-crlf.eml &&
100         {
101                 printf "%255s\\n" ""
102                 echo "X-Fake-Field: Line One" &&
103                 echo "X-Fake-Field: Line Two" &&
104                 echo "X-Fake-Field: Line Three" &&
105                 git format-patch --stdout first | sed -e "1d"
106         } > patch1-ws.eml &&
107
108         sed -n -e "3,\$p" msg >file &&
109         git add file &&
110         test_tick &&
111         git commit -m third &&
112
113         git format-patch --stdout first >patch2 &&
114
115         git checkout -b lorem &&
116         sed -n -e "11,\$p" msg >file &&
117         head -n 9 msg >>file &&
118         test_tick &&
119         git commit -a -m "moved stuff" &&
120
121         echo goodbye >another &&
122         git add another &&
123         test_tick &&
124         git commit -m "added another file" &&
125
126         git format-patch --stdout master >lorem-move.patch &&
127         git format-patch --no-prefix --stdout master >lorem-zero.patch &&
128
129         git checkout -b rename &&
130         git mv file renamed &&
131         git commit -m "renamed a file" &&
132
133         git format-patch -M --stdout lorem >rename.patch &&
134
135         git reset --soft lorem^ &&
136         git commit -m "renamed a file and added another" &&
137
138         git format-patch -M --stdout lorem^ >rename-add.patch &&
139
140         # reset time
141         sane_unset test_tick &&
142         test_tick
143 '
144
145 test_expect_success 'am applies patch correctly' '
146         rm -fr .git/rebase-apply &&
147         git reset --hard &&
148         git checkout first &&
149         test_tick &&
150         git am <patch1 &&
151         test_path_is_missing .git/rebase-apply &&
152         git diff --exit-code second &&
153         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
154         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
155 '
156
157 test_expect_success 'am applies patch e-mail not in a mbox' '
158         rm -fr .git/rebase-apply &&
159         git reset --hard &&
160         git checkout first &&
161         git am patch1.eml &&
162         test_path_is_missing .git/rebase-apply &&
163         git diff --exit-code second &&
164         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
165         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
166 '
167
168 test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
169         rm -fr .git/rebase-apply &&
170         git reset --hard &&
171         git checkout first &&
172         git am patch1-crlf.eml &&
173         test_path_is_missing .git/rebase-apply &&
174         git diff --exit-code second &&
175         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
176         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
177 '
178
179 test_expect_success 'am applies patch e-mail with preceding whitespace' '
180         rm -fr .git/rebase-apply &&
181         git reset --hard &&
182         git checkout first &&
183         git am patch1-ws.eml &&
184         test_path_is_missing .git/rebase-apply &&
185         git diff --exit-code second &&
186         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
187         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
188 '
189
190 test_expect_success 'setup: new author and committer' '
191         GIT_AUTHOR_NAME="Another Thor" &&
192         GIT_AUTHOR_EMAIL="a.thor@example.com" &&
193         GIT_COMMITTER_NAME="Co M Miter" &&
194         GIT_COMMITTER_EMAIL="c.miter@example.com" &&
195         export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
196 '
197
198 compare () {
199         a=$(git cat-file commit "$2" | grep "^$1 ") &&
200         b=$(git cat-file commit "$3" | grep "^$1 ") &&
201         test "$a" = "$b"
202 }
203
204 test_expect_success 'am changes committer and keeps author' '
205         test_tick &&
206         rm -fr .git/rebase-apply &&
207         git reset --hard &&
208         git checkout first &&
209         git am patch2 &&
210         test_path_is_missing .git/rebase-apply &&
211         test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
212         git diff --exit-code master..HEAD &&
213         git diff --exit-code master^..HEAD^ &&
214         compare author master HEAD &&
215         compare author master^ HEAD^ &&
216         test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
217              "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
218 '
219
220 test_expect_success 'am --signoff adds Signed-off-by: line' '
221         rm -fr .git/rebase-apply &&
222         git reset --hard &&
223         git checkout -b master2 first &&
224         git am --signoff <patch2 &&
225         printf "%s\n" "$signoff" >expected &&
226         echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected &&
227         git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
228         test_cmp expected actual &&
229         echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
230         git cat-file commit HEAD | grep "Signed-off-by:" >actual &&
231         test_cmp expected actual
232 '
233
234 test_expect_success 'am stays in branch' '
235         echo refs/heads/master2 >expected &&
236         git symbolic-ref HEAD >actual &&
237         test_cmp expected actual
238 '
239
240 test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
241         git format-patch --stdout HEAD^ >patch3 &&
242         sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," patch3 >patch4 &&
243         rm -fr .git/rebase-apply &&
244         git reset --hard &&
245         git checkout HEAD^ &&
246         git am --signoff patch4 &&
247         git cat-file commit HEAD >actual &&
248         test $(grep -c "^Signed-off-by:" actual) -eq 1
249 '
250
251 test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
252         git rev-parse HEAD >expected &&
253         git rev-parse master2 >actual &&
254         test_cmp expected actual
255 '
256
257 test_expect_success 'am --keep really keeps the subject' '
258         rm -fr .git/rebase-apply &&
259         git reset --hard &&
260         git checkout HEAD^ &&
261         git am --keep patch4 &&
262         test_path_is_missing .git/rebase-apply &&
263         git cat-file commit HEAD >actual &&
264         grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
265 '
266
267 test_expect_success 'am --keep-non-patch really keeps the non-patch part' '
268         rm -fr .git/rebase-apply &&
269         git reset --hard &&
270         git checkout HEAD^ &&
271         git am --keep-non-patch patch4 &&
272         test_path_is_missing .git/rebase-apply &&
273         git cat-file commit HEAD >actual &&
274         grep "^\[foo\] third" actual
275 '
276
277 test_expect_success 'am -3 falls back to 3-way merge' '
278         rm -fr .git/rebase-apply &&
279         git reset --hard &&
280         git checkout -b lorem2 master2 &&
281         sed -n -e "3,\$p" msg >file &&
282         head -n 9 msg >>file &&
283         git add file &&
284         test_tick &&
285         git commit -m "copied stuff" &&
286         git am -3 lorem-move.patch &&
287         test_path_is_missing .git/rebase-apply &&
288         git diff --exit-code lorem
289 '
290
291 test_expect_success 'am -3 -p0 can read --no-prefix patch' '
292         rm -fr .git/rebase-apply &&
293         git reset --hard &&
294         git checkout -b lorem3 master2 &&
295         sed -n -e "3,\$p" msg >file &&
296         head -n 9 msg >>file &&
297         git add file &&
298         test_tick &&
299         git commit -m "copied stuff" &&
300         git am -3 -p0 lorem-zero.patch &&
301         test_path_is_missing .git/rebase-apply &&
302         git diff --exit-code lorem
303 '
304
305 test_expect_success 'am can rename a file' '
306         grep "^rename from" rename.patch &&
307         rm -fr .git/rebase-apply &&
308         git reset --hard &&
309         git checkout lorem^0 &&
310         git am rename.patch &&
311         test_path_is_missing .git/rebase-apply &&
312         git update-index --refresh &&
313         git diff --exit-code rename
314 '
315
316 test_expect_success 'am -3 can rename a file' '
317         grep "^rename from" rename.patch &&
318         rm -fr .git/rebase-apply &&
319         git reset --hard &&
320         git checkout lorem^0 &&
321         git am -3 rename.patch &&
322         test_path_is_missing .git/rebase-apply &&
323         git update-index --refresh &&
324         git diff --exit-code rename
325 '
326
327 test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
328         grep "^rename from" rename-add.patch &&
329         rm -fr .git/rebase-apply &&
330         git reset --hard &&
331         git checkout lorem^0 &&
332         git am -3 rename-add.patch &&
333         test_path_is_missing .git/rebase-apply &&
334         git update-index --refresh &&
335         git diff --exit-code rename
336 '
337
338 test_expect_success 'am -3 -q is quiet' '
339         rm -fr .git/rebase-apply &&
340         git checkout -f lorem2 &&
341         git reset master2 --hard &&
342         sed -n -e "3,\$p" msg >file &&
343         head -n 9 msg >>file &&
344         git add file &&
345         test_tick &&
346         git commit -m "copied stuff" &&
347         git am -3 -q lorem-move.patch >output.out 2>&1 &&
348         ! test -s output.out
349 '
350
351 test_expect_success 'am pauses on conflict' '
352         rm -fr .git/rebase-apply &&
353         git reset --hard &&
354         git checkout lorem2^^ &&
355         test_must_fail git am lorem-move.patch &&
356         test -d .git/rebase-apply
357 '
358
359 test_expect_success 'am --skip works' '
360         echo goodbye >expected &&
361         git am --skip &&
362         test_path_is_missing .git/rebase-apply &&
363         git diff --exit-code lorem2^^ -- file &&
364         test_cmp expected another
365 '
366
367 test_expect_success 'am --abort removes a stray directory' '
368         mkdir .git/rebase-apply &&
369         git am --abort &&
370         test_path_is_missing .git/rebase-apply
371 '
372
373 test_expect_success 'am --resolved works' '
374         echo goodbye >expected &&
375         rm -fr .git/rebase-apply &&
376         git reset --hard &&
377         git checkout lorem2^^ &&
378         test_must_fail git am lorem-move.patch &&
379         test -d .git/rebase-apply &&
380         echo resolved >>file &&
381         git add file &&
382         git am --resolved &&
383         test_path_is_missing .git/rebase-apply &&
384         test_cmp expected another
385 '
386
387 test_expect_success 'am takes patches from a Pine mailbox' '
388         rm -fr .git/rebase-apply &&
389         git reset --hard &&
390         git checkout first &&
391         cat pine patch1 | git am &&
392         test_path_is_missing .git/rebase-apply &&
393         git diff --exit-code master^..HEAD
394 '
395
396 test_expect_success 'am fails on mail without patch' '
397         rm -fr .git/rebase-apply &&
398         git reset --hard &&
399         test_must_fail git am <failmail &&
400         git am --abort &&
401         test_path_is_missing .git/rebase-apply
402 '
403
404 test_expect_success 'am fails on empty patch' '
405         rm -fr .git/rebase-apply &&
406         git reset --hard &&
407         echo "---" >>failmail &&
408         test_must_fail git am <failmail &&
409         git am --skip &&
410         test_path_is_missing .git/rebase-apply
411 '
412
413 test_expect_success 'am works from stdin in subdirectory' '
414         rm -fr subdir &&
415         rm -fr .git/rebase-apply &&
416         git reset --hard &&
417         git checkout first &&
418         (
419                 mkdir -p subdir &&
420                 cd subdir &&
421                 git am <../patch1
422         ) &&
423         git diff --exit-code second
424 '
425
426 test_expect_success 'am works from file (relative path given) in subdirectory' '
427         rm -fr subdir &&
428         rm -fr .git/rebase-apply &&
429         git reset --hard &&
430         git checkout first &&
431         (
432                 mkdir -p subdir &&
433                 cd subdir &&
434                 git am ../patch1
435         ) &&
436         git diff --exit-code second
437 '
438
439 test_expect_success 'am works from file (absolute path given) in subdirectory' '
440         rm -fr subdir &&
441         rm -fr .git/rebase-apply &&
442         git reset --hard &&
443         git checkout first &&
444         P=$(pwd) &&
445         (
446                 mkdir -p subdir &&
447                 cd subdir &&
448                 git am "$P/patch1"
449         ) &&
450         git diff --exit-code second
451 '
452
453 test_expect_success 'am --committer-date-is-author-date' '
454         rm -fr .git/rebase-apply &&
455         git reset --hard &&
456         git checkout first &&
457         test_tick &&
458         git am --committer-date-is-author-date patch1 &&
459         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
460         sed -ne "/^author /s/.*> //p" head1 >at &&
461         sed -ne "/^committer /s/.*> //p" head1 >ct &&
462         test_cmp at ct
463 '
464
465 test_expect_success 'am without --committer-date-is-author-date' '
466         rm -fr .git/rebase-apply &&
467         git reset --hard &&
468         git checkout first &&
469         test_tick &&
470         git am patch1 &&
471         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
472         sed -ne "/^author /s/.*> //p" head1 >at &&
473         sed -ne "/^committer /s/.*> //p" head1 >ct &&
474         ! test_cmp at ct
475 '
476
477 # This checks for +0000 because TZ is set to UTC and that should
478 # show up when the current time is used. The date in message is set
479 # by test_tick that uses -0700 timezone; if this feature does not
480 # work, we will see that instead of +0000.
481 test_expect_success 'am --ignore-date' '
482         rm -fr .git/rebase-apply &&
483         git reset --hard &&
484         git checkout first &&
485         test_tick &&
486         git am --ignore-date patch1 &&
487         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
488         sed -ne "/^author /s/.*> //p" head1 >at &&
489         grep "+0000" at
490 '
491
492 test_expect_success 'am into an unborn branch' '
493         git rev-parse first^{tree} >expected &&
494         rm -fr .git/rebase-apply &&
495         git reset --hard &&
496         rm -fr subdir &&
497         mkdir subdir &&
498         git format-patch --numbered-files -o subdir -1 first &&
499         (
500                 cd subdir &&
501                 git init &&
502                 git am 1
503         ) &&
504         (
505                 cd subdir &&
506                 git rev-parse HEAD^{tree} >../actual
507         ) &&
508         test_cmp expected actual
509 '
510
511 test_expect_success 'am newline in subject' '
512         rm -fr .git/rebase-apply &&
513         git reset --hard &&
514         git checkout first &&
515         test_tick &&
516         sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
517         git am <patchnl >output.out 2>&1 &&
518         test_i18ngrep "^Applying: second \\\n foo$" output.out
519 '
520
521 test_expect_success 'am -q is quiet' '
522         rm -fr .git/rebase-apply &&
523         git reset --hard &&
524         git checkout first &&
525         test_tick &&
526         git am -q <patch1 >output.out 2>&1 &&
527         ! test -s output.out
528 '
529
530 test_expect_success 'am empty-file does not infloop' '
531         rm -fr .git/rebase-apply &&
532         git reset --hard &&
533         touch empty-file &&
534         test_tick &&
535         test_must_fail git am empty-file 2>actual &&
536         echo Patch format detection failed. >expected &&
537         test_i18ncmp expected actual
538 '
539
540 test_expect_success 'am --message-id really adds the message id' '
541         rm -fr .git/rebase-apply &&
542         git reset --hard &&
543         git checkout HEAD^ &&
544         git am --message-id patch1.eml &&
545         test_path_is_missing .git/rebase-apply &&
546         git cat-file commit HEAD | tail -n1 >actual &&
547         grep Message-Id patch1.eml >expected &&
548         test_cmp expected actual
549 '
550
551 test_expect_success 'am --message-id -s signs off after the message id' '
552         rm -fr .git/rebase-apply &&
553         git reset --hard &&
554         git checkout HEAD^ &&
555         git am -s --message-id patch1.eml &&
556         test_path_is_missing .git/rebase-apply &&
557         git cat-file commit HEAD | tail -n2 | head -n1 >actual &&
558         grep Message-Id patch1.eml >expected &&
559         test_cmp expected actual
560 '
561
562 test_done