#!/bin/sh global test_description := ''git am running'' source ./test-lib.sh test_expect_success 'setup: messages' ' cat >msg <<-\EOF && second Lorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. EOF qz_to_tab_space <<-\EOF >>msg && QDuis autem vel eum iriure dolor in hendrerit in vulputate velit Qesse molestie consequat, vel illum dolore eu feugiat nulla facilisis Qat vero eros et accumsan et iusto odio dignissim qui blandit Qpraesent luptatum zzril delenit augue duis dolore te feugait nulla Qfacilisi. EOF cat >>msg <<-\EOF && Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. git --- +++ Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. EOF cat >failmail <<-\EOF && From foo@example.com Fri May 23 10:43:49 2008 From: foo@example.com To: bar@example.com Subject: Re: [RFC/PATCH] git-foo.sh Date: Fri, 23 May 2008 05:23:42 +0200 Sometimes we have to find out that there'''''s nothing left. EOF cat >pine <<-\EOF && From MAILER-DAEMON Fri May 23 10:43:49 2008 Date: 23 May 2008 05:23:42 +0200 From: Mail System Internal Data Subject: DON'''''T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA Message-ID: This text is part of the internal format of your mail folder, and is not a real message. It is created automatically by the mail system software. If deleted, important folder data will be lost, and it will be re-created with the data reset to initial values. EOF cat >scissors-msg <<-\EOF && Test git-am with scissors line This line should be included in the commit message. EOF cat - scissors-msg >no-scissors-msg <<-\EOF && This line should not be included in the commit message with --scissors enabled. - - >8 - - remove everything above this line - - >8 - - EOF signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" ' test_expect_success setup ' echo hello >file && git add file && test_tick && git commit -m first && git tag first && echo world >>file && git add file && test_tick && git commit -s -F msg && git tag second && git format-patch --stdout first >patch1 && { echo "Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" && echo "X-Fake-Field: Line One" && echo "X-Fake-Field: Line Two" && echo "X-Fake-Field: Line Three" && git format-patch --stdout first | sed -e "1d" } > patch1.eml && { echo "X-Fake-Field: Line One" && echo "X-Fake-Field: Line Two" && echo "X-Fake-Field: Line Three" && git format-patch --stdout first | sed -e "1d" } | append_cr >patch1-crlf.eml && { printf "%255s\\n" "" echo "X-Fake-Field: Line One" && echo "X-Fake-Field: Line Two" && echo "X-Fake-Field: Line Three" && git format-patch --stdout first | sed -e "1d" } > patch1-ws.eml && { sed -ne "1p" msg && echo && echo "From: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" && echo "Date: $GIT_AUTHOR_DATE" && echo && sed -e "1,2d" msg && echo && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" && echo "---" && git diff-tree --no-commit-id --stat -p second } >patch1-stgit.eml && mkdir stgit-series && cp patch1-stgit.eml stgit-series/patch && { echo "# This series applies on GIT commit $(git rev-parse first)" && echo "patch" } >stgit-series/series && { echo "# HG changeset patch" && echo "# User $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" && echo "# Date $test_tick 25200" && echo "# $(git show --pretty="%aD" -s second)" && echo "# Node ID $_z40" && echo "# Parent $_z40" && cat msg && echo && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" && echo && git diff-tree --no-commit-id -p second } >patch1-hg.eml && echo scissors-file >scissors-file && git add scissors-file && git commit -F scissors-msg && git tag scissors && git format-patch --stdout scissors^ >scissors-patch.eml && git reset --hard HEAD^ && echo no-scissors-file >no-scissors-file && git add no-scissors-file && git commit -F no-scissors-msg && git tag no-scissors && git format-patch --stdout no-scissors^ >no-scissors-patch.eml && git reset --hard HEAD^ && sed -n -e "3,\$p" msg >file && git add file && test_tick && git commit -m third && git format-patch --stdout first >patch2 && git checkout -b lorem && sed -n -e "11,\$p" msg >file && head -n 9 msg >>file && test_tick && git commit -a -m "moved stuff" && echo goodbye >another && git add another && test_tick && git commit -m "added another file" && git format-patch --stdout master >lorem-move.patch && git format-patch --no-prefix --stdout master >lorem-zero.patch && git checkout -b rename && git mv file renamed && git commit -m "renamed a file" && git format-patch -M --stdout lorem >rename.patch && git reset --soft lorem^ && git commit -m "renamed a file and added another" && git format-patch -M --stdout lorem^ >rename-add.patch && # reset time sane_unset test_tick && test_tick ' test_expect_success 'am applies patch correctly' ' rm -fr .git/rebase-apply && git reset --hard && git checkout first && test_tick && git am dirtyfile && git add dirtyfile && test_must_fail git am patch1 && test_path_is_dir .git/rebase-apply && test_cmp_rev first HEAD ' test_expect_success 'am applies patch e-mail not in a mbox' ' rm -fr .git/rebase-apply && git reset --hard && git checkout first && git am patch1.eml && test_path_is_missing .git/rebase-apply && git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' test_expect_success 'am applies patch e-mail not in a mbox with CRLF' ' rm -fr .git/rebase-apply && git reset --hard && git checkout first && git am patch1-crlf.eml && test_path_is_missing .git/rebase-apply && git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' test_expect_success 'am applies patch e-mail with preceding whitespace' ' rm -fr .git/rebase-apply && git reset --hard && git checkout first && git am patch1-ws.eml && test_path_is_missing .git/rebase-apply && git diff --exit-code second && test "$(git rev-parse second)" = "$(git rev-parse HEAD)" && test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)" ' test_expect_success 'am applies stgit patch' ' rm -fr .git/rebase-apply && git checkout -f first && git am patch1-stgit.eml && test_path_is_missing .git/rebase-apply && git diff --exit-code second && test_cmp_rev second HEAD && test_cmp_rev second^ HEAD^ ' test_expect_success 'am --patch-format=stgit applies stgit patch' ' rm -fr .git/rebase-apply && git checkout -f first && git am --patch-format=stgit actual-msg && echo hook-message >"$1" EOF git am patch1 && test_path_is_missing .git/rebase-apply && git diff --exit-code second && echo hook-message >expected && git log -1 --format=format:%B >actual && test_cmp expected actual && git log -1 --format=format:%B second >expected && test_cmp expected actual-msg ' test_expect_success 'am with failing applypatch-msg hook' ' test_when_finished "rm -f .git/hooks/applypatch-msg" && rm -fr .git/rebase-apply && git reset --hard && git checkout first && mkdir -p .git/hooks && write_script .git/hooks/applypatch-msg <<-\EOF && exit 1 EOF test_must_fail git am patch1 && test_path_is_dir .git/rebase-apply && git diff --exit-code first && test_cmp_rev first HEAD ' test_expect_success 'am with pre-applypatch hook' ' test_when_finished "rm -f .git/hooks/pre-applypatch" && rm -fr .git/rebase-apply && git reset --hard && git checkout first && mkdir -p .git/hooks && write_script .git/hooks/pre-applypatch <<-\EOF && git diff first >diff.actual exit 0 EOF git am patch1 && test_path_is_missing .git/rebase-apply && git diff --exit-code second && test_cmp_rev second HEAD && git diff first..second >diff.expected && test_cmp diff.expected diff.actual ' test_expect_success 'am with failing pre-applypatch hook' ' test_when_finished "rm -f .git/hooks/pre-applypatch" && rm -fr .git/rebase-apply && git reset --hard && git checkout first && mkdir -p .git/hooks && write_script .git/hooks/pre-applypatch <<-\EOF && exit 1 EOF test_must_fail git am patch1 && test_path_is_dir .git/rebase-apply && git diff --exit-code second && test_cmp_rev first HEAD ' test_expect_success 'am with post-applypatch hook' ' test_when_finished "rm -f .git/hooks/post-applypatch" && rm -fr .git/rebase-apply && git reset --hard && git checkout first && mkdir -p .git/hooks && write_script .git/hooks/post-applypatch <<-\EOF && git rev-parse HEAD >head.actual git diff second >diff.actual exit 0 EOF git am patch1 && test_path_is_missing .git/rebase-apply && test_cmp_rev second HEAD && git rev-parse second >head.expected && test_cmp head.expected head.actual && git diff second >diff.expected && test_cmp diff.expected diff.actual ' test_expect_success 'am with failing post-applypatch hook' ' test_when_finished "rm -f .git/hooks/post-applypatch" && rm -fr .git/rebase-apply && git reset --hard && git checkout first && mkdir -p .git/hooks && write_script .git/hooks/post-applypatch <<-\EOF && git rev-parse HEAD >head.actual exit 1 EOF git am patch1 && test_path_is_missing .git/rebase-apply && git diff --exit-code second && test_cmp_rev second HEAD && git rev-parse second >head.expected && test_cmp head.expected head.actual ' test_expect_success 'am --scissors cuts the message at the scissors line' ' rm -fr .git/rebase-apply && git reset --hard && git checkout second && git am --scissors scissors-patch.eml && test_path_is_missing .git/rebase-apply && git diff --exit-code scissors && test_cmp_rev scissors HEAD ' test_expect_success 'am --no-scissors overrides mailinfo.scissors' ' rm -fr .git/rebase-apply && git reset --hard && git checkout second && test_config mailinfo.scissors true && git am --no-scissors no-scissors-patch.eml && test_path_is_missing .git/rebase-apply && git diff --exit-code no-scissors && test_cmp_rev no-scissors HEAD ' test_expect_success 'setup: new author and committer' ' GIT_AUTHOR_NAME="Another Thor" && GIT_AUTHOR_EMAIL="a.thor@example.com" && GIT_COMMITTER_NAME="Co M Miter" && GIT_COMMITTER_EMAIL="c.miter@example.com" && export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL ' proc compare { global a := $[git cat-file commit $2 | grep "^$1 ] && global b := $[git cat-file commit $3 | grep "^$1 ] && test $a = $b } test_expect_success 'am changes committer and keeps author' ' test_tick && rm -fr .git/rebase-apply && git reset --hard && git checkout first && git am patch2 && test_path_is_missing .git/rebase-apply && test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" && git diff --exit-code master..HEAD && git diff --exit-code master^..HEAD^ && compare author master HEAD && compare author master^ HEAD^ && test "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \ "$(git log -1 --pretty=format:"%cn <%ce>" HEAD)" ' test_expect_success 'am --signoff adds Signed-off-by: line' ' rm -fr .git/rebase-apply && git reset --hard && git checkout -b master2 first && git am --signoff expected && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >>expected && git cat-file commit HEAD^ | grep "Signed-off-by:" >actual && test_cmp expected actual && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected && git cat-file commit HEAD | grep "Signed-off-by:" >actual && test_cmp expected actual ' test_expect_success 'am stays in branch' ' echo refs/heads/master2 >expected && git symbolic-ref HEAD >actual && test_cmp expected actual ' test_expect_success 'am --signoff does not add Signed-off-by: line if already there' ' git format-patch --stdout HEAD^ >patch3 && sed -e "/^Subject/ s,\[PATCH,Re: Re: Re: & 1/5 v2] [foo," patch3 >patch4 && rm -fr .git/rebase-apply && git reset --hard && git checkout HEAD^ && git am --signoff patch4 && git cat-file commit HEAD >actual && test $(grep -c "^Signed-off-by:" actual) -eq 1 ' test_expect_success 'am without --keep removes Re: and [PATCH] stuff' ' git rev-parse HEAD >expected && git rev-parse master2 >actual && test_cmp expected actual ' test_expect_success 'am --keep really keeps the subject' ' rm -fr .git/rebase-apply && git reset --hard && git checkout HEAD^ && git am --keep patch4 && test_path_is_missing .git/rebase-apply && git cat-file commit HEAD >actual && grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual ' test_expect_success 'am --keep-non-patch really keeps the non-patch part' ' rm -fr .git/rebase-apply && git reset --hard && git checkout HEAD^ && git am --keep-non-patch patch4 && test_path_is_missing .git/rebase-apply && git cat-file commit HEAD >actual && grep "^\[foo\] third" actual ' test_expect_success 'setup am -3' ' rm -fr .git/rebase-apply && git reset --hard && git checkout -b base3way master2 && sed -n -e "3,\$p" msg >file && head -n 9 msg >>file && git add file && test_tick && git commit -m "copied stuff" ' test_expect_success 'am -3 falls back to 3-way merge' ' rm -fr .git/rebase-apply && git reset --hard && git checkout -b lorem2 base3way && git am -3 lorem-move.patch && test_path_is_missing .git/rebase-apply && git diff --exit-code lorem ' test_expect_success 'am -3 -p0 can read --no-prefix patch' ' rm -fr .git/rebase-apply && git reset --hard && git checkout -b lorem3 base3way && git am -3 -p0 lorem-zero.patch && test_path_is_missing .git/rebase-apply && git diff --exit-code lorem ' test_expect_success 'am with config am.threeWay falls back to 3-way merge' ' rm -fr .git/rebase-apply && git reset --hard && git checkout -b lorem4 base3way && test_config am.threeWay 1 && git am lorem-move.patch && test_path_is_missing .git/rebase-apply && git diff --exit-code lorem ' test_expect_success 'am with config am.threeWay overridden by --no-3way' ' rm -fr .git/rebase-apply && git reset --hard && git checkout -b lorem5 base3way && test_config am.threeWay 1 && test_must_fail git am --no-3way lorem-move.patch && test_path_is_dir .git/rebase-apply ' test_expect_success 'am can rename a file' ' grep "^rename from" rename.patch && rm -fr .git/rebase-apply && git reset --hard && git checkout lorem^0 && git am rename.patch && test_path_is_missing .git/rebase-apply && git update-index --refresh && git diff --exit-code rename ' test_expect_success 'am -3 can rename a file' ' grep "^rename from" rename.patch && rm -fr .git/rebase-apply && git reset --hard && git checkout lorem^0 && git am -3 rename.patch && test_path_is_missing .git/rebase-apply && git update-index --refresh && git diff --exit-code rename ' test_expect_success 'am -3 can rename a file after falling back to 3-way merge' ' grep "^rename from" rename-add.patch && rm -fr .git/rebase-apply && git reset --hard && git checkout lorem^0 && git am -3 rename-add.patch && test_path_is_missing .git/rebase-apply && git update-index --refresh && git diff --exit-code rename ' test_expect_success 'am -3 -q is quiet' ' rm -fr .git/rebase-apply && git checkout -f lorem2 && git reset base3way --hard && git am -3 -q lorem-move.patch >output.out 2>&1 && ! test -s output.out ' test_expect_success 'am pauses on conflict' ' rm -fr .git/rebase-apply && git reset --hard && git checkout lorem2^^ && test_must_fail git am lorem-move.patch && test -d .git/rebase-apply ' test_expect_success 'am --skip works' ' echo goodbye >expected && git am --skip && test_path_is_missing .git/rebase-apply && git diff --exit-code lorem2^^ -- file && test_cmp expected another ' test_expect_success 'am --abort removes a stray directory' ' mkdir .git/rebase-apply && git am --abort && test_path_is_missing .git/rebase-apply ' test_expect_success 'am refuses patches when paused' ' rm -fr .git/rebase-apply && git reset --hard && git checkout lorem2^^ && test_must_fail git am lorem-move.patch && test_path_is_dir .git/rebase-apply && test_cmp_rev lorem2^^ HEAD && test_must_fail git am expected && rm -fr .git/rebase-apply && git reset --hard && git checkout lorem2^^ && test_must_fail git am lorem-move.patch && test -d .git/rebase-apply && echo resolved >>file && git add file && git am --resolved && test_path_is_missing .git/rebase-apply && test_cmp expected another ' test_expect_success 'am --resolved fails if index has no changes' ' rm -fr .git/rebase-apply && git reset --hard && git checkout lorem2^^ && test_must_fail git am lorem-move.patch && test_path_is_dir .git/rebase-apply && test_cmp_rev lorem2^^ HEAD && test_must_fail git am --resolved && test_path_is_dir .git/rebase-apply && test_cmp_rev lorem2^^ HEAD ' test_expect_success 'am --resolved fails if index has unmerged entries' ' rm -fr .git/rebase-apply && git reset --hard && git checkout second && test_must_fail git am -3 lorem-move.patch && test_path_is_dir .git/rebase-apply && test_cmp_rev second HEAD && test_must_fail git am --resolved >err && test_path_is_dir .git/rebase-apply && test_cmp_rev second HEAD && test_i18ngrep "still have unmerged paths" err ' test_expect_success 'am takes patches from a Pine mailbox' ' rm -fr .git/rebase-apply && git reset --hard && git checkout first && cat pine patch1 | git am && test_path_is_missing .git/rebase-apply && git diff --exit-code master^..HEAD ' test_expect_success 'am fails on mail without patch' ' rm -fr .git/rebase-apply && git reset --hard && test_must_fail git am >failmail && test_must_fail git am head1 && sed -ne "/^author /s/.*> //p" head1 >at && sed -ne "/^committer /s/.*> //p" head1 >ct && test_cmp at ct ' test_expect_success 'am without --committer-date-is-author-date' ' rm -fr .git/rebase-apply && git reset --hard && git checkout first && test_tick && git am patch1 && git cat-file commit HEAD | sed -e "/^\$/q" >head1 && sed -ne "/^author /s/.*> //p" head1 >at && sed -ne "/^committer /s/.*> //p" head1 >ct && ! test_cmp at ct ' # This checks for +0000 because TZ is set to UTC and that should # show up when the current time is used. The date in message is set # by test_tick that uses -0700 timezone; if this feature does not # work, we will see that instead of +0000. test_expect_success 'am --ignore-date' ' rm -fr .git/rebase-apply && git reset --hard && git checkout first && test_tick && git am --ignore-date patch1 && git cat-file commit HEAD | sed -e "/^\$/q" >head1 && sed -ne "/^author /s/.*> //p" head1 >at && grep "+0000" at ' test_expect_success 'am into an unborn branch' ' git rev-parse first^{tree} >expected && rm -fr .git/rebase-apply && git reset --hard && rm -fr subdir && mkdir subdir && git format-patch --numbered-files -o subdir -1 first && ( cd subdir && git init && git am 1 ) && ( cd subdir && git rev-parse HEAD^{tree} >../actual ) && test_cmp expected actual ' test_expect_success 'am newline in subject' ' rm -fr .git/rebase-apply && git reset --hard && git checkout first && test_tick && sed -e "s/second/second \\\n foo/" patch1 >patchnl && git am output.out 2>&1 && test_i18ngrep "^Applying: second \\\n foo$" output.out ' test_expect_success 'am -q is quiet' ' rm -fr .git/rebase-apply && git reset --hard && git checkout first && test_tick && git am -q output.out 2>&1 && ! test -s output.out ' test_expect_success 'am empty-file does not infloop' ' rm -fr .git/rebase-apply && git reset --hard && touch empty-file && test_tick && test_must_fail git am empty-file 2>actual && echo Patch format detection failed. >expected && test_i18ncmp expected actual ' test_expect_success 'am --message-id really adds the message id' ' rm -fr .git/rebase-apply && git reset --hard && git checkout HEAD^ && git am --message-id patch1.eml && test_path_is_missing .git/rebase-apply && git cat-file commit HEAD | tail -n1 >actual && grep Message-Id patch1.eml >expected && test_cmp expected actual ' test_expect_success 'am.messageid really adds the message id' ' rm -fr .git/rebase-apply && git reset --hard && git checkout HEAD^ && test_config am.messageid true && git am patch1.eml && test_path_is_missing .git/rebase-apply && git cat-file commit HEAD | tail -n1 >actual && grep Message-Id patch1.eml >expected && test_cmp expected actual ' test_expect_success 'am --message-id -s signs off after the message id' ' rm -fr .git/rebase-apply && git reset --hard && git checkout HEAD^ && git am -s --message-id patch1.eml && test_path_is_missing .git/rebase-apply && git cat-file commit HEAD | tail -n2 | head -n1 >actual && grep Message-Id patch1.eml >expected && test_cmp expected actual ' test_expect_success 'am -3 works with rerere' ' rm -fr .git/rebase-apply && git reset --hard && # make patches one->two and two->three... test_commit one file && test_commit two file && test_commit three file && git format-patch -2 --stdout >seq.patch && # and create a situation that conflicts... git reset --hard one && test_commit other file && # enable rerere... test_config rerere.enabled true && test_when_finished "rm -rf .git/rr-cache" && # ...and apply. Our resolution is to skip the first # patch, and the rerere the second one. test_must_fail git am -3 seq.patch && test_must_fail git am --skip && echo resolved >file && git add file && git am --resolved && # now apply again, and confirm that rerere engaged (we still # expect failure from am because rerere does not auto-commit # for us). git reset --hard other && test_must_fail git am -3 seq.patch && test_must_fail git am --skip && echo resolved >expect && test_cmp expect file ' test_expect_success 'am -s unexpected trailer block' ' rm -fr .git/rebase-apply && git reset --hard && echo signed >file && git add file && cat >msg <<-EOF && subject here Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> [jc: tweaked log message] Signed-off-by: J C H EOF git commit -F msg && git cat-file commit HEAD | sed -e '1,/^$/d' >original && git format-patch --stdout -1 >patch && git reset --hard HEAD^ && git am -s patch && ( cat original && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" ) >expect && git cat-file commit HEAD | sed -e '1,/^$/d' >actual && test_cmp expect actual && cat >msg <<-\EOF && subject here We make sure that there is a blank line between the log message proper and Signed-off-by: line added. EOF git reset HEAD^ && git commit -F msg file && git cat-file commit HEAD | sed -e '1,/^$/d' >original && git format-patch --stdout -1 >patch && git reset --hard HEAD^ && git am -s patch && ( cat original && echo && echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" ) >expect && git cat-file commit HEAD | sed -e '1,/^$/d' >actual && test_cmp expect actual ' test_expect_success 'am --patch-format=mboxrd handles mboxrd' ' rm -fr .git/rebase-apply && git checkout -f first && echo mboxrd >>file && git add file && cat >msg <<-\INPUT_END && mboxrd should escape the body From could trip up a loose mbox parser >From extra escape for reversibility INPUT_END git commit -F msg && git format-patch --pretty=mboxrd --stdout -1 >mboxrd1 && grep "^>From could trip up a loose mbox parser" mboxrd1 && git checkout -f first && git am --patch-format=mboxrd mboxrd1 && git cat-file commit HEAD | tail -n4 >out && test_cmp msg out ' test_expect_success 'am works with multi-line in-body headers' ' FORTY="String that has a length of more than forty characters" && LONG="$FORTY $FORTY" && rm -fr .git/rebase-apply && git checkout -f first && echo one >> file && git commit -am "$LONG" --author="$LONG " && git format-patch --stdout -1 >patch && # bump from, date, and subject down to in-body header perl -lpe " if (/^From:/) { print \"From: x \"; print \"Date: Sat, 1 Jan 2000 00:00:00 +0000\"; print \"Subject: x\n\"; } " patch >msg && git checkout HEAD^ && git am msg && # Ensure that the author and full message are present git cat-file commit HEAD | grep "^author.*long@example.com" && git cat-file commit HEAD | grep "^$LONG" ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"git am running">)} spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (C {(test_expect_success)} {(SQ <"setup: messages">)} { (SQ <"\n"> <"\tcat >msg <<-\\EOF &&\n"> <"\tsecond\n"> <"\n"> <"\tLorem ipsum dolor sit amet, consectetuer sadipscing elitr, sed diam nonumy\n"> <"\teirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n"> <"\tvoluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita\n"> <"\tkasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem\n"> <"\tipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod\n"> <"\ttempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At\n"> <"\tvero eos et accusam et justo duo dolores et ea rebum.\n"> <"\n"> <"\tEOF\n"> <"\tqz_to_tab_space <<-\\EOF >>msg &&\n"> <"\tQDuis autem vel eum iriure dolor in hendrerit in vulputate velit\n"> <"\tQesse molestie consequat, vel illum dolore eu feugiat nulla facilisis\n"> <"\tQat vero eros et accumsan et iusto odio dignissim qui blandit\n"> <"\tQpraesent luptatum zzril delenit augue duis dolore te feugait nulla\n"> <"\tQfacilisi.\n"> <"\tEOF\n"> <"\tcat >>msg <<-\\EOF &&\n"> <"\n"> <"\tLorem ipsum dolor sit amet,\n"> <"\tconsectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut\n"> <"\tlaoreet dolore magna aliquam erat volutpat.\n"> <"\n"> <"\t git\n"> <"\t ---\n"> <"\t +++\n"> <"\n"> <"\tUt wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit\n"> <"\tlobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure\n"> <"\tdolor in hendrerit in vulputate velit esse molestie consequat, vel illum\n"> <"\tdolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio\n"> <"\tdignissim qui blandit praesent luptatum zzril delenit augue duis dolore te\n"> <"\tfeugait nulla facilisi.\n"> <"\tEOF\n"> <"\n"> <"\tcat >failmail <<-\\EOF &&\n"> <"\tFrom foo@example.com Fri May 23 10:43:49 2008\n"> <"\tFrom:\tfoo@example.com\n"> <"\tTo:\tbar@example.com\n"> <"\tSubject: Re: [RFC/PATCH] git-foo.sh\n"> <"\tDate:\tFri, 23 May 2008 05:23:42 +0200\n"> <"\n"> <"\tSometimes we have to find out that there"> ) (EscapedLiteralPart token:) (SQ <"s nothing left.\n"> <"\n"> <"\tEOF\n"> <"\n"> <"\tcat >pine <<-\\EOF &&\n"> <"\tFrom MAILER-DAEMON Fri May 23 10:43:49 2008\n"> <"\tDate: 23 May 2008 05:23:42 +0200\n"> <"\tFrom: Mail System Internal Data \n"> <"\tSubject: DON"> ) (EscapedLiteralPart token:) (SQ <"T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA\n"> <"\tMessage-ID: \n"> <"\n"> <"\tThis text is part of the internal format of your mail folder, and is not\n"> <"\ta real message. It is created automatically by the mail system software.\n"> <"\tIf deleted, important folder data will be lost, and it will be re-created\n"> <"\twith the data reset to initial values.\n"> <"\n"> <"\tEOF\n"> <"\n"> <"\tcat >scissors-msg <<-\\EOF &&\n"> <"\tTest git-am with scissors line\n"> <"\n"> <"\tThis line should be included in the commit message.\n"> <"\tEOF\n"> <"\n"> <"\tcat - scissors-msg >no-scissors-msg <<-\\EOF &&\n"> <"\tThis line should not be included in the commit message with --scissors enabled.\n"> <"\n"> <"\t - - >8 - - remove everything above this line - - >8 - -\n"> <"\n"> <"\tEOF\n"> <"\n"> <"\tsignoff=\"Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\"\n"> ) } ) (C {(test_expect_success)} {(setup)} { (SQ <"\n"> <"\techo hello >file &&\n"> <"\tgit add file &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m first &&\n"> <"\tgit tag first &&\n"> <"\n"> <"\techo world >>file &&\n"> <"\tgit add file &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -s -F msg &&\n"> <"\tgit tag second &&\n"> <"\n"> <"\tgit format-patch --stdout first >patch1 &&\n"> <"\t{\n"> <"\t\techo \"Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>\" &&\n"> <"\t\techo \"X-Fake-Field: Line One\" &&\n"> <"\t\techo \"X-Fake-Field: Line Two\" &&\n"> <"\t\techo \"X-Fake-Field: Line Three\" &&\n"> <"\t\tgit format-patch --stdout first | sed -e \"1d\"\n"> <"\t} > patch1.eml &&\n"> <"\t{\n"> <"\t\techo \"X-Fake-Field: Line One\" &&\n"> <"\t\techo \"X-Fake-Field: Line Two\" &&\n"> <"\t\techo \"X-Fake-Field: Line Three\" &&\n"> <"\t\tgit format-patch --stdout first | sed -e \"1d\"\n"> <"\t} | append_cr >patch1-crlf.eml &&\n"> <"\t{\n"> <"\t\tprintf \"%255s\\\\n\" \"\"\n"> <"\t\techo \"X-Fake-Field: Line One\" &&\n"> <"\t\techo \"X-Fake-Field: Line Two\" &&\n"> <"\t\techo \"X-Fake-Field: Line Three\" &&\n"> <"\t\tgit format-patch --stdout first | sed -e \"1d\"\n"> <"\t} > patch1-ws.eml &&\n"> <"\t{\n"> <"\t\tsed -ne \"1p\" msg &&\n"> <"\t\techo &&\n"> <"\t\techo \"From: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\" &&\n"> <"\t\techo \"Date: $GIT_AUTHOR_DATE\" &&\n"> <"\t\techo &&\n"> <"\t\tsed -e \"1,2d\" msg &&\n"> <"\t\techo &&\n"> <"\t\techo \"Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\" &&\n"> <"\t\techo \"---\" &&\n"> <"\t\tgit diff-tree --no-commit-id --stat -p second\n"> <"\t} >patch1-stgit.eml &&\n"> <"\tmkdir stgit-series &&\n"> <"\tcp patch1-stgit.eml stgit-series/patch &&\n"> <"\t{\n"> <"\t\techo \"# This series applies on GIT commit $(git rev-parse first)\" &&\n"> <"\t\techo \"patch\"\n"> <"\t} >stgit-series/series &&\n"> <"\t{\n"> <"\t\techo \"# HG changeset patch\" &&\n"> <"\t\techo \"# User $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\" &&\n"> <"\t\techo \"# Date $test_tick 25200\" &&\n"> <"\t\techo \"# $(git show --pretty=\"%aD\" -s second)\" &&\n"> <"\t\techo \"# Node ID $_z40\" &&\n"> <"\t\techo \"# Parent $_z40\" &&\n"> <"\t\tcat msg &&\n"> <"\t\techo &&\n"> <"\t\techo \"Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\" &&\n"> <"\t\techo &&\n"> <"\t\tgit diff-tree --no-commit-id -p second\n"> <"\t} >patch1-hg.eml &&\n"> <"\n"> <"\n"> <"\techo scissors-file >scissors-file &&\n"> <"\tgit add scissors-file &&\n"> <"\tgit commit -F scissors-msg &&\n"> <"\tgit tag scissors &&\n"> <"\tgit format-patch --stdout scissors^ >scissors-patch.eml &&\n"> <"\tgit reset --hard HEAD^ &&\n"> <"\n"> <"\techo no-scissors-file >no-scissors-file &&\n"> <"\tgit add no-scissors-file &&\n"> <"\tgit commit -F no-scissors-msg &&\n"> <"\tgit tag no-scissors &&\n"> <"\tgit format-patch --stdout no-scissors^ >no-scissors-patch.eml &&\n"> <"\tgit reset --hard HEAD^ &&\n"> <"\n"> <"\tsed -n -e \"3,\\$p\" msg >file &&\n"> <"\tgit add file &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m third &&\n"> <"\n"> <"\tgit format-patch --stdout first >patch2\t&&\n"> <"\n"> <"\tgit checkout -b lorem &&\n"> <"\tsed -n -e \"11,\\$p\" msg >file &&\n"> <"\thead -n 9 msg >>file &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -a -m \"moved stuff\" &&\n"> <"\n"> <"\techo goodbye >another &&\n"> <"\tgit add another &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"added another file\" &&\n"> <"\n"> <"\tgit format-patch --stdout master >lorem-move.patch &&\n"> <"\tgit format-patch --no-prefix --stdout master >lorem-zero.patch &&\n"> <"\n"> <"\tgit checkout -b rename &&\n"> <"\tgit mv file renamed &&\n"> <"\tgit commit -m \"renamed a file\" &&\n"> <"\n"> <"\tgit format-patch -M --stdout lorem >rename.patch &&\n"> <"\n"> <"\tgit reset --soft lorem^ &&\n"> <"\tgit commit -m \"renamed a file and added another\" &&\n"> <"\n"> <"\tgit format-patch -M --stdout lorem^ >rename-add.patch &&\n"> <"\n"> <"\t# reset time\n"> <"\tsane_unset test_tick &&\n"> <"\ttest_tick\n"> ) } ) (C {(test_expect_success)} {(SQ <"am applies patch correctly">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\ttest_tick &&\n"> <"\tgit am <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest \"$(git rev-parse second)\" = \"$(git rev-parse HEAD)\" &&\n"> <"\ttest \"$(git rev-parse second^)\" = \"$(git rev-parse HEAD^)\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"am fails if index is dirty">)} { (SQ <"\n"> <"\ttest_when_finished \"rm -f dirtyfile\" &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\techo dirtyfile >dirtyfile &&\n"> <"\tgit add dirtyfile &&\n"> <"\ttest_must_fail git am patch1 &&\n"> <"\ttest_path_is_dir .git/rebase-apply &&\n"> <"\ttest_cmp_rev first HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"am applies patch e-mail not in a mbox">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tgit am patch1.eml &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest \"$(git rev-parse second)\" = \"$(git rev-parse HEAD)\" &&\n"> <"\ttest \"$(git rev-parse second^)\" = \"$(git rev-parse HEAD^)\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"am applies patch e-mail not in a mbox with CRLF">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tgit am patch1-crlf.eml &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest \"$(git rev-parse second)\" = \"$(git rev-parse HEAD)\" &&\n"> <"\ttest \"$(git rev-parse second^)\" = \"$(git rev-parse HEAD^)\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"am applies patch e-mail with preceding whitespace">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tgit am patch1-ws.eml &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest \"$(git rev-parse second)\" = \"$(git rev-parse HEAD)\" &&\n"> <"\ttest \"$(git rev-parse second^)\" = \"$(git rev-parse HEAD^)\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"am applies stgit patch">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit checkout -f first &&\n"> <"\tgit am patch1-stgit.eml &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest_cmp_rev second HEAD &&\n"> <"\ttest_cmp_rev second^ HEAD^\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --patch-format=stgit applies stgit patch">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit checkout -f first &&\n"> <"\tgit am --patch-format=stgit <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest_cmp_rev second HEAD &&\n"> <"\ttest_cmp_rev second^ HEAD^\n"> ) } ) (C {(test_expect_success)} {(SQ <"am applies stgit series">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit checkout -f first &&\n"> <"\tgit am stgit-series/series &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest_cmp_rev second HEAD &&\n"> <"\ttest_cmp_rev second^ HEAD^\n"> ) } ) (C {(test_expect_success)} {(SQ <"am applies hg patch">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit checkout -f first &&\n"> <"\tgit am patch1-hg.eml &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest_cmp_rev second HEAD &&\n"> <"\ttest_cmp_rev second^ HEAD^\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --patch-format=hg applies hg patch">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit checkout -f first &&\n"> <"\tgit am --patch-format=hg <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest_cmp_rev second HEAD &&\n"> <"\ttest_cmp_rev second^ HEAD^\n"> ) } ) (C {(test_expect_success)} {(SQ <"am with applypatch-msg hook">)} { (SQ <"\n"> <"\ttest_when_finished \"rm -f .git/hooks/applypatch-msg\" &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tmkdir -p .git/hooks &&\n"> <"\twrite_script .git/hooks/applypatch-msg <<-\\EOF &&\n"> <"\tcat \"$1\" >actual-msg &&\n"> <"\techo hook-message >\"$1\"\n"> <"\tEOF\n"> <"\tgit am patch1 &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\techo hook-message >expected &&\n"> <"\tgit log -1 --format=format:%B >actual &&\n"> <"\ttest_cmp expected actual &&\n"> <"\tgit log -1 --format=format:%B second >expected &&\n"> <"\ttest_cmp expected actual-msg\n"> ) } ) (C {(test_expect_success)} {(SQ <"am with failing applypatch-msg hook">)} { (SQ <"\n"> <"\ttest_when_finished \"rm -f .git/hooks/applypatch-msg\" &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tmkdir -p .git/hooks &&\n"> <"\twrite_script .git/hooks/applypatch-msg <<-\\EOF &&\n"> <"\texit 1\n"> <"\tEOF\n"> <"\ttest_must_fail git am patch1 &&\n"> <"\ttest_path_is_dir .git/rebase-apply &&\n"> <"\tgit diff --exit-code first &&\n"> <"\ttest_cmp_rev first HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"am with pre-applypatch hook">)} { (SQ <"\n"> <"\ttest_when_finished \"rm -f .git/hooks/pre-applypatch\" &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tmkdir -p .git/hooks &&\n"> <"\twrite_script .git/hooks/pre-applypatch <<-\\EOF &&\n"> <"\tgit diff first >diff.actual\n"> <"\texit 0\n"> <"\tEOF\n"> <"\tgit am patch1 &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest_cmp_rev second HEAD &&\n"> <"\tgit diff first..second >diff.expected &&\n"> <"\ttest_cmp diff.expected diff.actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am with failing pre-applypatch hook">)} { (SQ <"\n"> <"\ttest_when_finished \"rm -f .git/hooks/pre-applypatch\" &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tmkdir -p .git/hooks &&\n"> <"\twrite_script .git/hooks/pre-applypatch <<-\\EOF &&\n"> <"\texit 1\n"> <"\tEOF\n"> <"\ttest_must_fail git am patch1 &&\n"> <"\ttest_path_is_dir .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest_cmp_rev first HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"am with post-applypatch hook">)} { (SQ <"\n"> <"\ttest_when_finished \"rm -f .git/hooks/post-applypatch\" &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tmkdir -p .git/hooks &&\n"> <"\twrite_script .git/hooks/post-applypatch <<-\\EOF &&\n"> <"\tgit rev-parse HEAD >head.actual\n"> <"\tgit diff second >diff.actual\n"> <"\texit 0\n"> <"\tEOF\n"> <"\tgit am patch1 &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\ttest_cmp_rev second HEAD &&\n"> <"\tgit rev-parse second >head.expected &&\n"> <"\ttest_cmp head.expected head.actual &&\n"> <"\tgit diff second >diff.expected &&\n"> <"\ttest_cmp diff.expected diff.actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am with failing post-applypatch hook">)} { (SQ <"\n"> <"\ttest_when_finished \"rm -f .git/hooks/post-applypatch\" &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tmkdir -p .git/hooks &&\n"> <"\twrite_script .git/hooks/post-applypatch <<-\\EOF &&\n"> <"\tgit rev-parse HEAD >head.actual\n"> <"\texit 1\n"> <"\tEOF\n"> <"\tgit am patch1 &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code second &&\n"> <"\ttest_cmp_rev second HEAD &&\n"> <"\tgit rev-parse second >head.expected &&\n"> <"\ttest_cmp head.expected head.actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --scissors cuts the message at the scissors line">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout second &&\n"> <"\tgit am --scissors scissors-patch.eml &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code scissors &&\n"> <"\ttest_cmp_rev scissors HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --no-scissors overrides mailinfo.scissors">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout second &&\n"> <"\ttest_config mailinfo.scissors true &&\n"> <"\tgit am --no-scissors no-scissors-patch.eml &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code no-scissors &&\n"> <"\ttest_cmp_rev no-scissors HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup: new author and committer">)} { (SQ <"\n"> <"\tGIT_AUTHOR_NAME=\"Another Thor\" &&\n"> <"\tGIT_AUTHOR_EMAIL=\"a.thor@example.com\" &&\n"> <"\tGIT_COMMITTER_NAME=\"Co M Miter\" &&\n"> <"\tGIT_COMMITTER_EMAIL=\"c.miter@example.com\" &&\n"> <"\texport GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL\n"> ) } ) (FuncDef name: compare body: (BraceGroup children: [ (AndOr children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:a) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(git)} {(cat-file)} {(commit)} {(DQ ($ VSub_Number "$2"))}) (C {(grep)} {(DQ ("^") ($ VSub_Number "$1") (" "))}) ] negated: False ) ] ) left_token: spids: [637 657] ) } spids: [636] ) ] spids: [636] ) (AndOr children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:b) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(git)} {(cat-file)} {(commit)} {(DQ ($ VSub_Number "$3"))}) (C {(grep)} {(DQ ("^") ($ VSub_Number "$1") (" "))}) ] negated: False ) ] ) left_token: spids: [663 683] ) } spids: [662] ) ] spids: [662] ) (C {(test)} {(DQ ($ VSub_Name "$a"))} {(Lit_Other "=")} {(DQ ($ VSub_Name "$b"))}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [633] ) spids: [628 632] ) (C {(test_expect_success)} {(SQ <"am changes committer and keeps author">)} { (SQ <"\n"> <"\ttest_tick &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tgit am patch2 &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\ttest \"$(git rev-parse master^^)\" = \"$(git rev-parse HEAD^^)\" &&\n"> <"\tgit diff --exit-code master..HEAD &&\n"> <"\tgit diff --exit-code master^..HEAD^ &&\n"> <"\tcompare author master HEAD &&\n"> <"\tcompare author master^ HEAD^ &&\n"> <"\ttest \"$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\" = \\\n"> <"\t \"$(git log -1 --pretty=format:\"%cn <%ce>\" HEAD)\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --signoff adds Signed-off-by: line">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout -b master2 first &&\n"> <"\tgit am --signoff <"\tprintf \"%s\\n\" \"$signoff\" >expected &&\n"> <"\techo \"Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\" >>expected &&\n"> <"\tgit cat-file commit HEAD^ | grep \"Signed-off-by:\" >actual &&\n"> <"\ttest_cmp expected actual &&\n"> <"\techo \"Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\" >expected &&\n"> <"\tgit cat-file commit HEAD | grep \"Signed-off-by:\" >actual &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am stays in branch">)} { (SQ <"\n"> <"\techo refs/heads/master2 >expected &&\n"> <"\tgit symbolic-ref HEAD >actual &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --signoff does not add Signed-off-by: line if already there">)} { (SQ <"\n"> <"\tgit format-patch --stdout HEAD^ >patch3 &&\n"> <"\tsed -e \"/^Subject/ s,\\[PATCH,Re: Re: Re: & 1/5 v2] [foo,\" patch3 >patch4 &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout HEAD^ &&\n"> <"\tgit am --signoff patch4 &&\n"> <"\tgit cat-file commit HEAD >actual &&\n"> <"\ttest $(grep -c \"^Signed-off-by:\" actual) -eq 1\n"> ) } ) (C {(test_expect_success)} {(SQ <"am without --keep removes Re: and [PATCH] stuff">)} { (SQ <"\n"> <"\tgit rev-parse HEAD >expected &&\n"> <"\tgit rev-parse master2 >actual &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --keep really keeps the subject">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout HEAD^ &&\n"> <"\tgit am --keep patch4 &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit cat-file commit HEAD >actual &&\n"> <"\tgrep \"Re: Re: Re: \\[PATCH 1/5 v2\\] \\[foo\\] third\" actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --keep-non-patch really keeps the non-patch part">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout HEAD^ &&\n"> <"\tgit am --keep-non-patch patch4 &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit cat-file commit HEAD >actual &&\n"> <"\tgrep \"^\\[foo\\] third\" actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup am -3">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout -b base3way master2 &&\n"> <"\tsed -n -e \"3,\\$p\" msg >file &&\n"> <"\thead -n 9 msg >>file &&\n"> <"\tgit add file &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"copied stuff\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"am -3 falls back to 3-way merge">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout -b lorem2 base3way &&\n"> <"\tgit am -3 lorem-move.patch &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code lorem\n"> ) } ) (C {(test_expect_success)} {(SQ <"am -3 -p0 can read --no-prefix patch">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout -b lorem3 base3way &&\n"> <"\tgit am -3 -p0 lorem-zero.patch &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code lorem\n"> ) } ) (C {(test_expect_success)} {(SQ <"am with config am.threeWay falls back to 3-way merge">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout -b lorem4 base3way &&\n"> <"\ttest_config am.threeWay 1 &&\n"> <"\tgit am lorem-move.patch &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code lorem\n"> ) } ) (C {(test_expect_success)} {(SQ <"am with config am.threeWay overridden by --no-3way">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout -b lorem5 base3way &&\n"> <"\ttest_config am.threeWay 1 &&\n"> <"\ttest_must_fail git am --no-3way lorem-move.patch &&\n"> <"\ttest_path_is_dir .git/rebase-apply\n"> ) } ) (C {(test_expect_success)} {(SQ <"am can rename a file">)} { (SQ <"\n"> <"\tgrep \"^rename from\" rename.patch &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout lorem^0 &&\n"> <"\tgit am rename.patch &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit update-index --refresh &&\n"> <"\tgit diff --exit-code rename\n"> ) } ) (C {(test_expect_success)} {(SQ <"am -3 can rename a file">)} { (SQ <"\n"> <"\tgrep \"^rename from\" rename.patch &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout lorem^0 &&\n"> <"\tgit am -3 rename.patch &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit update-index --refresh &&\n"> <"\tgit diff --exit-code rename\n"> ) } ) (C {(test_expect_success)} {(SQ <"am -3 can rename a file after falling back to 3-way merge">)} { (SQ <"\n"> <"\tgrep \"^rename from\" rename-add.patch &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout lorem^0 &&\n"> <"\tgit am -3 rename-add.patch &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit update-index --refresh &&\n"> <"\tgit diff --exit-code rename\n"> ) } ) (C {(test_expect_success)} {(SQ <"am -3 -q is quiet">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit checkout -f lorem2 &&\n"> <"\tgit reset base3way --hard &&\n"> <"\tgit am -3 -q lorem-move.patch >output.out 2>&1 &&\n"> <"\t! test -s output.out\n"> ) } ) (C {(test_expect_success)} {(SQ <"am pauses on conflict">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout lorem2^^ &&\n"> <"\ttest_must_fail git am lorem-move.patch &&\n"> <"\ttest -d .git/rebase-apply\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --skip works">)} { (SQ <"\n"> <"\techo goodbye >expected &&\n"> <"\tgit am --skip &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code lorem2^^ -- file &&\n"> <"\ttest_cmp expected another\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --abort removes a stray directory">)} { (SQ <"\n"> <"\tmkdir .git/rebase-apply &&\n"> <"\tgit am --abort &&\n"> <"\ttest_path_is_missing .git/rebase-apply\n"> ) } ) (C {(test_expect_success)} {(SQ <"am refuses patches when paused">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout lorem2^^ &&\n"> <"\n"> <"\ttest_must_fail git am lorem-move.patch &&\n"> <"\ttest_path_is_dir .git/rebase-apply &&\n"> <"\ttest_cmp_rev lorem2^^ HEAD &&\n"> <"\n"> <"\ttest_must_fail git am <"\ttest_path_is_dir .git/rebase-apply &&\n"> <"\ttest_cmp_rev lorem2^^ HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --resolved works">)} { (SQ <"\n"> <"\techo goodbye >expected &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout lorem2^^ &&\n"> <"\ttest_must_fail git am lorem-move.patch &&\n"> <"\ttest -d .git/rebase-apply &&\n"> <"\techo resolved >>file &&\n"> <"\tgit add file &&\n"> <"\tgit am --resolved &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\ttest_cmp expected another\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --resolved fails if index has no changes">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout lorem2^^ &&\n"> <"\ttest_must_fail git am lorem-move.patch &&\n"> <"\ttest_path_is_dir .git/rebase-apply &&\n"> <"\ttest_cmp_rev lorem2^^ HEAD &&\n"> <"\ttest_must_fail git am --resolved &&\n"> <"\ttest_path_is_dir .git/rebase-apply &&\n"> <"\ttest_cmp_rev lorem2^^ HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --resolved fails if index has unmerged entries">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout second &&\n"> <"\ttest_must_fail git am -3 lorem-move.patch &&\n"> <"\ttest_path_is_dir .git/rebase-apply &&\n"> <"\ttest_cmp_rev second HEAD &&\n"> <"\ttest_must_fail git am --resolved >err &&\n"> <"\ttest_path_is_dir .git/rebase-apply &&\n"> <"\ttest_cmp_rev second HEAD &&\n"> <"\ttest_i18ngrep \"still have unmerged paths\" err\n"> ) } ) (C {(test_expect_success)} {(SQ <"am takes patches from a Pine mailbox">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tcat pine patch1 | git am &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit diff --exit-code master^..HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"am fails on mail without patch">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\ttest_must_fail git am <"\tgit am --abort &&\n"> <"\ttest_path_is_missing .git/rebase-apply\n"> ) } ) (C {(test_expect_success)} {(SQ <"am fails on empty patch">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\techo \"---\" >>failmail &&\n"> <"\ttest_must_fail git am <"\tgit am --skip &&\n"> <"\ttest_path_is_missing .git/rebase-apply\n"> ) } ) (C {(test_expect_success)} {(SQ <"am works from stdin in subdirectory">)} { (SQ <"\n"> <"\trm -fr subdir &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\t(\n"> <"\t\tmkdir -p subdir &&\n"> <"\t\tcd subdir &&\n"> <"\t\tgit am <../patch1\n"> <"\t) &&\n"> <"\tgit diff --exit-code second\n"> ) } ) (C {(test_expect_success)} {(SQ <"am works from file (relative path given) in subdirectory">)} { (SQ <"\n"> <"\trm -fr subdir &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\t(\n"> <"\t\tmkdir -p subdir &&\n"> <"\t\tcd subdir &&\n"> <"\t\tgit am ../patch1\n"> <"\t) &&\n"> <"\tgit diff --exit-code second\n"> ) } ) (C {(test_expect_success)} {(SQ <"am works from file (absolute path given) in subdirectory">)} { (SQ <"\n"> <"\trm -fr subdir &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\tP=$(pwd) &&\n"> <"\t(\n"> <"\t\tmkdir -p subdir &&\n"> <"\t\tcd subdir &&\n"> <"\t\tgit am \"$P/patch1\"\n"> <"\t) &&\n"> <"\tgit diff --exit-code second\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --committer-date-is-author-date">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\ttest_tick &&\n"> <"\tgit am --committer-date-is-author-date patch1 &&\n"> <"\tgit cat-file commit HEAD | sed -e \"/^\\$/q\" >head1 &&\n"> <"\tsed -ne \"/^author /s/.*> //p\" head1 >at &&\n"> <"\tsed -ne \"/^committer /s/.*> //p\" head1 >ct &&\n"> <"\ttest_cmp at ct\n"> ) } ) (C {(test_expect_success)} {(SQ <"am without --committer-date-is-author-date">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\ttest_tick &&\n"> <"\tgit am patch1 &&\n"> <"\tgit cat-file commit HEAD | sed -e \"/^\\$/q\" >head1 &&\n"> <"\tsed -ne \"/^author /s/.*> //p\" head1 >at &&\n"> <"\tsed -ne \"/^committer /s/.*> //p\" head1 >ct &&\n"> <"\t! test_cmp at ct\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --ignore-date">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\ttest_tick &&\n"> <"\tgit am --ignore-date patch1 &&\n"> <"\tgit cat-file commit HEAD | sed -e \"/^\\$/q\" >head1 &&\n"> <"\tsed -ne \"/^author /s/.*> //p\" head1 >at &&\n"> <"\tgrep \"+0000\" at\n"> ) } ) (C {(test_expect_success)} {(SQ <"am into an unborn branch">)} { (SQ <"\n"> <"\tgit rev-parse first^{tree} >expected &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\trm -fr subdir &&\n"> <"\tmkdir subdir &&\n"> <"\tgit format-patch --numbered-files -o subdir -1 first &&\n"> <"\t(\n"> <"\t\tcd subdir &&\n"> <"\t\tgit init &&\n"> <"\t\tgit am 1\n"> <"\t) &&\n"> <"\t(\n"> <"\t\tcd subdir &&\n"> <"\t\tgit rev-parse HEAD^{tree} >../actual\n"> <"\t) &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am newline in subject">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\ttest_tick &&\n"> <"\tsed -e \"s/second/second \\\\\\n foo/\" patch1 >patchnl &&\n"> <"\tgit am output.out 2>&1 &&\n"> <"\ttest_i18ngrep \"^Applying: second \\\\\\n foo$\" output.out\n"> ) } ) (C {(test_expect_success)} {(SQ <"am -q is quiet">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout first &&\n"> <"\ttest_tick &&\n"> <"\tgit am -q output.out 2>&1 &&\n"> <"\t! test -s output.out\n"> ) } ) (C {(test_expect_success)} {(SQ <"am empty-file does not infloop">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\ttouch empty-file &&\n"> <"\ttest_tick &&\n"> <"\ttest_must_fail git am empty-file 2>actual &&\n"> <"\techo Patch format detection failed. >expected &&\n"> <"\ttest_i18ncmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --message-id really adds the message id">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout HEAD^ &&\n"> <"\tgit am --message-id patch1.eml &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit cat-file commit HEAD | tail -n1 >actual &&\n"> <"\tgrep Message-Id patch1.eml >expected &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am.messageid really adds the message id">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout HEAD^ &&\n"> <"\ttest_config am.messageid true &&\n"> <"\tgit am patch1.eml &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit cat-file commit HEAD | tail -n1 >actual &&\n"> <"\tgrep Message-Id patch1.eml >expected &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am --message-id -s signs off after the message id">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout HEAD^ &&\n"> <"\tgit am -s --message-id patch1.eml &&\n"> <"\ttest_path_is_missing .git/rebase-apply &&\n"> <"\tgit cat-file commit HEAD | tail -n2 | head -n1 >actual &&\n"> <"\tgrep Message-Id patch1.eml >expected &&\n"> <"\ttest_cmp expected actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"am -3 works with rerere">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\n"> <"\t# make patches one->two and two->three...\n"> <"\ttest_commit one file &&\n"> <"\ttest_commit two file &&\n"> <"\ttest_commit three file &&\n"> <"\tgit format-patch -2 --stdout >seq.patch &&\n"> <"\n"> <"\t# and create a situation that conflicts...\n"> <"\tgit reset --hard one &&\n"> <"\ttest_commit other file &&\n"> <"\n"> <"\t# enable rerere...\n"> <"\ttest_config rerere.enabled true &&\n"> <"\ttest_when_finished \"rm -rf .git/rr-cache\" &&\n"> <"\n"> <"\t# ...and apply. Our resolution is to skip the first\n"> <"\t# patch, and the rerere the second one.\n"> <"\ttest_must_fail git am -3 seq.patch &&\n"> <"\ttest_must_fail git am --skip &&\n"> <"\techo resolved >file &&\n"> <"\tgit add file &&\n"> <"\tgit am --resolved &&\n"> <"\n"> <"\t# now apply again, and confirm that rerere engaged (we still\n"> <"\t# expect failure from am because rerere does not auto-commit\n"> <"\t# for us).\n"> <"\tgit reset --hard other &&\n"> <"\ttest_must_fail git am -3 seq.patch &&\n"> <"\ttest_must_fail git am --skip &&\n"> <"\techo resolved >expect &&\n"> <"\ttest_cmp expect file\n"> ) } ) (C {(test_expect_success)} {(SQ <"am -s unexpected trailer block">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit reset --hard &&\n"> <"\techo signed >file &&\n"> <"\tgit add file &&\n"> <"\tcat >msg <<-EOF &&\n"> <"\tsubject here\n"> <"\n"> <"\tSigned-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n"> <"\t[jc: tweaked log message]\n"> <"\tSigned-off-by: J C H \n"> <"\tEOF\n"> <"\tgit commit -F msg &&\n"> <"\tgit cat-file commit HEAD | sed -e "> ) (1) (Lit_Comma ",") (/) (Lit_Other "^") (Lit_Other "$") (/d) (SQ <" >original &&\n"> <"\tgit format-patch --stdout -1 >patch &&\n"> <"\n"> <"\tgit reset --hard HEAD^ &&\n"> <"\tgit am -s patch &&\n"> <"\t(\n"> <"\t\tcat original &&\n"> <"\t\techo \"Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\"\n"> <"\t) >expect &&\n"> <"\tgit cat-file commit HEAD | sed -e "> ) (1) (Lit_Comma ",") (/) (Lit_Other "^") (Lit_Other "$") (/d) (SQ <" >actual &&\n"> <"\ttest_cmp expect actual &&\n"> <"\n"> <"\tcat >msg <<-\\EOF &&\n"> <"\tsubject here\n"> <"\n"> <"\tWe make sure that there is a blank line between the log\n"> <"\tmessage proper and Signed-off-by: line added.\n"> <"\tEOF\n"> <"\tgit reset HEAD^ &&\n"> <"\tgit commit -F msg file &&\n"> <"\tgit cat-file commit HEAD | sed -e "> ) (1) (Lit_Comma ",") (/) (Lit_Other "^") (Lit_Other "$") (/d) (SQ <" >original &&\n"> <"\tgit format-patch --stdout -1 >patch &&\n"> <"\n"> <"\tgit reset --hard HEAD^ &&\n"> <"\tgit am -s patch &&\n"> <"\n"> <"\t(\n"> <"\t\tcat original &&\n"> <"\t\techo &&\n"> <"\t\techo \"Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\"\n"> <"\t) >expect &&\n"> <"\tgit cat-file commit HEAD | sed -e "> ) (1) (Lit_Comma ",") (/) (Lit_Other "^") (Lit_Other "$") (/d) (SQ <" >actual &&\n"> <"\ttest_cmp expect actual\n">) } ) (C {(test_expect_success)} {(SQ <"am --patch-format=mboxrd handles mboxrd">)} { (SQ <"\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit checkout -f first &&\n"> <"\techo mboxrd >>file &&\n"> <"\tgit add file &&\n"> <"\tcat >msg <<-\\INPUT_END &&\n"> <"\tmboxrd should escape the body\n"> <"\n"> <"\tFrom could trip up a loose mbox parser\n"> <"\t>From extra escape for reversibility\n"> <"\tINPUT_END\n"> <"\tgit commit -F msg &&\n"> <"\tgit format-patch --pretty=mboxrd --stdout -1 >mboxrd1 &&\n"> <"\tgrep \"^>From could trip up a loose mbox parser\" mboxrd1 &&\n"> <"\tgit checkout -f first &&\n"> <"\tgit am --patch-format=mboxrd mboxrd1 &&\n"> <"\tgit cat-file commit HEAD | tail -n4 >out &&\n"> <"\ttest_cmp msg out\n"> ) } ) (C {(test_expect_success)} {(SQ <"am works with multi-line in-body headers">)} { (SQ <"\n"> <"\tFORTY=\"String that has a length of more than forty characters\" &&\n"> <"\tLONG=\"$FORTY $FORTY\" &&\n"> <"\trm -fr .git/rebase-apply &&\n"> <"\tgit checkout -f first &&\n"> <"\techo one >> file &&\n"> <"\tgit commit -am \"$LONG\" --author=\"$LONG \" &&\n"> <"\tgit format-patch --stdout -1 >patch &&\n"> <"\t# bump from, date, and subject down to in-body header\n"> <"\tperl -lpe \"\n"> <"\t\tif (/^From:/) {\n"> <"\t\t\tprint \\\"From: x \\\";\n"> <"\t\t\tprint \\\"Date: Sat, 1 Jan 2000 00:00:00 +0000\\\";\n"> <"\t\t\tprint \\\"Subject: x\\n\\\";\n"> <"\t\t}\n"> <"\t\" patch >msg &&\n"> <"\tgit checkout HEAD^ &&\n"> <"\tgit am msg &&\n"> <"\t# Ensure that the author and full message are present\n"> <"\tgit cat-file commit HEAD | grep \"^author.*long@example.com\" &&\n"> <"\tgit cat-file commit HEAD | grep \"^$LONG\"\n"> ) } ) (C {(test_done)}) ] )