pack-refs: prune top-level refs like "refs/foo"
[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 "X-Fake-Field: Line One" &&
89                 echo "X-Fake-Field: Line Two" &&
90                 echo "X-Fake-Field: Line Three" &&
91                 git format-patch --stdout first | sed -e "1d"
92         } > patch1.eml &&
93         {
94                 echo "X-Fake-Field: Line One" &&
95                 echo "X-Fake-Field: Line Two" &&
96                 echo "X-Fake-Field: Line Three" &&
97                 git format-patch --stdout first | sed -e "1d"
98         } | append_cr >patch1-crlf.eml &&
99         {
100                 printf "%255s\\n" ""
101                 echo "X-Fake-Field: Line One" &&
102                 echo "X-Fake-Field: Line Two" &&
103                 echo "X-Fake-Field: Line Three" &&
104                 git format-patch --stdout first | sed -e "1d"
105         } > patch1-ws.eml &&
106
107         sed -n -e "3,\$p" msg >file &&
108         git add file &&
109         test_tick &&
110         git commit -m third &&
111
112         git format-patch --stdout first >patch2 &&
113
114         git checkout -b lorem &&
115         sed -n -e "11,\$p" msg >file &&
116         head -n 9 msg >>file &&
117         test_tick &&
118         git commit -a -m "moved stuff" &&
119
120         echo goodbye >another &&
121         git add another &&
122         test_tick &&
123         git commit -m "added another file" &&
124
125         git format-patch --stdout master >lorem-move.patch &&
126         git format-patch --no-prefix --stdout master >lorem-zero.patch &&
127
128         git checkout -b rename &&
129         git mv file renamed &&
130         git commit -m "renamed a file" &&
131
132         git format-patch -M --stdout lorem >rename.patch &&
133
134         git reset --soft lorem^ &&
135         git commit -m "renamed a file and added another" &&
136
137         git format-patch -M --stdout lorem^ >rename-add.patch &&
138
139         # reset time
140         sane_unset test_tick &&
141         test_tick
142 '
143
144 test_expect_success 'am applies patch correctly' '
145         rm -fr .git/rebase-apply &&
146         git reset --hard &&
147         git checkout first &&
148         test_tick &&
149         git am <patch1 &&
150         test_path_is_missing .git/rebase-apply &&
151         git diff --exit-code second &&
152         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
153         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
154 '
155
156 test_expect_success 'am applies patch e-mail not in a mbox' '
157         rm -fr .git/rebase-apply &&
158         git reset --hard &&
159         git checkout first &&
160         git am patch1.eml &&
161         test_path_is_missing .git/rebase-apply &&
162         git diff --exit-code second &&
163         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
164         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
165 '
166
167 test_expect_success 'am applies patch e-mail not in a mbox with CRLF' '
168         rm -fr .git/rebase-apply &&
169         git reset --hard &&
170         git checkout first &&
171         git am patch1-crlf.eml &&
172         test_path_is_missing .git/rebase-apply &&
173         git diff --exit-code second &&
174         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
175         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
176 '
177
178 test_expect_success 'am applies patch e-mail with preceding whitespace' '
179         rm -fr .git/rebase-apply &&
180         git reset --hard &&
181         git checkout first &&
182         git am patch1-ws.eml &&
183         test_path_is_missing .git/rebase-apply &&
184         git diff --exit-code second &&
185         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
186         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
187 '
188
189 test_expect_success 'setup: new author and committer' '
190         GIT_AUTHOR_NAME="Another Thor" &&
191         GIT_AUTHOR_EMAIL="a.thor@example.com" &&
192         GIT_COMMITTER_NAME="Co M Miter" &&
193         GIT_COMMITTER_EMAIL="c.miter@example.com" &&
194         export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
195 '
196
197 compare () {
198         a=$(git cat-file commit "$2" | grep "^$1 ") &&
199         b=$(git cat-file commit "$3" | grep "^$1 ") &&
200         test "$a" = "$b"
201 }
202
203 test_expect_success 'am changes committer and keeps author' '
204         test_tick &&
205         rm -fr .git/rebase-apply &&
206         git reset --hard &&
207         git checkout first &&
208         git am patch2 &&
209         test_path_is_missing .git/rebase-apply &&
210         test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
211         git diff --exit-code master..HEAD &&
212         git diff --exit-code master^..HEAD^ &&
213         compare author master HEAD &&
214         compare author master^ HEAD^ &&
215         test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
216              "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
217 '
218
219 test_expect_success 'am --signoff adds Signed-off-by: line' '
220         rm -fr .git/rebase-apply &&
221         git reset --hard &&
222         git checkout -b master2 first &&
223         git am --signoff <patch2 &&
224         printf "%s\n" "$signoff" >expected &&
225         echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected &&
226         git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
227         test_cmp expected actual &&
228         echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
229         git cat-file commit HEAD | grep "Signed-off-by:" >actual &&
230         test_cmp expected actual
231 '
232
233 test_expect_success 'am stays in branch' '
234         echo refs/heads/master2 >expected &&
235         git symbolic-ref HEAD >actual &&
236         test_cmp expected actual
237 '
238
239 test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
240         git format-patch --stdout HEAD^ >patch3 &&
241         sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," patch3 >patch4 &&
242         rm -fr .git/rebase-apply &&
243         git reset --hard &&
244         git checkout HEAD^ &&
245         git am --signoff patch4 &&
246         git cat-file commit HEAD >actual &&
247         test $(grep -c "^Signed-off-by:" actual) -eq 1
248 '
249
250 test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
251         git rev-parse HEAD >expected &&
252         git rev-parse master2 >actual &&
253         test_cmp expected actual
254 '
255
256 test_expect_success 'am --keep really keeps the subject' '
257         rm -fr .git/rebase-apply &&
258         git reset --hard &&
259         git checkout HEAD^ &&
260         git am --keep patch4 &&
261         test_path_is_missing .git/rebase-apply &&
262         git cat-file commit HEAD >actual &&
263         grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
264 '
265
266 test_expect_success 'am --keep-non-patch really keeps the non-patch part' '
267         rm -fr .git/rebase-apply &&
268         git reset --hard &&
269         git checkout HEAD^ &&
270         git am --keep-non-patch patch4 &&
271         test_path_is_missing .git/rebase-apply &&
272         git cat-file commit HEAD >actual &&
273         grep "^\[foo\] third" actual
274 '
275
276 test_expect_success 'am -3 falls back to 3-way merge' '
277         rm -fr .git/rebase-apply &&
278         git reset --hard &&
279         git checkout -b lorem2 master2 &&
280         sed -n -e "3,\$p" msg >file &&
281         head -n 9 msg >>file &&
282         git add file &&
283         test_tick &&
284         git commit -m "copied stuff" &&
285         git am -3 lorem-move.patch &&
286         test_path_is_missing .git/rebase-apply &&
287         git diff --exit-code lorem
288 '
289
290 test_expect_success 'am -3 -p0 can read --no-prefix patch' '
291         rm -fr .git/rebase-apply &&
292         git reset --hard &&
293         git checkout -b lorem3 master2 &&
294         sed -n -e "3,\$p" msg >file &&
295         head -n 9 msg >>file &&
296         git add file &&
297         test_tick &&
298         git commit -m "copied stuff" &&
299         git am -3 -p0 lorem-zero.patch &&
300         test_path_is_missing .git/rebase-apply &&
301         git diff --exit-code lorem
302 '
303
304 test_expect_success 'am can rename a file' '
305         grep "^rename from" rename.patch &&
306         rm -fr .git/rebase-apply &&
307         git reset --hard &&
308         git checkout lorem^0 &&
309         git am rename.patch &&
310         test_path_is_missing .git/rebase-apply &&
311         git update-index --refresh &&
312         git diff --exit-code rename
313 '
314
315 test_expect_success 'am -3 can rename a file' '
316         grep "^rename from" rename.patch &&
317         rm -fr .git/rebase-apply &&
318         git reset --hard &&
319         git checkout lorem^0 &&
320         git am -3 rename.patch &&
321         test_path_is_missing .git/rebase-apply &&
322         git update-index --refresh &&
323         git diff --exit-code rename
324 '
325
326 test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
327         grep "^rename from" rename-add.patch &&
328         rm -fr .git/rebase-apply &&
329         git reset --hard &&
330         git checkout lorem^0 &&
331         git am -3 rename-add.patch &&
332         test_path_is_missing .git/rebase-apply &&
333         git update-index --refresh &&
334         git diff --exit-code rename
335 '
336
337 test_expect_success 'am -3 -q is quiet' '
338         rm -fr .git/rebase-apply &&
339         git checkout -f lorem2 &&
340         git reset master2 --hard &&
341         sed -n -e "3,\$p" msg >file &&
342         head -n 9 msg >>file &&
343         git add file &&
344         test_tick &&
345         git commit -m "copied stuff" &&
346         git am -3 -q lorem-move.patch >output.out 2>&1 &&
347         ! test -s output.out
348 '
349
350 test_expect_success 'am pauses on conflict' '
351         rm -fr .git/rebase-apply &&
352         git reset --hard &&
353         git checkout lorem2^^ &&
354         test_must_fail git am lorem-move.patch &&
355         test -d .git/rebase-apply
356 '
357
358 test_expect_success 'am --skip works' '
359         echo goodbye >expected &&
360         git am --skip &&
361         test_path_is_missing .git/rebase-apply &&
362         git diff --exit-code lorem2^^ -- file &&
363         test_cmp expected another
364 '
365
366 test_expect_success 'am --abort removes a stray directory' '
367         mkdir .git/rebase-apply &&
368         git am --abort &&
369         test_path_is_missing .git/rebase-apply
370 '
371
372 test_expect_success 'am --resolved works' '
373         echo goodbye >expected &&
374         rm -fr .git/rebase-apply &&
375         git reset --hard &&
376         git checkout lorem2^^ &&
377         test_must_fail git am lorem-move.patch &&
378         test -d .git/rebase-apply &&
379         echo resolved >>file &&
380         git add file &&
381         git am --resolved &&
382         test_path_is_missing .git/rebase-apply &&
383         test_cmp expected another
384 '
385
386 test_expect_success 'am takes patches from a Pine mailbox' '
387         rm -fr .git/rebase-apply &&
388         git reset --hard &&
389         git checkout first &&
390         cat pine patch1 | git am &&
391         test_path_is_missing .git/rebase-apply &&
392         git diff --exit-code master^..HEAD
393 '
394
395 test_expect_success 'am fails on mail without patch' '
396         rm -fr .git/rebase-apply &&
397         git reset --hard &&
398         test_must_fail git am <failmail &&
399         git am --abort &&
400         test_path_is_missing .git/rebase-apply
401 '
402
403 test_expect_success 'am fails on empty patch' '
404         rm -fr .git/rebase-apply &&
405         git reset --hard &&
406         echo "---" >>failmail &&
407         test_must_fail git am <failmail &&
408         git am --skip &&
409         test_path_is_missing .git/rebase-apply
410 '
411
412 test_expect_success 'am works from stdin in subdirectory' '
413         rm -fr subdir &&
414         rm -fr .git/rebase-apply &&
415         git reset --hard &&
416         git checkout first &&
417         (
418                 mkdir -p subdir &&
419                 cd subdir &&
420                 git am <../patch1
421         ) &&
422         git diff --exit-code second
423 '
424
425 test_expect_success 'am works from file (relative path given) in subdirectory' '
426         rm -fr subdir &&
427         rm -fr .git/rebase-apply &&
428         git reset --hard &&
429         git checkout first &&
430         (
431                 mkdir -p subdir &&
432                 cd subdir &&
433                 git am ../patch1
434         ) &&
435         git diff --exit-code second
436 '
437
438 test_expect_success 'am works from file (absolute path given) in subdirectory' '
439         rm -fr subdir &&
440         rm -fr .git/rebase-apply &&
441         git reset --hard &&
442         git checkout first &&
443         P=$(pwd) &&
444         (
445                 mkdir -p subdir &&
446                 cd subdir &&
447                 git am "$P/patch1"
448         ) &&
449         git diff --exit-code second
450 '
451
452 test_expect_success 'am --committer-date-is-author-date' '
453         rm -fr .git/rebase-apply &&
454         git reset --hard &&
455         git checkout first &&
456         test_tick &&
457         git am --committer-date-is-author-date patch1 &&
458         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
459         sed -ne "/^author /s/.*> //p" head1 >at &&
460         sed -ne "/^committer /s/.*> //p" head1 >ct &&
461         test_cmp at ct
462 '
463
464 test_expect_success 'am without --committer-date-is-author-date' '
465         rm -fr .git/rebase-apply &&
466         git reset --hard &&
467         git checkout first &&
468         test_tick &&
469         git am patch1 &&
470         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
471         sed -ne "/^author /s/.*> //p" head1 >at &&
472         sed -ne "/^committer /s/.*> //p" head1 >ct &&
473         ! test_cmp at ct
474 '
475
476 # This checks for +0000 because TZ is set to UTC and that should
477 # show up when the current time is used. The date in message is set
478 # by test_tick that uses -0700 timezone; if this feature does not
479 # work, we will see that instead of +0000.
480 test_expect_success 'am --ignore-date' '
481         rm -fr .git/rebase-apply &&
482         git reset --hard &&
483         git checkout first &&
484         test_tick &&
485         git am --ignore-date patch1 &&
486         git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
487         sed -ne "/^author /s/.*> //p" head1 >at &&
488         grep "+0000" at
489 '
490
491 test_expect_success 'am into an unborn branch' '
492         git rev-parse first^{tree} >expected &&
493         rm -fr .git/rebase-apply &&
494         git reset --hard &&
495         rm -fr subdir &&
496         mkdir subdir &&
497         git format-patch --numbered-files -o subdir -1 first &&
498         (
499                 cd subdir &&
500                 git init &&
501                 git am 1
502         ) &&
503         (
504                 cd subdir &&
505                 git rev-parse HEAD^{tree} >../actual
506         ) &&
507         test_cmp expected actual
508 '
509
510 test_expect_success 'am newline in subject' '
511         rm -fr .git/rebase-apply &&
512         git reset --hard &&
513         git checkout first &&
514         test_tick &&
515         sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
516         git am <patchnl >output.out 2>&1 &&
517         test_i18ngrep "^Applying: second \\\n foo$" output.out
518 '
519
520 test_expect_success 'am -q is quiet' '
521         rm -fr .git/rebase-apply &&
522         git reset --hard &&
523         git checkout first &&
524         test_tick &&
525         git am -q <patch1 >output.out 2>&1 &&
526         ! test -s output.out
527 '
528
529 test_expect_success 'am empty-file does not infloop' '
530         rm -fr .git/rebase-apply &&
531         git reset --hard &&
532         touch empty-file &&
533         test_tick &&
534         test_must_fail git am empty-file 2>actual &&
535         echo Patch format detection failed. >expected &&
536         test_i18ncmp expected actual
537 '
538
539 test_done