#!/bin/sh global test_description := ''add -i basic tests'' source ./test-lib.sh if ! test_have_prereq PERL { global skip_all := ''skipping add -i tests, perl not available'' test_done } test_expect_success 'setup (initial)' ' echo content >file && git add file && echo more >>file && echo lines >>file ' test_expect_success 'status works (initial)' ' git add -i output && grep "+1/-0 *+2/-0 file" output ' test_expect_success 'setup expected' ' cat >expected <output && sed -ne "/new file/,/content/p" diff && test_cmp expected diff ' test_expect_success 'revert works (initial)' ' git add file && (echo r; echo 1) | git add -i && git ls-files >output && ! grep . output ' test_expect_success 'setup (commit)' ' echo baseline >file && git add file && git commit -m commit && echo content >>file && git add file && echo more >>file && echo lines >>file ' test_expect_success 'status works (commit)' ' git add -i output && grep "+1/-0 *+2/-0 file" output ' test_expect_success 'setup expected' ' cat >expected <output && sed -ne "/^index/,/content/p" diff && test_cmp expected diff ' test_expect_success 'revert works (commit)' ' git add file && (echo r; echo 1) | git add -i && git add -i output && grep "unchanged *+3/-0 file" output ' test_expect_success 'setup expected' ' cat >expected <fake_editor.sh && chmod a+x fake_editor.sh && test_set_editor "$(pwd)/fake_editor.sh" ' test_expect_success 'dummy edit works' ' (echo e; echo a) | git add -p && git diff > diff && test_cmp expected diff ' test_expect_success 'setup patch' ' cat >patch <fake_editor.sh && cat >>fake_editor.sh <<\EOF && mv -f "$1" oldpatch && mv -f patch "$1" EOF chmod a+x fake_editor.sh && test_set_editor "$(pwd)/fake_editor.sh" ' test_expect_success 'bad edit rejected' ' git reset && (echo e; echo n; echo d) | git add -p >output && grep "hunk does not apply" output ' test_expect_success 'setup patch' ' cat >patch <output && grep "hunk does not apply" output ' test_expect_success 'setup patch' ' cat >patch <expected <output && test_cmp expected output ' test_expect_success 'skip files similarly as commit -a' ' git reset && echo file >.gitignore && echo changed >file && echo y | git add -p file && git diff >output && git reset && git commit -am commit && git diff >expected && test_cmp expected output && git reset --hard HEAD^ ' rm -f .gitignore test_expect_success FILEMODE 'patch does not affect mode' ' git reset --hard && echo content >>file && chmod +x file && printf "n\\ny\\n" | git add -p && git show :file | grep content && git diff file | grep "new mode" ' test_expect_success FILEMODE 'stage mode but not hunk' ' git reset --hard && echo content >>file && chmod +x file && printf "y\\nn\\n" | git add -p && git diff --cached file | grep "new mode" && git diff file | grep "+content" ' test_expect_success FILEMODE 'stage mode and hunk' ' git reset --hard && echo content >>file && chmod +x file && printf "y\\ny\\n" | git add -p && git diff --cached file | grep "new mode" && git diff --cached file | grep "+content" && test -z "$(git diff file)" ' # end of tests disabled when filemode is not usable test_expect_success 'setup again' ' git reset --hard && test_chmod +x file && echo content >>file ' # Write the patch file with a new line at the top and bottom test_expect_success 'setup patch' ' cat >patch <expected < diff && test_cmp expected diff ' test_expect_success 'setup expected' ' cat >expected <non-empty && git add non-empty && git commit -m non-empty && rm non-empty && echo y | git add -p non-empty && git diff --cached >diff && test_cmp expected diff ' test_expect_success 'setup expected' ' cat >expected < empty && git add empty && git commit -m empty && rm empty && echo y | git add -p empty && git diff --cached >diff && test_cmp expected diff ' test_expect_success 'split hunk setup' ' git reset --hard && for i in 10 20 30 40 50 60 do echo $i done >test && git add test && test_tick && git commit -m test && for i in 10 15 20 21 22 23 24 30 40 50 60 do echo $i done >test ' test_expect_success 'split hunk "add -p (edit)"' ' # Split, say Edit and do nothing. Then: # # 1. Broken version results in a patch that does not apply and # only takes [y/n] (edit again) so the first q is discarded # and then n attempts to discard the edit. Repeat q enough # times to get out. # # 2. Correct version applies the (not)edited version, and asks # about the next hunk, against which we say q and program # exits. printf "%s\n" s e q n q q | EDITOR=: git add -p && git diff >actual && ! grep "^+15" actual ' test_expect_failure 'split hunk "add -p (no, yes, edit)"' ' cat >test <<-\EOF && 5 10 20 21 30 31 40 50 60 EOF git reset && # test sequence is s(plit), n(o), y(es), e(dit) # q n q q is there to make sure we exit at the end. printf "%s\n" s n y e q n q q | EDITOR=: git add -p 2>error && test_must_be_empty error && git diff >actual && ! grep "^+31" actual ' test_expect_success 'patch mode ignores unmerged entries' ' git reset --hard && test_commit conflict && test_commit non-conflict && git checkout -b side && test_commit side conflict.t && git checkout master && test_commit master conflict.t && test_must_fail git merge side && echo changed >non-conflict.t && echo y | git add -p >output && ! grep a/conflict.t output && cat >expected <<-\EOF && * Unmerged path conflict.t diff --git a/non-conflict.t b/non-conflict.t index f766221..5ea2ed4 100644 --- a/non-conflict.t +++ b/non-conflict.t @@ -1 +1 @@ -non-conflict +changed EOF git diff --cached >diff && test_cmp expected diff ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"add -i basic tests">)} spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (If arms: [ (if_arm cond: [(Pipeline children:[(C {(test_have_prereq)} {(PERL)})] negated:True)] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:skip_all) op: Equal rhs: {(SQ <"skipping add -i tests, perl not available">)} spids: [25] ) ] spids: [25] ) (C {(test_done)}) ] spids: [-1 22] ) ] spids: [-1 33] ) (C {(test_expect_success)} {(SQ <"setup (initial)">)} { (SQ <"\n"> <"\techo content >file &&\n"> <"\tgit add file &&\n"> <"\techo more >>file &&\n"> <"\techo lines >>file\n"> ) } ) (C {(test_expect_success)} {(SQ <"status works (initial)">)} { (SQ <"\n"> <"\tgit add -i output &&\n"> <"\tgrep \"+1/-0 *+2/-0 file\" output\n">) } ) (C {(test_expect_success)} {(SQ <"setup expected">)} { (SQ <"\n"> <"cat >expected < <"new file mode 100644\n"> <"index 0000000..d95f3ad\n"> <"--- /dev/null\n"> <"+++ b/file\n"> <"@@ -0,0 +1 @@\n"> <"+content\n"> <"EOF\n"> ) } ) (C {(test_expect_success)} {(SQ <"diff works (initial)">)} { (SQ <"\n"> <"\t(echo d; echo 1) | git add -i >output &&\n"> <"\tsed -ne \"/new file/,/content/p\" diff &&\n"> <"\ttest_cmp expected diff\n"> ) } ) (C {(test_expect_success)} {(SQ <"revert works (initial)">)} { (SQ <"\n"> <"\tgit add file &&\n"> <"\t(echo r; echo 1) | git add -i &&\n"> <"\tgit ls-files >output &&\n"> <"\t! grep . output\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup (commit)">)} { (SQ <"\n"> <"\techo baseline >file &&\n"> <"\tgit add file &&\n"> <"\tgit commit -m commit &&\n"> <"\techo content >>file &&\n"> <"\tgit add file &&\n"> <"\techo more >>file &&\n"> <"\techo lines >>file\n"> ) } ) (C {(test_expect_success)} {(SQ <"status works (commit)">)} { (SQ <"\n"> <"\tgit add -i output &&\n"> <"\tgrep \"+1/-0 *+2/-0 file\" output\n">) } ) (C {(test_expect_success)} {(SQ <"setup expected">)} { (SQ <"\n"> <"cat >expected < <"index 180b47c..b6f2c08 100644\n"> <"--- a/file\n"> <"+++ b/file\n"> <"@@ -1 +1,2 @@\n"> <" baseline\n"> <"+content\n"> <"EOF\n"> ) } ) (C {(test_expect_success)} {(SQ <"diff works (commit)">)} { (SQ <"\n"> <"\t(echo d; echo 1) | git add -i >output &&\n"> <"\tsed -ne \"/^index/,/content/p\" diff &&\n"> <"\ttest_cmp expected diff\n"> ) } ) (C {(test_expect_success)} {(SQ <"revert works (commit)">)} { (SQ <"\n"> <"\tgit add file &&\n"> <"\t(echo r; echo 1) | git add -i &&\n"> <"\tgit add -i output &&\n"> <"\tgrep \"unchanged *+3/-0 file\" output\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup expected">)} {(SQ <"\n"> <"cat >expected < <"EOF\n">)} ) (C {(test_expect_success)} {(SQ <"setup fake editor">)} { (SQ <"\n"> <"\t>fake_editor.sh &&\n"> <"\tchmod a+x fake_editor.sh &&\n"> <"\ttest_set_editor \"$(pwd)/fake_editor.sh\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"dummy edit works">)} { (SQ <"\n"> <"\t(echo e; echo a) | git add -p &&\n"> <"\tgit diff > diff &&\n"> <"\ttest_cmp expected diff\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup patch">)} { (SQ <"\n"> <"cat >patch < <"@@ -1,1 +1,4 @@\n"> <" this\n"> <"+patch\n"> <"-does not\n"> <" apply\n"> <"EOF\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup fake editor">)} { (SQ <"\n"> <"\techo \"#!$SHELL_PATH\" >fake_editor.sh &&\n"> <"\tcat >>fake_editor.sh <<\\EOF &&\n"> <"mv -f \"$1\" oldpatch &&\n"> <"mv -f patch \"$1\"\n"> <"EOF\n"> <"\tchmod a+x fake_editor.sh &&\n"> <"\ttest_set_editor \"$(pwd)/fake_editor.sh\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"bad edit rejected">)} { (SQ <"\n"> <"\tgit reset &&\n"> <"\t(echo e; echo n; echo d) | git add -p >output &&\n"> <"\tgrep \"hunk does not apply\" output\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup patch">)} {(SQ <"\n"> <"cat >patch < <"this patch\n"> <"is garbage\n"> <"EOF\n">)} ) (C {(test_expect_success)} {(SQ <"garbage edit rejected">)} { (SQ <"\n"> <"\tgit reset &&\n"> <"\t(echo e; echo n; echo d) | git add -p >output &&\n"> <"\tgrep \"hunk does not apply\" output\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup patch">)} { (SQ <"\n"> <"cat >patch < <"@@ -1,0 +1,0 @@\n"> <" baseline\n"> <"+content\n"> <"+newcontent\n"> <"+lines\n"> <"EOF\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup expected">)} { (SQ <"\n"> <"cat >expected < <"diff --git a/file b/file\n"> <"index b5dd6c9..f910ae9 100644\n"> <"--- a/file\n"> <"+++ b/file\n"> <"@@ -1,4 +1,4 @@\n"> <" baseline\n"> <" content\n"> <"-newcontent\n"> <"+more\n"> <" lines\n"> <"EOF\n"> ) } ) (C {(test_expect_success)} {(SQ <"real edit works">)} { (SQ <"\n"> <"\t(echo e; echo n; echo d) | git add -p &&\n"> <"\tgit diff >output &&\n"> <"\ttest_cmp expected output\n"> ) } ) (C {(test_expect_success)} {(SQ <"skip files similarly as commit -a">)} { (SQ <"\n"> <"\tgit reset &&\n"> <"\techo file >.gitignore &&\n"> <"\techo changed >file &&\n"> <"\techo y | git add -p file &&\n"> <"\tgit diff >output &&\n"> <"\tgit reset &&\n"> <"\tgit commit -am commit &&\n"> <"\tgit diff >expected &&\n"> <"\ttest_cmp expected output &&\n"> <"\tgit reset --hard HEAD^\n"> ) } ) (C {(rm)} {(-f)} {(.gitignore)}) (C {(test_expect_success)} {(FILEMODE)} {(SQ <"patch does not affect mode">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\techo content >>file &&\n"> <"\tchmod +x file &&\n"> <"\tprintf \"n\\\\ny\\\\n\" | git add -p &&\n"> <"\tgit show :file | grep content &&\n"> <"\tgit diff file | grep \"new mode\"\n"> ) } ) (C {(test_expect_success)} {(FILEMODE)} {(SQ <"stage mode but not hunk">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\techo content >>file &&\n"> <"\tchmod +x file &&\n"> <"\tprintf \"y\\\\nn\\\\n\" | git add -p &&\n"> <"\tgit diff --cached file | grep \"new mode\" &&\n"> <"\tgit diff file | grep \"+content\"\n"> ) } ) (C {(test_expect_success)} {(FILEMODE)} {(SQ <"stage mode and hunk">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\techo content >>file &&\n"> <"\tchmod +x file &&\n"> <"\tprintf \"y\\\\ny\\\\n\" | git add -p &&\n"> <"\tgit diff --cached file | grep \"new mode\" &&\n"> <"\tgit diff --cached file | grep \"+content\" &&\n"> <"\ttest -z \"$(git diff file)\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup again">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\ttest_chmod +x file &&\n"> <"\techo content >>file\n">) } ) (C {(test_expect_success)} {(SQ <"setup patch">)} { (SQ <"\n"> <"cat >patch < <"index 180b47c..b6f2c08 100644\n"> <"--- a/file\n"> <"+++ b/file\n"> <"@@ -1,2 +1,4 @@\n"> <"+firstline\n"> <" baseline\n"> <" content\n"> <"+lastline\n"> <"EOF\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup expected">)} { (SQ <"\n"> <"cat >expected < <"diff --git a/file b/file\n"> <"index b6f2c08..61b9053 100755\n"> <"--- a/file\n"> <"+++ b/file\n"> <"@@ -1,2 +1,4 @@\n"> <"+firstline\n"> <" baseline\n"> <" content\n"> <"+lastline\n"> <"EOF\n"> ) } ) (C {(test_expect_success)} {(SQ <"add first line works">)} { (SQ <"\n"> <"\tgit commit -am \"clear local changes\" &&\n"> <"\tgit apply patch &&\n"> <"\t(echo s; echo y; echo y) | git add -p file &&\n"> <"\tgit diff --cached > diff &&\n"> <"\ttest_cmp expected diff\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup expected">)} { (SQ <"\n"> <"cat >expected < <"diff --git a/non-empty b/non-empty\n"> <"deleted file mode 100644\n"> <"index d95f3ad..0000000\n"> <"--- a/non-empty\n"> <"+++ /dev/null\n"> <"@@ -1 +0,0 @@\n"> <"-content\n"> <"EOF\n"> ) } ) (C {(test_expect_success)} {(SQ <"deleting a non-empty file">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\techo content >non-empty &&\n"> <"\tgit add non-empty &&\n"> <"\tgit commit -m non-empty &&\n"> <"\trm non-empty &&\n"> <"\techo y | git add -p non-empty &&\n"> <"\tgit diff --cached >diff &&\n"> <"\ttest_cmp expected diff\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup expected">)} { (SQ <"\n"> <"cat >expected < <"diff --git a/empty b/empty\n"> <"deleted file mode 100644\n"> <"index e69de29..0000000\n"> <"EOF\n"> ) } ) (C {(test_expect_success)} {(SQ <"deleting an empty file">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\t> empty &&\n"> <"\tgit add empty &&\n"> <"\tgit commit -m empty &&\n"> <"\trm empty &&\n"> <"\techo y | git add -p empty &&\n"> <"\tgit diff --cached >diff &&\n"> <"\ttest_cmp expected diff\n"> ) } ) (C {(test_expect_success)} {(SQ <"split hunk setup">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\tfor i in 10 20 30 40 50 60\n"> <"\tdo\n"> <"\t\techo $i\n"> <"\tdone >test &&\n"> <"\tgit add test &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m test &&\n"> <"\n"> <"\tfor i in 10 15 20 21 22 23 24 30 40 50 60\n"> <"\tdo\n"> <"\t\techo $i\n"> <"\tdone >test\n"> ) } ) (C {(test_expect_success)} {(SQ <"split hunk \"add -p (edit)\"">)} { (SQ <"\n"> <"\t# Split, say Edit and do nothing. Then:\n"> <"\t#\n"> <"\t# 1. Broken version results in a patch that does not apply and\n"> <"\t# only takes [y/n] (edit again) so the first q is discarded\n"> <"\t# and then n attempts to discard the edit. Repeat q enough\n"> <"\t# times to get out.\n"> <"\t#\n"> <"\t# 2. Correct version applies the (not)edited version, and asks\n"> <"\t# about the next hunk, against which we say q and program\n"> <"\t# exits.\n"> <"\tprintf \"%s\\n\" s e q n q q |\n"> <"\tEDITOR=: git add -p &&\n"> <"\tgit diff >actual &&\n"> <"\t! grep \"^+15\" actual\n"> ) } ) (C {(test_expect_failure)} {(SQ <"split hunk \"add -p (no, yes, edit)\"">)} { (SQ <"\n"> <"\tcat >test <<-\\EOF &&\n"> <"\t5\n"> <"\t10\n"> <"\t20\n"> <"\t21\n"> <"\t30\n"> <"\t31\n"> <"\t40\n"> <"\t50\n"> <"\t60\n"> <"\tEOF\n"> <"\tgit reset &&\n"> <"\t# test sequence is s(plit), n(o), y(es), e(dit)\n"> <"\t# q n q q is there to make sure we exit at the end.\n"> <"\tprintf \"%s\\n\" s n y e q n q q |\n"> <"\tEDITOR=: git add -p 2>error &&\n"> <"\ttest_must_be_empty error &&\n"> <"\tgit diff >actual &&\n"> <"\t! grep \"^+31\" actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"patch mode ignores unmerged entries">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\ttest_commit conflict &&\n"> <"\ttest_commit non-conflict &&\n"> <"\tgit checkout -b side &&\n"> <"\ttest_commit side conflict.t &&\n"> <"\tgit checkout master &&\n"> <"\ttest_commit master conflict.t &&\n"> <"\ttest_must_fail git merge side &&\n"> <"\techo changed >non-conflict.t &&\n"> <"\techo y | git add -p >output &&\n"> <"\t! grep a/conflict.t output &&\n"> <"\tcat >expected <<-\\EOF &&\n"> <"\t* Unmerged path conflict.t\n"> <"\tdiff --git a/non-conflict.t b/non-conflict.t\n"> <"\tindex f766221..5ea2ed4 100644\n"> <"\t--- a/non-conflict.t\n"> <"\t+++ b/non-conflict.t\n"> <"\t@@ -1 +1 @@\n"> <"\t-non-conflict\n"> <"\t+changed\n"> <"\tEOF\n"> <"\tgit diff --cached >diff &&\n"> <"\ttest_cmp expected diff\n"> ) } ) (C {(test_done)}) ] )