#!/bin/sh global test_description := ''Test cherry-pick continuation features + conflicting: rewrites unrelated to conflicting + yetanotherpick: rewrites foo to e + anotherpick: rewrites foo to d + picked: rewrites foo to c + unrelatedpick: rewrites unrelated to reallyunrelated + base: rewrites foo to b + initial: writes foo as a, unrelated as unrelated '' source ./test-lib.sh # Repeat first match 10 times global _r10 := ''\1\1\1\1\1\1\1\1\1\1'' proc pristine_detach { git cherry-pick --quit && git checkout -f "$1^0" && git read-tree -u --reset HEAD && git clean -d -f -f -q -x } test_expect_success setup ' git config advice.detachedhead false && echo unrelated >unrelated && git add unrelated && test_commit initial foo a && test_commit base foo b && test_commit unrelatedpick unrelated reallyunrelated && test_commit picked foo c && test_commit anotherpick foo d && test_commit yetanotherpick foo e && pristine_detach initial && test_commit conflicting unrelated ' test_expect_success 'cherry-pick persists data on failure' ' pristine_detach initial && test_expect_code 1 git cherry-pick -s base..anotherpick && test_path_is_dir .git/sequencer && test_path_is_file .git/sequencer/head && test_path_is_file .git/sequencer/todo && test_path_is_file .git/sequencer/opts ' test_expect_success 'cherry-pick mid-cherry-pick-sequence' ' pristine_detach initial && test_must_fail git cherry-pick base..anotherpick && test_cmp_rev picked CHERRY_PICK_HEAD && # "oops, I forgot that these patches rely on the change from base" git checkout HEAD foo && git cherry-pick base && git cherry-pick picked && git cherry-pick --continue && git diff --exit-code anotherpick ' test_expect_success 'cherry-pick persists opts correctly' ' pristine_detach initial && test_expect_code 128 git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours initial..anotherpick && test_path_is_dir .git/sequencer && test_path_is_file .git/sequencer/head && test_path_is_file .git/sequencer/todo && test_path_is_file .git/sequencer/opts && echo "true" >expect && git config --file=.git/sequencer/opts --get-all options.signoff >actual && test_cmp expect actual && echo "1" >expect && git config --file=.git/sequencer/opts --get-all options.mainline >actual && test_cmp expect actual && echo "recursive" >expect && git config --file=.git/sequencer/opts --get-all options.strategy >actual && test_cmp expect actual && cat >expect <<-\EOF && patience ours EOF git config --file=.git/sequencer/opts --get-all options.strategy-option >actual && test_cmp expect actual ' test_expect_success 'cherry-pick cleans up sequencer state upon success' ' pristine_detach initial && git cherry-pick initial..picked && test_path_is_missing .git/sequencer ' test_expect_success '--quit does not complain when no cherry-pick is in progress' ' pristine_detach initial && git cherry-pick --quit ' test_expect_success '--abort requires cherry-pick in progress' ' pristine_detach initial && test_must_fail git cherry-pick --abort ' test_expect_success '--quit cleans up sequencer state' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..picked && git cherry-pick --quit && test_path_is_missing .git/sequencer ' test_expect_success '--quit keeps HEAD and conflicted index intact' ' pristine_detach initial && cat >expect <<-\EOF && OBJID :100644 100644 OBJID OBJID M unrelated OBJID :000000 100644 OBJID OBJID A foo :000000 100644 OBJID OBJID A unrelated EOF test_expect_code 1 git cherry-pick base..picked && git cherry-pick --quit && test_path_is_missing .git/sequencer && test_must_fail git update-index --refresh && { git rev-list HEAD | git diff-tree --root --stdin | sed "s/$_x40/OBJID/g" } >actual && test_cmp expect actual ' test_expect_success '--abort to cancel multiple cherry-pick' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..anotherpick && git cherry-pick --abort && test_path_is_missing .git/sequencer && test_cmp_rev initial HEAD && git update-index --refresh && git diff-index --exit-code HEAD ' test_expect_success '--abort to cancel single cherry-pick' ' pristine_detach initial && test_expect_code 1 git cherry-pick picked && git cherry-pick --abort && test_path_is_missing .git/sequencer && test_cmp_rev initial HEAD && git update-index --refresh && git diff-index --exit-code HEAD ' test_expect_success 'cherry-pick --abort to cancel multiple revert' ' pristine_detach anotherpick && test_expect_code 1 git revert base..picked && git cherry-pick --abort && test_path_is_missing .git/sequencer && test_cmp_rev anotherpick HEAD && git update-index --refresh && git diff-index --exit-code HEAD ' test_expect_success 'revert --abort works, too' ' pristine_detach anotherpick && test_expect_code 1 git revert base..picked && git revert --abort && test_path_is_missing .git/sequencer && test_cmp_rev anotherpick HEAD ' test_expect_success '--abort to cancel single revert' ' pristine_detach anotherpick && test_expect_code 1 git revert picked && git revert --abort && test_path_is_missing .git/sequencer && test_cmp_rev anotherpick HEAD && git update-index --refresh && git diff-index --exit-code HEAD ' test_expect_success '--abort keeps unrelated change, easy case' ' pristine_detach unrelatedpick && echo changed >expect && test_expect_code 1 git cherry-pick picked..yetanotherpick && echo changed >unrelated && git cherry-pick --abort && test_cmp expect unrelated ' test_expect_success '--abort refuses to clobber unrelated change, harder case' ' pristine_detach initial && echo changed >expect && test_expect_code 1 git cherry-pick base..anotherpick && echo changed >unrelated && test_must_fail git cherry-pick --abort && test_cmp expect unrelated && git rev-list HEAD >log && test_line_count = 2 log && test_must_fail git update-index --refresh && git checkout unrelated && git cherry-pick --abort && test_cmp_rev initial HEAD ' test_expect_success 'cherry-pick still writes sequencer state when one commit is left' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..picked && test_path_is_dir .git/sequencer && echo "resolved" >foo && git add foo && git commit && { git rev-list HEAD | git diff-tree --root --stdin | sed "s/$_x40/OBJID/g" } >actual && cat >expect <<-\EOF && OBJID :100644 100644 OBJID OBJID M foo OBJID :100644 100644 OBJID OBJID M unrelated OBJID :000000 100644 OBJID OBJID A foo :000000 100644 OBJID OBJID A unrelated EOF test_cmp expect actual ' test_expect_success '--abort after last commit in sequence' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..picked && git cherry-pick --abort && test_path_is_missing .git/sequencer && test_cmp_rev initial HEAD && git update-index --refresh && git diff-index --exit-code HEAD ' test_expect_success 'cherry-pick does not implicitly stomp an existing operation' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..anotherpick && test-chmtime -v +0 .git/sequencer >expect && test_expect_code 128 git cherry-pick unrelatedpick && test-chmtime -v +0 .git/sequencer >actual && test_cmp expect actual ' test_expect_success '--continue complains when no cherry-pick is in progress' ' pristine_detach initial && test_expect_code 128 git cherry-pick --continue ' test_expect_success '--continue complains when there are unresolved conflicts' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..anotherpick && test_expect_code 128 git cherry-pick --continue ' test_expect_success '--continue of single cherry-pick' ' pristine_detach initial && echo c >expect && test_must_fail git cherry-pick picked && echo c >foo && git add foo && git cherry-pick --continue && test_cmp expect foo && test_cmp_rev initial HEAD^ && git diff --exit-code HEAD && test_must_fail git rev-parse --verify CHERRY_PICK_HEAD ' test_expect_success '--continue of single revert' ' pristine_detach initial && echo resolved >expect && echo "Revert \"picked\"" >expect.msg && test_must_fail git revert picked && echo resolved >foo && git add foo && git cherry-pick --continue && git diff --exit-code HEAD && test_cmp expect foo && test_cmp_rev initial HEAD^ && git diff-tree -s --pretty=tformat:%s HEAD >msg && test_cmp expect.msg msg && test_must_fail git rev-parse --verify CHERRY_PICK_HEAD && test_must_fail git rev-parse --verify REVERT_HEAD ' test_expect_success '--continue after resolving conflicts' ' pristine_detach initial && echo d >expect && cat >expect.log <<-\EOF && OBJID :100644 100644 OBJID OBJID M foo OBJID :100644 100644 OBJID OBJID M foo OBJID :100644 100644 OBJID OBJID M unrelated OBJID :000000 100644 OBJID OBJID A foo :000000 100644 OBJID OBJID A unrelated EOF test_must_fail git cherry-pick base..anotherpick && echo c >foo && git add foo && git cherry-pick --continue && { git rev-list HEAD | git diff-tree --root --stdin | sed "s/$_x40/OBJID/g" } >actual.log && test_cmp expect foo && test_cmp expect.log actual.log ' test_expect_success '--continue after resolving conflicts and committing' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..anotherpick && echo "c" >foo && git add foo && git commit && git cherry-pick --continue && test_path_is_missing .git/sequencer && { git rev-list HEAD | git diff-tree --root --stdin | sed "s/$_x40/OBJID/g" } >actual && cat >expect <<-\EOF && OBJID :100644 100644 OBJID OBJID M foo OBJID :100644 100644 OBJID OBJID M foo OBJID :100644 100644 OBJID OBJID M unrelated OBJID :000000 100644 OBJID OBJID A foo :000000 100644 OBJID OBJID A unrelated EOF test_cmp expect actual ' test_expect_success '--continue asks for help after resolving patch to nil' ' pristine_detach conflicting && test_must_fail git cherry-pick initial..picked && test_cmp_rev unrelatedpick CHERRY_PICK_HEAD && git checkout HEAD -- unrelated && test_must_fail git cherry-pick --continue 2>msg && test_i18ngrep "The previous cherry-pick is now empty" msg ' test_expect_success 'follow advice and skip nil patch' ' pristine_detach conflicting && test_must_fail git cherry-pick initial..picked && git checkout HEAD -- unrelated && test_must_fail git cherry-pick --continue && git reset && git cherry-pick --continue && git rev-list initial..HEAD >commits && test_line_count = 3 commits ' test_expect_success '--continue respects opts' ' pristine_detach initial && test_expect_code 1 git cherry-pick -x base..anotherpick && echo "c" >foo && git add foo && git commit && git cherry-pick --continue && test_path_is_missing .git/sequencer && git cat-file commit HEAD >anotherpick_msg && git cat-file commit HEAD~1 >picked_msg && git cat-file commit HEAD~2 >unrelatedpick_msg && git cat-file commit HEAD~3 >initial_msg && test_must_fail grep "cherry picked from" initial_msg && grep "cherry picked from" unrelatedpick_msg && grep "cherry picked from" picked_msg && grep "cherry picked from" anotherpick_msg ' test_expect_success '--continue of single-pick respects -x' ' pristine_detach initial && test_must_fail git cherry-pick -x picked && echo c >foo && git add foo && git cherry-pick --continue && test_path_is_missing .git/sequencer && git cat-file commit HEAD >msg && grep "cherry picked from" msg ' test_expect_success '--continue respects -x in first commit in multi-pick' ' pristine_detach initial && test_must_fail git cherry-pick -x picked anotherpick && echo c >foo && git add foo && git cherry-pick --continue && test_path_is_missing .git/sequencer && git cat-file commit HEAD^ >msg && picked=$(git rev-parse --verify picked) && grep "cherry picked from.*$picked" msg ' test_expect_failure '--signoff is automatically propagated to resolved conflict' ' pristine_detach initial && test_expect_code 1 git cherry-pick --signoff base..anotherpick && echo "c" >foo && git add foo && git commit && git cherry-pick --continue && test_path_is_missing .git/sequencer && git cat-file commit HEAD >anotherpick_msg && git cat-file commit HEAD~1 >picked_msg && git cat-file commit HEAD~2 >unrelatedpick_msg && git cat-file commit HEAD~3 >initial_msg && test_must_fail grep "Signed-off-by:" initial_msg && grep "Signed-off-by:" unrelatedpick_msg && test_must_fail grep "Signed-off-by:" picked_msg && grep "Signed-off-by:" anotherpick_msg ' test_expect_failure '--signoff dropped for implicit commit of resolution, multi-pick case' ' pristine_detach initial && test_must_fail git cherry-pick -s picked anotherpick && echo c >foo && git add foo && git cherry-pick --continue && git diff --exit-code HEAD && test_cmp_rev initial HEAD^^ && git cat-file commit HEAD^ >msg && ! grep Signed-off-by: msg ' test_expect_failure 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' ' pristine_detach initial && test_must_fail git cherry-pick -s picked && echo c >foo && git add foo && git cherry-pick --continue && git diff --exit-code HEAD && test_cmp_rev initial HEAD^ && git cat-file commit HEAD >msg && ! grep Signed-off-by: msg ' test_expect_success 'malformed instruction sheet 1' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..anotherpick && echo "resolved" >foo && git add foo && git commit && sed "s/pick /pick/" .git/sequencer/todo >new_sheet && cp new_sheet .git/sequencer/todo && test_expect_code 128 git cherry-pick --continue ' test_expect_success 'malformed instruction sheet 2' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..anotherpick && echo "resolved" >foo && git add foo && git commit && sed "s/pick/revert/" .git/sequencer/todo >new_sheet && cp new_sheet .git/sequencer/todo && test_expect_code 128 git cherry-pick --continue ' test_expect_success 'empty commit set' ' pristine_detach initial && test_expect_code 128 git cherry-pick base..base ' test_expect_success 'malformed instruction sheet 3' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..anotherpick && echo "resolved" >foo && git add foo && git commit && sed "s/pick \([0-9a-f]*\)/pick $_r10/" .git/sequencer/todo >new_sheet && cp new_sheet .git/sequencer/todo && test_expect_code 128 git cherry-pick --continue ' test_expect_success 'instruction sheet, fat-fingers version' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..anotherpick && echo "c" >foo && git add foo && git commit && sed "s/pick \([0-9a-f]*\)/pick \1 /" .git/sequencer/todo >new_sheet && cp new_sheet .git/sequencer/todo && git cherry-pick --continue ' test_expect_success 'commit descriptions in insn sheet are optional' ' pristine_detach initial && test_expect_code 1 git cherry-pick base..anotherpick && echo "c" >foo && git add foo && git commit && cut -d" " -f1,2 .git/sequencer/todo >new_sheet && cp new_sheet .git/sequencer/todo && git cherry-pick --continue && test_path_is_missing .git/sequencer && git rev-list HEAD >commits && test_line_count = 4 commits ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: { (SQ <"Test cherry-pick continuation features\n"> <"\n"> <" + conflicting: rewrites unrelated to conflicting\n"> <" + yetanotherpick: rewrites foo to e\n"> <" + anotherpick: rewrites foo to d\n"> <" + picked: rewrites foo to c\n"> <" + unrelatedpick: rewrites unrelated to reallyunrelated\n"> <" + base: rewrites foo to b\n"> <" + initial: writes foo as a, unrelated as unrelated\n"> <"\n"> ) } spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:_r10) op: Equal rhs: {(SQ <"\\1\\1\\1\\1\\1\\1\\1\\1\\1\\1">)} spids: [27] ) ] spids: [27] ) (FuncDef name: pristine_detach body: (BraceGroup children: [ (AndOr children: [ (C {(git)} {(cherry-pick)} {(--quit)}) (AndOr children: [ (C {(git)} {(checkout)} {(-f)} {(DQ ($ VSub_Number "$1") ("^0"))}) (AndOr children: [ (C {(git)} {(read-tree)} {(-u)} {(--reset)} {(HEAD)}) (C {(git)} {(clean)} {(-d)} {(-f)} {(-f)} {(-q)} {(-x)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [38] ) spids: [33 37] ) (C {(test_expect_success)} {(setup)} { (SQ <"\n"> <"\tgit config advice.detachedhead false &&\n"> <"\techo unrelated >unrelated &&\n"> <"\tgit add unrelated &&\n"> <"\ttest_commit initial foo a &&\n"> <"\ttest_commit base foo b &&\n"> <"\ttest_commit unrelatedpick unrelated reallyunrelated &&\n"> <"\ttest_commit picked foo c &&\n"> <"\ttest_commit anotherpick foo d &&\n"> <"\ttest_commit yetanotherpick foo e &&\n"> <"\tpristine_detach initial &&\n"> <"\ttest_commit conflicting unrelated\n"> ) } ) (C {(test_expect_success)} {(SQ <"cherry-pick persists data on failure">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick -s base..anotherpick &&\n"> <"\ttest_path_is_dir .git/sequencer &&\n"> <"\ttest_path_is_file .git/sequencer/head &&\n"> <"\ttest_path_is_file .git/sequencer/todo &&\n"> <"\ttest_path_is_file .git/sequencer/opts\n"> ) } ) (C {(test_expect_success)} {(SQ <"cherry-pick mid-cherry-pick-sequence">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_must_fail git cherry-pick base..anotherpick &&\n"> <"\ttest_cmp_rev picked CHERRY_PICK_HEAD &&\n"> <"\t# \"oops, I forgot that these patches rely on the change from base\"\n"> <"\tgit checkout HEAD foo &&\n"> <"\tgit cherry-pick base &&\n"> <"\tgit cherry-pick picked &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\tgit diff --exit-code anotherpick\n"> ) } ) (C {(test_expect_success)} {(SQ <"cherry-pick persists opts correctly">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> < "\ttest_expect_code 128 git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours initial..anotherpick &&\n" > <"\ttest_path_is_dir .git/sequencer &&\n"> <"\ttest_path_is_file .git/sequencer/head &&\n"> <"\ttest_path_is_file .git/sequencer/todo &&\n"> <"\ttest_path_is_file .git/sequencer/opts &&\n"> <"\techo \"true\" >expect &&\n"> <"\tgit config --file=.git/sequencer/opts --get-all options.signoff >actual &&\n"> <"\ttest_cmp expect actual &&\n"> <"\techo \"1\" >expect &&\n"> <"\tgit config --file=.git/sequencer/opts --get-all options.mainline >actual &&\n"> <"\ttest_cmp expect actual &&\n"> <"\techo \"recursive\" >expect &&\n"> <"\tgit config --file=.git/sequencer/opts --get-all options.strategy >actual &&\n"> <"\ttest_cmp expect actual &&\n"> <"\tcat >expect <<-\\EOF &&\n"> <"\tpatience\n"> <"\tours\n"> <"\tEOF\n"> <"\tgit config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"cherry-pick cleans up sequencer state upon success">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\tgit cherry-pick initial..picked &&\n"> <"\ttest_path_is_missing .git/sequencer\n"> ) } ) (C {(test_expect_success)} {(SQ <"--quit does not complain when no cherry-pick is in progress">)} {(SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\tgit cherry-pick --quit\n">)} ) (C {(test_expect_success)} {(SQ <"--abort requires cherry-pick in progress">)} {(SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_must_fail git cherry-pick --abort\n">)} ) (C {(test_expect_success)} {(SQ <"--quit cleans up sequencer state">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..picked &&\n"> <"\tgit cherry-pick --quit &&\n"> <"\ttest_path_is_missing .git/sequencer\n"> ) } ) (C {(test_expect_success)} {(SQ <"--quit keeps HEAD and conflicted index intact">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\tcat >expect <<-\\EOF &&\n"> <"\tOBJID\n"> <"\t:100644 100644 OBJID OBJID M\tunrelated\n"> <"\tOBJID\n"> <"\t:000000 100644 OBJID OBJID A\tfoo\n"> <"\t:000000 100644 OBJID OBJID A\tunrelated\n"> <"\tEOF\n"> <"\ttest_expect_code 1 git cherry-pick base..picked &&\n"> <"\tgit cherry-pick --quit &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\ttest_must_fail git update-index --refresh &&\n"> <"\t{\n"> <"\t\tgit rev-list HEAD |\n"> <"\t\tgit diff-tree --root --stdin |\n"> <"\t\tsed \"s/$_x40/OBJID/g\"\n"> <"\t} >actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"--abort to cancel multiple cherry-pick">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..anotherpick &&\n"> <"\tgit cherry-pick --abort &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\ttest_cmp_rev initial HEAD &&\n"> <"\tgit update-index --refresh &&\n"> <"\tgit diff-index --exit-code HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"--abort to cancel single cherry-pick">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick picked &&\n"> <"\tgit cherry-pick --abort &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\ttest_cmp_rev initial HEAD &&\n"> <"\tgit update-index --refresh &&\n"> <"\tgit diff-index --exit-code HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"cherry-pick --abort to cancel multiple revert">)} { (SQ <"\n"> <"\tpristine_detach anotherpick &&\n"> <"\ttest_expect_code 1 git revert base..picked &&\n"> <"\tgit cherry-pick --abort &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\ttest_cmp_rev anotherpick HEAD &&\n"> <"\tgit update-index --refresh &&\n"> <"\tgit diff-index --exit-code HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"revert --abort works, too">)} { (SQ <"\n"> <"\tpristine_detach anotherpick &&\n"> <"\ttest_expect_code 1 git revert base..picked &&\n"> <"\tgit revert --abort &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\ttest_cmp_rev anotherpick HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"--abort to cancel single revert">)} { (SQ <"\n"> <"\tpristine_detach anotherpick &&\n"> <"\ttest_expect_code 1 git revert picked &&\n"> <"\tgit revert --abort &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\ttest_cmp_rev anotherpick HEAD &&\n"> <"\tgit update-index --refresh &&\n"> <"\tgit diff-index --exit-code HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"--abort keeps unrelated change, easy case">)} { (SQ <"\n"> <"\tpristine_detach unrelatedpick &&\n"> <"\techo changed >expect &&\n"> <"\ttest_expect_code 1 git cherry-pick picked..yetanotherpick &&\n"> <"\techo changed >unrelated &&\n"> <"\tgit cherry-pick --abort &&\n"> <"\ttest_cmp expect unrelated\n"> ) } ) (C {(test_expect_success)} {(SQ <"--abort refuses to clobber unrelated change, harder case">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\techo changed >expect &&\n"> <"\ttest_expect_code 1 git cherry-pick base..anotherpick &&\n"> <"\techo changed >unrelated &&\n"> <"\ttest_must_fail git cherry-pick --abort &&\n"> <"\ttest_cmp expect unrelated &&\n"> <"\tgit rev-list HEAD >log &&\n"> <"\ttest_line_count = 2 log &&\n"> <"\ttest_must_fail git update-index --refresh &&\n"> <"\n"> <"\tgit checkout unrelated &&\n"> <"\tgit cherry-pick --abort &&\n"> <"\ttest_cmp_rev initial HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"cherry-pick still writes sequencer state when one commit is left">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..picked &&\n"> <"\ttest_path_is_dir .git/sequencer &&\n"> <"\techo \"resolved\" >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit commit &&\n"> <"\t{\n"> <"\t\tgit rev-list HEAD |\n"> <"\t\tgit diff-tree --root --stdin |\n"> <"\t\tsed \"s/$_x40/OBJID/g\"\n"> <"\t} >actual &&\n"> <"\tcat >expect <<-\\EOF &&\n"> <"\tOBJID\n"> <"\t:100644 100644 OBJID OBJID M\tfoo\n"> <"\tOBJID\n"> <"\t:100644 100644 OBJID OBJID M\tunrelated\n"> <"\tOBJID\n"> <"\t:000000 100644 OBJID OBJID A\tfoo\n"> <"\t:000000 100644 OBJID OBJID A\tunrelated\n"> <"\tEOF\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"--abort after last commit in sequence">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..picked &&\n"> <"\tgit cherry-pick --abort &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\ttest_cmp_rev initial HEAD &&\n"> <"\tgit update-index --refresh &&\n"> <"\tgit diff-index --exit-code HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"cherry-pick does not implicitly stomp an existing operation">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..anotherpick &&\n"> <"\ttest-chmtime -v +0 .git/sequencer >expect &&\n"> <"\ttest_expect_code 128 git cherry-pick unrelatedpick &&\n"> <"\ttest-chmtime -v +0 .git/sequencer >actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"--continue complains when no cherry-pick is in progress">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 128 git cherry-pick --continue\n"> ) } ) (C {(test_expect_success)} {(SQ <"--continue complains when there are unresolved conflicts">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..anotherpick &&\n"> <"\ttest_expect_code 128 git cherry-pick --continue\n"> ) } ) (C {(test_expect_success)} {(SQ <"--continue of single cherry-pick">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\techo c >expect &&\n"> <"\ttest_must_fail git cherry-pick picked &&\n"> <"\techo c >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\n"> <"\ttest_cmp expect foo &&\n"> <"\ttest_cmp_rev initial HEAD^ &&\n"> <"\tgit diff --exit-code HEAD &&\n"> <"\ttest_must_fail git rev-parse --verify CHERRY_PICK_HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"--continue of single revert">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\techo resolved >expect &&\n"> <"\techo \"Revert \\\"picked\\\"\" >expect.msg &&\n"> <"\ttest_must_fail git revert picked &&\n"> <"\techo resolved >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\n"> <"\tgit diff --exit-code HEAD &&\n"> <"\ttest_cmp expect foo &&\n"> <"\ttest_cmp_rev initial HEAD^ &&\n"> <"\tgit diff-tree -s --pretty=tformat:%s HEAD >msg &&\n"> <"\ttest_cmp expect.msg msg &&\n"> <"\ttest_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&\n"> <"\ttest_must_fail git rev-parse --verify REVERT_HEAD\n"> ) } ) (C {(test_expect_success)} {(SQ <"--continue after resolving conflicts">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\techo d >expect &&\n"> <"\tcat >expect.log <<-\\EOF &&\n"> <"\tOBJID\n"> <"\t:100644 100644 OBJID OBJID M\tfoo\n"> <"\tOBJID\n"> <"\t:100644 100644 OBJID OBJID M\tfoo\n"> <"\tOBJID\n"> <"\t:100644 100644 OBJID OBJID M\tunrelated\n"> <"\tOBJID\n"> <"\t:000000 100644 OBJID OBJID A\tfoo\n"> <"\t:000000 100644 OBJID OBJID A\tunrelated\n"> <"\tEOF\n"> <"\ttest_must_fail git cherry-pick base..anotherpick &&\n"> <"\techo c >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\t{\n"> <"\t\tgit rev-list HEAD |\n"> <"\t\tgit diff-tree --root --stdin |\n"> <"\t\tsed \"s/$_x40/OBJID/g\"\n"> <"\t} >actual.log &&\n"> <"\ttest_cmp expect foo &&\n"> <"\ttest_cmp expect.log actual.log\n"> ) } ) (C {(test_expect_success)} {(SQ <"--continue after resolving conflicts and committing">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..anotherpick &&\n"> <"\techo \"c\" >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit commit &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\t{\n"> <"\t\tgit rev-list HEAD |\n"> <"\t\tgit diff-tree --root --stdin |\n"> <"\t\tsed \"s/$_x40/OBJID/g\"\n"> <"\t} >actual &&\n"> <"\tcat >expect <<-\\EOF &&\n"> <"\tOBJID\n"> <"\t:100644 100644 OBJID OBJID M\tfoo\n"> <"\tOBJID\n"> <"\t:100644 100644 OBJID OBJID M\tfoo\n"> <"\tOBJID\n"> <"\t:100644 100644 OBJID OBJID M\tunrelated\n"> <"\tOBJID\n"> <"\t:000000 100644 OBJID OBJID A\tfoo\n"> <"\t:000000 100644 OBJID OBJID A\tunrelated\n"> <"\tEOF\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"--continue asks for help after resolving patch to nil">)} { (SQ <"\n"> <"\tpristine_detach conflicting &&\n"> <"\ttest_must_fail git cherry-pick initial..picked &&\n"> <"\n"> <"\ttest_cmp_rev unrelatedpick CHERRY_PICK_HEAD &&\n"> <"\tgit checkout HEAD -- unrelated &&\n"> <"\ttest_must_fail git cherry-pick --continue 2>msg &&\n"> <"\ttest_i18ngrep \"The previous cherry-pick is now empty\" msg\n"> ) } ) (C {(test_expect_success)} {(SQ <"follow advice and skip nil patch">)} { (SQ <"\n"> <"\tpristine_detach conflicting &&\n"> <"\ttest_must_fail git cherry-pick initial..picked &&\n"> <"\n"> <"\tgit checkout HEAD -- unrelated &&\n"> <"\ttest_must_fail git cherry-pick --continue &&\n"> <"\tgit reset &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\n"> <"\tgit rev-list initial..HEAD >commits &&\n"> <"\ttest_line_count = 3 commits\n"> ) } ) (C {(test_expect_success)} {(SQ <"--continue respects opts">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick -x base..anotherpick &&\n"> <"\techo \"c\" >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit commit &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\tgit cat-file commit HEAD >anotherpick_msg &&\n"> <"\tgit cat-file commit HEAD~1 >picked_msg &&\n"> <"\tgit cat-file commit HEAD~2 >unrelatedpick_msg &&\n"> <"\tgit cat-file commit HEAD~3 >initial_msg &&\n"> <"\ttest_must_fail grep \"cherry picked from\" initial_msg &&\n"> <"\tgrep \"cherry picked from\" unrelatedpick_msg &&\n"> <"\tgrep \"cherry picked from\" picked_msg &&\n"> <"\tgrep \"cherry picked from\" anotherpick_msg\n"> ) } ) (C {(test_expect_success)} {(SQ <"--continue of single-pick respects -x">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_must_fail git cherry-pick -x picked &&\n"> <"\techo c >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\tgit cat-file commit HEAD >msg &&\n"> <"\tgrep \"cherry picked from\" msg\n"> ) } ) (C {(test_expect_success)} {(SQ <"--continue respects -x in first commit in multi-pick">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_must_fail git cherry-pick -x picked anotherpick &&\n"> <"\techo c >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\tgit cat-file commit HEAD^ >msg &&\n"> <"\tpicked=$(git rev-parse --verify picked) &&\n"> <"\tgrep \"cherry picked from.*$picked\" msg\n"> ) } ) (C {(test_expect_failure)} {(SQ <"--signoff is automatically propagated to resolved conflict">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick --signoff base..anotherpick &&\n"> <"\techo \"c\" >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit commit &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\tgit cat-file commit HEAD >anotherpick_msg &&\n"> <"\tgit cat-file commit HEAD~1 >picked_msg &&\n"> <"\tgit cat-file commit HEAD~2 >unrelatedpick_msg &&\n"> <"\tgit cat-file commit HEAD~3 >initial_msg &&\n"> <"\ttest_must_fail grep \"Signed-off-by:\" initial_msg &&\n"> <"\tgrep \"Signed-off-by:\" unrelatedpick_msg &&\n"> <"\ttest_must_fail grep \"Signed-off-by:\" picked_msg &&\n"> <"\tgrep \"Signed-off-by:\" anotherpick_msg\n"> ) } ) (C {(test_expect_failure)} {(SQ <"--signoff dropped for implicit commit of resolution, multi-pick case">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_must_fail git cherry-pick -s picked anotherpick &&\n"> <"\techo c >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\n"> <"\tgit diff --exit-code HEAD &&\n"> <"\ttest_cmp_rev initial HEAD^^ &&\n"> <"\tgit cat-file commit HEAD^ >msg &&\n"> <"\t! grep Signed-off-by: msg\n"> ) } ) (C {(test_expect_failure)} {(SQ <"sign-off needs to be reaffirmed after conflict resolution, single-pick case">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_must_fail git cherry-pick -s picked &&\n"> <"\techo c >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\n"> <"\tgit diff --exit-code HEAD &&\n"> <"\ttest_cmp_rev initial HEAD^ &&\n"> <"\tgit cat-file commit HEAD >msg &&\n"> <"\t! grep Signed-off-by: msg\n"> ) } ) (C {(test_expect_success)} {(SQ <"malformed instruction sheet 1">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..anotherpick &&\n"> <"\techo \"resolved\" >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit commit &&\n"> <"\tsed \"s/pick /pick/\" .git/sequencer/todo >new_sheet &&\n"> <"\tcp new_sheet .git/sequencer/todo &&\n"> <"\ttest_expect_code 128 git cherry-pick --continue\n"> ) } ) (C {(test_expect_success)} {(SQ <"malformed instruction sheet 2">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..anotherpick &&\n"> <"\techo \"resolved\" >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit commit &&\n"> <"\tsed \"s/pick/revert/\" .git/sequencer/todo >new_sheet &&\n"> <"\tcp new_sheet .git/sequencer/todo &&\n"> <"\ttest_expect_code 128 git cherry-pick --continue\n"> ) } ) (C {(test_expect_success)} {(SQ <"empty commit set">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 128 git cherry-pick base..base\n"> ) } ) (C {(test_expect_success)} {(SQ <"malformed instruction sheet 3">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..anotherpick &&\n"> <"\techo \"resolved\" >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit commit &&\n"> <"\tsed \"s/pick \\([0-9a-f]*\\)/pick $_r10/\" .git/sequencer/todo >new_sheet &&\n"> <"\tcp new_sheet .git/sequencer/todo &&\n"> <"\ttest_expect_code 128 git cherry-pick --continue\n"> ) } ) (C {(test_expect_success)} {(SQ <"instruction sheet, fat-fingers version">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..anotherpick &&\n"> <"\techo \"c\" >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit commit &&\n"> <"\tsed \"s/pick \\([0-9a-f]*\\)/pick \t \\1 \t/\" .git/sequencer/todo >new_sheet &&\n"> <"\tcp new_sheet .git/sequencer/todo &&\n"> <"\tgit cherry-pick --continue\n"> ) } ) (C {(test_expect_success)} {(SQ <"commit descriptions in insn sheet are optional">)} { (SQ <"\n"> <"\tpristine_detach initial &&\n"> <"\ttest_expect_code 1 git cherry-pick base..anotherpick &&\n"> <"\techo \"c\" >foo &&\n"> <"\tgit add foo &&\n"> <"\tgit commit &&\n"> <"\tcut -d\" \" -f1,2 .git/sequencer/todo >new_sheet &&\n"> <"\tcp new_sheet .git/sequencer/todo &&\n"> <"\tgit cherry-pick --continue &&\n"> <"\ttest_path_is_missing .git/sequencer &&\n"> <"\tgit rev-list HEAD >commits &&\n"> <"\ttest_line_count = 4 commits\n"> ) } ) (C {(test_done)}) ] )