From: Junio C Hamano Date: Mon, 3 Aug 2015 17:41:32 +0000 (-0700) Subject: Merge branch 'pt/am-abort-fix' into maint X-Git-Tag: v2.4.8~4 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/c36e465aca712cea70cb9570a1e7136e5de36b76?ds=inline;hp=-c Merge branch 'pt/am-abort-fix' into maint Various fixes around "git am" that applies a patch to a history that is not there yet. * pt/am-abort-fix: am --abort: keep unrelated commits on unborn branch am --abort: support aborting to unborn branch am --abort: revert changes introduced by failed 3way merge am --skip: support skipping while on unborn branch am -3: support 3way merge on unborn branch am --skip: revert changes introduced by failed 3way merge --- c36e465aca712cea70cb9570a1e7136e5de36b76 diff --combined git-am.sh index a67d0f9898,f594ed0811..3103c0fc28 --- a/git-am.sh +++ b/git-am.sh @@@ -17,7 -17,6 +17,7 @@@ s,signoff add a Signed-off-by lin u,utf8 recode into utf8 (default) k,keep pass -k flag to git-mailinfo keep-non-patch pass -b flag to git-mailinfo +m,message-id pass -m flag to git-mailinfo keep-cr pass --keep-cr flag to git-mailsplit for mbox format no-keep-cr do not pass --keep-cr flag to git-mailsplit independent of am.keepcr c,scissors strip everything before a scissors line @@@ -69,6 -68,8 +69,8 @@@ the cmdline="$cmdline -3" fi + empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904 + sq () { git rev-parse --sq-quote "$@" } @@@ -85,7 -86,7 +87,7 @@@ safe_to_abort () return 1 fi - if ! test -s "$dotest/abort-safety" + if ! test -f "$dotest/abort-safety" then return 0 fi @@@ -177,7 -178,8 +179,8 @@@ It does not apply to blobs recorded in then GIT_MERGE_VERBOSITY=0 && export GIT_MERGE_VERBOSITY fi - git-merge-recursive $orig_tree -- HEAD $his_tree || { + our_tree=$(git rev-parse --verify -q HEAD || echo $empty_tree) + git-merge-recursive $orig_tree -- $our_tree $his_tree || { git rerere $allow_rerere_autoupdate die "$(gettext "Failed to merge in the changes.")" } @@@ -372,18 -374,13 +375,18 @@@ split_patches () prec=4 dotest="$GIT_DIR/rebase-apply" sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort= -resolvemsg= resume= scissors= no_inbody_headers= +messageid= resolvemsg= resume= scissors= no_inbody_headers= git_apply_opt= committer_date_is_author_date= ignore_date= allow_rerere_autoupdate= gpg_sign_opt= +if test "$(git config --bool --get am.messageid)" = true +then + messageid=t +fi + if test "$(git config --bool --get am.keepcr)" = true then keepcr=t @@@ -406,10 -403,6 +409,10 @@@ it will be removed. Please do not use i utf8=t ;; # this is now default --no-utf8) utf8= ;; + -m|--message-id) + messageid=t ;; + --no-message-id) + messageid=f ;; -k|--keep) keep=t ;; --keep-non-patch) @@@ -502,10 -495,11 +505,11 @@@ the ;; t,) git rerere clear - git read-tree --reset -u HEAD HEAD - orig_head=$(cat "$GIT_DIR/ORIG_HEAD") - git reset HEAD - git update-ref ORIG_HEAD $orig_head + head_tree=$(git rev-parse --verify -q HEAD || echo $empty_tree) && + git read-tree --reset -u $head_tree $head_tree && + index_tree=$(git write-tree) && + git read-tree -m -u $index_tree $head_tree + git read-tree $head_tree ;; ,t) if test -f "$dotest/rebasing" @@@ -515,8 -509,19 +519,19 @@@ git rerere clear if safe_to_abort then - git read-tree --reset -u HEAD ORIG_HEAD - git reset ORIG_HEAD + head_tree=$(git rev-parse --verify -q HEAD || echo $empty_tree) && + git read-tree --reset -u $head_tree $head_tree && + index_tree=$(git write-tree) && + orig_head=$(git rev-parse --verify -q ORIG_HEAD || echo $empty_tree) && + git read-tree -m -u $index_tree $orig_head + if git rev-parse --verify -q ORIG_HEAD >/dev/null 2>&1 + then + git reset ORIG_HEAD + else + git read-tree $empty_tree + curr_branch=$(git symbolic-ref HEAD 2>/dev/null) && + git update-ref -d $curr_branch + fi fi rm -fr "$dotest" exit ;; @@@ -577,7 -582,6 +592,7 @@@ Use \"git am --abort\" to remove it.") echo "$sign" >"$dotest/sign" echo "$utf8" >"$dotest/utf8" echo "$keep" >"$dotest/keep" + echo "$messageid" >"$dotest/messageid" echo "$scissors" >"$dotest/scissors" echo "$no_inbody_headers" >"$dotest/no_inbody_headers" echo "$GIT_QUIET" >"$dotest/quiet" @@@ -632,12 -636,6 +647,12 @@@ b *) keep= ;; esac +case "$(cat "$dotest/messageid")" in +t) + messageid=-m ;; +f) + messageid= ;; +esac case "$(cat "$dotest/scissors")" in t) scissors=--scissors ;; @@@ -709,7 -707,7 +724,7 @@@ d get_author_ident_from_commit "$commit" >"$dotest/author-script" git diff-tree --root --binary --full-index "$commit" >"$dotest/patch" else - git mailinfo $keep $no_inbody_headers $scissors $utf8 "$dotest/msg" "$dotest/patch" \ + git mailinfo $keep $no_inbody_headers $messageid $scissors $utf8 "$dotest/msg" "$dotest/patch" \ <"$dotest/$msgnum" >"$dotest/info" || stop_here $this diff --combined t/t4151-am-abort.sh index 8d90634ab8,1274f75a60..833e7b2cea --- a/t/t4151-am-abort.sh +++ b/t/t4151-am-abort.sh @@@ -14,13 -14,14 +14,14 @@@ test_expect_success setup git add file-1 file-2 && git commit -m initial && git tag initial && + git format-patch --stdout --root initial >initial.patch && for i in 2 3 4 5 6 do echo $i >>file-1 && echo $i >otherfile-$i && git add otherfile-$i && test_tick && - git commit -a -m $i || break + git commit -a -m $i || return 1 done && git format-patch --no-numbered initial && git checkout -b side initial && @@@ -63,6 -64,28 +64,28 @@@ d done + test_expect_success 'am -3 --skip removes otherfile-4' ' + git reset --hard initial && + test_must_fail git am -3 0003-*.patch && + test 3 -eq $(git ls-files -u | wc -l) && + test 4 = "$(cat otherfile-4)" && + git am --skip && + test_cmp_rev initial HEAD && + test -z "$(git ls-files -u)" && + test_path_is_missing otherfile-4 + ' + + test_expect_success 'am -3 --abort removes otherfile-4' ' + git reset --hard initial && + test_must_fail git am -3 0003-*.patch && + test 3 -eq $(git ls-files -u | wc -l) && + test 4 = "$(cat otherfile-4)" && + git am --abort && + test_cmp_rev initial HEAD && + test -z $(git ls-files -u) && + test_path_is_missing otherfile-4 + ' + test_expect_success 'am --abort will keep the local commits intact' ' test_must_fail git am 0004-*.patch && test_commit unrelated && @@@ -72,4 -95,62 +95,62 @@@ test_cmp expect actual ' + test_expect_success 'am -3 stops on conflict on unborn branch' ' + git checkout -f --orphan orphan && + git reset && + rm -f otherfile-4 && + test_must_fail git am -3 0003-*.patch && + test 2 -eq $(git ls-files -u | wc -l) && + test 4 = "$(cat otherfile-4)" + ' + + test_expect_success 'am -3 --skip clears index on unborn branch' ' + test_path_is_dir .git/rebase-apply && + echo tmpfile >tmpfile && + git add tmpfile && + git am --skip && + test -z "$(git ls-files)" && + test_path_is_missing otherfile-4 && + test_path_is_missing tmpfile + ' + + test_expect_success 'am -3 --abort removes otherfile-4 on unborn branch' ' + git checkout -f --orphan orphan && + git reset && + rm -f otherfile-4 file-1 && + test_must_fail git am -3 0003-*.patch && + test 2 -eq $(git ls-files -u | wc -l) && + test 4 = "$(cat otherfile-4)" && + git am --abort && + test -z "$(git ls-files -u)" && + test_path_is_missing otherfile-4 + ' + + test_expect_success 'am -3 --abort on unborn branch removes applied commits' ' + git checkout -f --orphan orphan && + git reset && + rm -f otherfile-4 otherfile-2 file-1 file-2 && + test_must_fail git am -3 initial.patch 0003-*.patch && + test 3 -eq $(git ls-files -u | wc -l) && + test 4 = "$(cat otherfile-4)" && + git am --abort && + test -z "$(git ls-files -u)" && + test_path_is_missing otherfile-4 && + test_path_is_missing file-1 && + test_path_is_missing file-2 && + test 0 -eq $(git log --oneline 2>/dev/null | wc -l) && + test refs/heads/orphan = "$(git symbolic-ref HEAD)" + ' + + test_expect_success 'am --abort on unborn branch will keep local commits intact' ' + git checkout -f --orphan orphan && + git reset && + test_must_fail git am 0004-*.patch && + test_commit unrelated2 && + git rev-parse HEAD >expect && + git am --abort && + git rev-parse HEAD >actual && + test_cmp expect actual + ' + test_done