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