(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 </dev/null >output &&\n'> <'\tgrep "+1/-0 *+2/-0 file" output\n'>)} ) (C {(test_expect_success)} {(SQ <'setup expected'>)} { (SQ <'\n'> <'cat >expected <<EOF\n'> <'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" <output >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 </dev/null >output &&\n'> <'\tgrep "+1/-0 *+2/-0 file" output\n'>)} ) (C {(test_expect_success)} {(SQ <'setup expected'>)} { (SQ <'\n'> <'cat >expected <<EOF\n'> <'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" <output >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 </dev/null >output &&\n'> <'\tgrep "unchanged *+3/-0 file" output\n'> ) } ) (C {(test_expect_success)} {(SQ <'setup expected'>)} {(SQ <'\n'> <'cat >expected <<EOF\n'> <'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 <<EOF\n'> <'@@ -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 <<EOF\n'> <'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 <<EOF\n'> <'@@ -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 <<EOF\n'> <'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 <<EOF\n'> <'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 <<EOF\n'> <'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 <<EOF\n'> <'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 <<EOF\n'> <'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)}) ] )