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