1#!/bin/sh
2
3test_description='git am running'
4
5. ./test-lib.sh
6
7test_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
73test_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
136test_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
148test_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
159test_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
170test_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
178compare () {
179 a=$(git cat-file commit "$2" | grep "^$1 ") &&
180 b=$(git cat-file commit "$3" | grep "^$1 ") &&
181 test "$a" = "$b"
182}
183
184test_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
200test_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
214test_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
220test_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] [foo," 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
231test_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
237test_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\] \[foo\] third" actual
245'
246
247test_expect_failure 'am --keep-non-patch really keeps the non-patch part' '
248 rm -fr .git/rebase-apply &&
249 git reset --hard &&
250 git checkout HEAD^ &&
251 git am --keep-non-patch patch4 &&
252 ! test -d .git/rebase-apply &&
253 git cat-file commit HEAD >actual &&
254 grep "^\[foo\] third" actual
255'
256
257test_expect_success 'am -3 falls back to 3-way merge' '
258 rm -fr .git/rebase-apply &&
259 git reset --hard &&
260 git checkout -b lorem2 master2 &&
261 sed -n -e "3,\$p" msg >file &&
262 head -n 9 msg >>file &&
263 git add file &&
264 test_tick &&
265 git commit -m "copied stuff" &&
266 git am -3 lorem-move.patch &&
267 ! test -d .git/rebase-apply &&
268 git diff --exit-code lorem
269'
270
271test_expect_success 'am can rename a file' '
272 grep "^rename from" rename.patch &&
273 rm -fr .git/rebase-apply &&
274 git reset --hard &&
275 git checkout lorem^0 &&
276 git am rename.patch &&
277 ! test -d .git/rebase-apply &&
278 git update-index --refresh &&
279 git diff --exit-code rename
280'
281
282test_expect_success 'am -3 can rename a file' '
283 grep "^rename from" rename.patch &&
284 rm -fr .git/rebase-apply &&
285 git reset --hard &&
286 git checkout lorem^0 &&
287 git am -3 rename.patch &&
288 ! test -d .git/rebase-apply &&
289 git update-index --refresh &&
290 git diff --exit-code rename
291'
292
293test_expect_success 'am -3 can rename a file after falling back to 3-way merge' '
294 grep "^rename from" rename-add.patch &&
295 rm -fr .git/rebase-apply &&
296 git reset --hard &&
297 git checkout lorem^0 &&
298 git am -3 rename-add.patch &&
299 ! test -d .git/rebase-apply &&
300 git update-index --refresh &&
301 git diff --exit-code rename
302'
303
304test_expect_success 'am -3 -q is quiet' '
305 rm -fr .git/rebase-apply &&
306 git checkout -f lorem2 &&
307 git reset master2 --hard &&
308 sed -n -e "3,\$p" msg >file &&
309 head -n 9 msg >>file &&
310 git add file &&
311 test_tick &&
312 git commit -m "copied stuff" &&
313 git am -3 -q lorem-move.patch >output.out 2>&1 &&
314 ! test -s output.out
315'
316
317test_expect_success 'am pauses on conflict' '
318 rm -fr .git/rebase-apply &&
319 git reset --hard &&
320 git checkout lorem2^^ &&
321 test_must_fail git am lorem-move.patch &&
322 test -d .git/rebase-apply
323'
324
325test_expect_success 'am --skip works' '
326 echo goodbye >expected &&
327 git am --skip &&
328 ! test -d .git/rebase-apply &&
329 git diff --exit-code lorem2^^ -- file &&
330 test_cmp expected another
331'
332
333test_expect_success 'am --resolved works' '
334 echo goodbye >expected &&
335 rm -fr .git/rebase-apply &&
336 git reset --hard &&
337 git checkout lorem2^^ &&
338 test_must_fail git am lorem-move.patch &&
339 test -d .git/rebase-apply &&
340 echo resolved >>file &&
341 git add file &&
342 git am --resolved &&
343 ! test -d .git/rebase-apply &&
344 test_cmp expected another
345'
346
347test_expect_success 'am takes patches from a Pine mailbox' '
348 rm -fr .git/rebase-apply &&
349 git reset --hard &&
350 git checkout first &&
351 cat pine patch1 | git am &&
352 ! test -d .git/rebase-apply &&
353 git diff --exit-code master^..HEAD
354'
355
356test_expect_success 'am fails on mail without patch' '
357 rm -fr .git/rebase-apply &&
358 git reset --hard &&
359 test_must_fail git am <failmail &&
360 git am --abort &&
361 ! test -d .git/rebase-apply
362'
363
364test_expect_success 'am fails on empty patch' '
365 rm -fr .git/rebase-apply &&
366 git reset --hard &&
367 echo "---" >>failmail &&
368 test_must_fail git am <failmail &&
369 git am --skip &&
370 ! test -d .git/rebase-apply
371'
372
373test_expect_success 'am works from stdin in subdirectory' '
374 rm -fr subdir &&
375 rm -fr .git/rebase-apply &&
376 git reset --hard &&
377 git checkout first &&
378 (
379 mkdir -p subdir &&
380 cd subdir &&
381 git am <../patch1
382 ) &&
383 git diff --exit-code second
384'
385
386test_expect_success 'am works from file (relative path given) in subdirectory' '
387 rm -fr subdir &&
388 rm -fr .git/rebase-apply &&
389 git reset --hard &&
390 git checkout first &&
391 (
392 mkdir -p subdir &&
393 cd subdir &&
394 git am ../patch1
395 ) &&
396 git diff --exit-code second
397'
398
399test_expect_success 'am works from file (absolute path given) in subdirectory' '
400 rm -fr subdir &&
401 rm -fr .git/rebase-apply &&
402 git reset --hard &&
403 git checkout first &&
404 P=$(pwd) &&
405 (
406 mkdir -p subdir &&
407 cd subdir &&
408 git am "$P/patch1"
409 ) &&
410 git diff --exit-code second
411'
412
413test_expect_success 'am --committer-date-is-author-date' '
414 rm -fr .git/rebase-apply &&
415 git reset --hard &&
416 git checkout first &&
417 test_tick &&
418 git am --committer-date-is-author-date patch1 &&
419 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
420 sed -ne "/^author /s/.*> //p" head1 >at &&
421 sed -ne "/^committer /s/.*> //p" head1 >ct &&
422 test_cmp at ct
423'
424
425test_expect_success 'am without --committer-date-is-author-date' '
426 rm -fr .git/rebase-apply &&
427 git reset --hard &&
428 git checkout first &&
429 test_tick &&
430 git am patch1 &&
431 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
432 sed -ne "/^author /s/.*> //p" head1 >at &&
433 sed -ne "/^committer /s/.*> //p" head1 >ct &&
434 ! test_cmp at ct
435'
436
437# This checks for +0000 because TZ is set to UTC and that should
438# show up when the current time is used. The date in message is set
439# by test_tick that uses -0700 timezone; if this feature does not
440# work, we will see that instead of +0000.
441test_expect_success 'am --ignore-date' '
442 rm -fr .git/rebase-apply &&
443 git reset --hard &&
444 git checkout first &&
445 test_tick &&
446 git am --ignore-date patch1 &&
447 git cat-file commit HEAD | sed -e "/^\$/q" >head1 &&
448 sed -ne "/^author /s/.*> //p" head1 >at &&
449 grep "+0000" at
450'
451
452test_expect_success 'am into an unborn branch' '
453 git rev-parse first^{tree} >expected &&
454 rm -fr .git/rebase-apply &&
455 git reset --hard &&
456 rm -fr subdir &&
457 mkdir subdir &&
458 git format-patch --numbered-files -o subdir -1 first &&
459 (
460 cd subdir &&
461 git init &&
462 git am 1
463 ) &&
464 (
465 cd subdir &&
466 git rev-parse HEAD^{tree} >../actual
467 ) &&
468 test_cmp expected actual
469'
470
471test_expect_success 'am newline in subject' '
472 rm -fr .git/rebase-apply &&
473 git reset --hard &&
474 git checkout first &&
475 test_tick &&
476 sed -e "s/second/second \\\n foo/" patch1 >patchnl &&
477 git am <patchnl >output.out 2>&1 &&
478 grep "^Applying: second \\\n foo$" output.out
479'
480
481test_expect_success 'am -q is quiet' '
482 rm -fr .git/rebase-apply &&
483 git reset --hard &&
484 git checkout first &&
485 test_tick &&
486 git am -q <patch1 >output.out 2>&1 &&
487 ! test -s output.out
488'
489
490test_done