bash: teach 'git checkout' options
[git] / t / t4150-am.sh
1 #!/bin/sh
2
3 test_description='git am running'
4
5 . ./test-lib.sh
6
7 cat >msg <<EOF
8 second
9
10 Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy
11 eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
12 voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita
13 kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem
14 ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
15 tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
16 vero eos et accusam et justo duo dolores et ea rebum.
17
18         Duis autem vel eum iriure dolor in hendrerit in vulputate velit
19         esse molestie consequat, vel illum dolore eu feugiat nulla facilisis
20         at vero eros et accumsan et iusto odio dignissim qui blandit
21         praesent luptatum zzril delenit augue duis dolore te feugait nulla
22         facilisi.
23
24
25 Lorem ipsum dolor sit amet,
26 consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut
27 laoreet dolore magna aliquam erat volutpat.
28
29   git
30   ---
31   +++
32
33 Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit
34 lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure
35 dolor in hendrerit in vulputate velit esse molestie consequat, vel illum
36 dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
37 dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te
38 feugait nulla facilisi.
39 EOF
40
41 cat >failmail <<EOF
42 From foo@example.com Fri May 23 10:43:49 2008
43 From:   foo@example.com
44 To:     bar@example.com
45 Subject: Re: [RFC/PATCH] git-foo.sh
46 Date:   Fri, 23 May 2008 05:23:42 +0200
47
48 Sometimes we have to find out that there's nothing left.
49
50 EOF
51
52 cat >pine <<EOF
53 From MAILER-DAEMON Fri May 23 10:43:49 2008
54 Date: 23 May 2008 05:23:42 +0200
55 From: Mail System Internal Data <MAILER-DAEMON@example.com>
56 Subject: DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA
57 Message-ID: <foo-0001@example.com>
58
59 This text is part of the internal format of your mail folder, and is not
60 a real message.  It is created automatically by the mail system software.
61 If deleted, important folder data will be lost, and it will be re-created
62 with the data reset to initial values.
63
64 EOF
65
66 echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected
67
68 test_expect_success setup '
69         echo hello >file &&
70         git add file &&
71         test_tick &&
72         git commit -m first &&
73         git tag first &&
74         echo world >>file &&
75         git add file &&
76         test_tick &&
77         git commit -s -F msg &&
78         git tag second &&
79         git format-patch --stdout first >patch1 &&
80         {
81                 echo "X-Fake-Field: Line One" &&
82                 echo "X-Fake-Field: Line Two" &&
83                 echo "X-Fake-Field: Line Three" &&
84                 git format-patch --stdout first | sed -e "1d"
85         } > patch1.eml &&
86         sed -n -e "3,\$p" msg >file &&
87         git add file &&
88         test_tick &&
89         git commit -m third &&
90         git format-patch --stdout first >patch2 &&
91         git checkout -b lorem &&
92         sed -n -e "11,\$p" msg >file &&
93         head -n 9 msg >>file &&
94         test_tick &&
95         git commit -a -m "moved stuff" &&
96         echo goodbye >another &&
97         git add another &&
98         test_tick &&
99         git commit -m "added another file" &&
100         git format-patch --stdout master >lorem-move.patch
101 '
102
103 # reset time
104 unset test_tick
105 test_tick
106
107 test_expect_success 'am applies patch correctly' '
108         git checkout first &&
109         test_tick &&
110         git am <patch1 &&
111         ! test -d .git/rebase-apply &&
112         test -z "$(git diff second)" &&
113         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
114         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
115 '
116
117 test_expect_success 'am applies patch e-mail not in a mbox' '
118         git checkout first &&
119         git am patch1.eml &&
120         ! test -d .git/rebase-apply &&
121         test -z "$(git diff second)" &&
122         test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
123         test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
124 '
125
126 GIT_AUTHOR_NAME="Another Thor"
127 GIT_AUTHOR_EMAIL="a.thor@example.com"
128 GIT_COMMITTER_NAME="Co M Miter"
129 GIT_COMMITTER_EMAIL="c.miter@example.com"
130 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
131
132 compare () {
133         test "$(git cat-file commit "$2" | grep "^$1 ")" = \
134              "$(git cat-file commit "$3" | grep "^$1 ")"
135 }
136
137 test_expect_success 'am changes committer and keeps author' '
138         test_tick &&
139         git checkout first &&
140         git am patch2 &&
141         ! test -d .git/rebase-apply &&
142         test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
143         test -z "$(git diff master..HEAD)" &&
144         test -z "$(git diff master^..HEAD^)" &&
145         compare author master HEAD &&
146         compare author master^ HEAD^ &&
147         test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
148              "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)"
149 '
150
151 test_expect_success 'am --signoff adds Signed-off-by: line' '
152         git checkout -b master2 first &&
153         git am --signoff <patch2 &&
154         echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected &&
155         git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
156         test_cmp actual expected &&
157         echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
158         git cat-file commit HEAD | grep "Signed-off-by:" >actual &&
159         test_cmp actual expected
160 '
161
162 test_expect_success 'am stays in branch' '
163         test "refs/heads/master2" = "$(git symbolic-ref HEAD)"
164 '
165
166 test_expect_success 'am --signoff does not add Signed-off-by: line if already there' '
167         git format-patch --stdout HEAD^ >patch3 &&
168         sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2," patch3 >patch4
169         git checkout HEAD^ &&
170         git am --signoff patch4 &&
171         test "$(git cat-file commit HEAD | grep -c "^Signed-off-by:")" -eq 1
172 '
173
174 test_expect_success 'am without --keep removes Re: and [PATCH] stuff' '
175         test "$(git rev-parse HEAD)" = "$(git rev-parse master2)"
176 '
177
178 test_expect_success 'am --keep really keeps the subject' '
179         git checkout HEAD^ &&
180         git am --keep patch4 &&
181         ! test -d .git/rebase-apply &&
182         git cat-file commit HEAD |
183                 fgrep "Re: Re: Re: [PATCH 1/5 v2] third"
184 '
185
186 test_expect_success 'am -3 falls back to 3-way merge' '
187         git checkout -b lorem2 master2 &&
188         sed -n -e "3,\$p" msg >file &&
189         head -n 9 msg >>file &&
190         git add file &&
191         test_tick &&
192         git commit -m "copied stuff" &&
193         git am -3 lorem-move.patch &&
194         ! test -d .git/rebase-apply &&
195         test -z "$(git diff lorem)"
196 '
197
198 test_expect_success 'am -3 -q is quiet' '
199         git reset master2 --hard &&
200         sed -n -e "3,\$p" msg >file &&
201         head -n 9 msg >>file &&
202         git add file &&
203         test_tick &&
204         git commit -m "copied stuff" &&
205         git am -3 -q lorem-move.patch > output.out 2>&1 &&
206         ! test -s output.out
207 '
208
209 test_expect_success 'am pauses on conflict' '
210         git checkout lorem2^^ &&
211         test_must_fail git am lorem-move.patch &&
212         test -d .git/rebase-apply
213 '
214
215 test_expect_success 'am --skip works' '
216         git am --skip &&
217         ! test -d .git/rebase-apply &&
218         test -z "$(git diff lorem2^^ -- file)" &&
219         test goodbye = "$(cat another)"
220 '
221
222 test_expect_success 'am --resolved works' '
223         git checkout lorem2^^ &&
224         test_must_fail git am lorem-move.patch &&
225         test -d .git/rebase-apply &&
226         echo resolved >>file &&
227         git add file &&
228         git am --resolved &&
229         ! test -d .git/rebase-apply &&
230         test goodbye = "$(cat another)"
231 '
232
233 test_expect_success 'am takes patches from a Pine mailbox' '
234         git checkout first &&
235         cat pine patch1 | git am &&
236         ! test -d .git/rebase-apply &&
237         test -z "$(git diff master^..HEAD)"
238 '
239
240 test_expect_success 'am fails on mail without patch' '
241         test_must_fail git am <failmail &&
242         rm -r .git/rebase-apply/
243 '
244
245 test_expect_success 'am fails on empty patch' '
246         echo "---" >>failmail &&
247         test_must_fail git am <failmail &&
248         git am --skip &&
249         ! test -d .git/rebase-apply
250 '
251
252 test_expect_success 'am works from stdin in subdirectory' '
253         rm -fr subdir &&
254         git checkout first &&
255         (
256                 mkdir -p subdir &&
257                 cd subdir &&
258                 git am <../patch1
259         ) &&
260         test -z "$(git diff second)"
261 '
262
263 test_expect_success 'am works from file (relative path given) in subdirectory' '
264         rm -fr subdir &&
265         git checkout first &&
266         (
267                 mkdir -p subdir &&
268                 cd subdir &&
269                 git am ../patch1
270         ) &&
271         test -z "$(git diff second)"
272 '
273
274 test_expect_success 'am works from file (absolute path given) in subdirectory' '
275         rm -fr subdir &&
276         git checkout first &&
277         P=$(pwd) &&
278         (
279                 mkdir -p subdir &&
280                 cd subdir &&
281                 git am "$P/patch1"
282         ) &&
283         test -z "$(git diff second)"
284 '
285
286 test_expect_success 'am --committer-date-is-author-date' '
287         git checkout first &&
288         test_tick &&
289         git am --committer-date-is-author-date patch1 &&
290         git cat-file commit HEAD | sed -e "/^$/q" >head1 &&
291         at=$(sed -ne "/^author /s/.*> //p" head1) &&
292         ct=$(sed -ne "/^committer /s/.*> //p" head1) &&
293         test "$at" = "$ct"
294 '
295
296 test_expect_success 'am without --committer-date-is-author-date' '
297         git checkout first &&
298         test_tick &&
299         git am patch1 &&
300         git cat-file commit HEAD | sed -e "/^$/q" >head1 &&
301         at=$(sed -ne "/^author /s/.*> //p" head1) &&
302         ct=$(sed -ne "/^committer /s/.*> //p" head1) &&
303         test "$at" != "$ct"
304 '
305
306 # This checks for +0000 because TZ is set to UTC and that should
307 # show up when the current time is used. The date in message is set
308 # by test_tick that uses -0700 timezone; if this feature does not
309 # work, we will see that instead of +0000.
310 test_expect_success 'am --ignore-date' '
311         git checkout first &&
312         test_tick &&
313         git am --ignore-date patch1 &&
314         git cat-file commit HEAD | sed -e "/^$/q" >head1 &&
315         at=$(sed -ne "/^author /s/.*> //p" head1) &&
316         echo "$at" | grep "+0000"
317 '
318
319 test_expect_success 'am into an unborn branch' '
320         rm -fr subdir &&
321         mkdir -p subdir &&
322         git format-patch --numbered-files -o subdir -1 first &&
323         (
324                 cd subdir &&
325                 git init &&
326                 git am 1
327         ) &&
328         result=$(
329                 cd subdir && git rev-parse HEAD^{tree}
330         ) &&
331         test "z$result" = "z$(git rev-parse first^{tree})"
332 '
333
334 test_expect_success 'am newline in subject' '
335         git checkout first &&
336         test_tick &&
337         sed -e "s/second/second \\\n foo/" patch1 > patchnl &&
338         git am < patchnl > output.out 2>&1 &&
339         grep "^Applying: second \\\n foo$" output.out
340 '
341
342 test_expect_success 'am -q is quiet' '
343         git checkout first &&
344         test_tick &&
345         git am -q < patch1 > output.out 2>&1 &&
346         ! test -s output.out
347 '
348
349 test_done