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