(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)})
  ]
)