(command.CommandList
  children: [
    (command.ShAssignment
      pairs: [
        (assign_pair
          lhs: (sh_lhs_expr.Name name:test_description)
          op: assign_op.Equal
          rhs: 
            {
              (SQ <'Two way merge with read-tree -m $H $M\n'> <'\n'> 
                <'This test tries two-way merge (aka fast-forward with carry forward).\n'> <'\n'> <'There is the head (called H) and another commit (called M), which is\n'> 
                <'simply ahead of H.  The index and the work tree contains a state that\n'> <'is derived from H, but may also have local changes.  This test checks\n'> 
                <'all the combinations described in the two-tree merge "carry forward"\n'> <'rules, found in <Documentation/git read-tree.txt>.\n'> <'\n'> 
                <'In the test, these paths are used:\n'> <'        bozbar  - in H, stays in M, modified from bozbar to gnusto\n'> 
                <'        frotz   - not in H added in M\n'> <'        nitfol  - in H, stays in M unmodified\n'> <'        rezrov  - in H, deleted in M\n'> 
                <'\tyomin   - not in H or M\n'>
              )
            }
          spids: [13]
        )
      ]
    )
    (C {<.>} {<'./test-lib.sh'>})
    (C {<.>} {(DQ ($ Id.VSub_DollarName '$TEST_DIRECTORY')) <'/lib-read-tree.sh'>})
    (command.ShFunction
      name: read_tree_twoway
      body: 
        (BraceGroup
          children: [
            (command.AndOr
              ops: [Id.Op_DAmp]
              children: [
                (C {<git>} {<read-tree>} {<-m>} {(DQ ($ Id.VSub_Number '$1'))} 
                  {(DQ ($ Id.VSub_Number '$2'))}
                )
                (C {<git>} {<ls-files>} {<--stage>})
              ]
            )
          ]
        )
    )
    (command.ShFunction
      name: compare_change
      body: 
        (BraceGroup
          children: [
            (command.Simple
              words: [
                {<sed>}
                {<-n>}
                {<-e>}
                {(SQ <'/^--- /d; /^+++ /d; /^@@ /d;'>)}
                {<-e>}
                {(SQ <'s/^\\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\\) '>) 
                  (DQ ($ Id.VSub_DollarName '$_x40')) (SQ <' /\\1 X /p'>)
                }
                {(DQ ($ Id.VSub_Number '$1'))}
              ]
              redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<current>})]
              do_fork: T
            )
            (C {<test_cmp>} {<expected>} {<current>})
          ]
        )
    )
    (command.ShFunction
      name: check_cache_at
      body: 
        (BraceGroup
          children: [
            (command.ShAssignment
              pairs: [
                (assign_pair
                  lhs: (sh_lhs_expr.Name name:clean_if_empty)
                  op: assign_op.Equal
                  rhs: 
                    {
                      (command_sub
                        left_token: <Id.Left_DollarParen '$('>
                        child: (C {<git>} {<diff-files>} {<-->} {(DQ ($ Id.VSub_Number '$1'))})
                      )
                    }
                  spids: [139]
                )
              ]
            )
            (command.Case
              to_match: {(DQ ($ Id.VSub_DollarName '$clean_if_empty'))}
              arms: [
                (case_arm
                  pat_list: [{(SQ )}]
                  action: [(C {<echo>} {(DQ ($ Id.VSub_Number '$1') <': clean'>)})]
                  spids: [162 164 173 -1]
                )
                (case_arm
                  pat_list: [{<Id.Lit_QMark '?'> <Id.Lit_Star '*'>}]
                  action: [(C {<echo>} {(DQ ($ Id.VSub_Number '$1') <': dirty'>)})]
                  spids: [176 178 187 -1]
                )
              ]
            )
            (command.Case
              to_match: {(DQ ($ Id.VSub_Number '$2') <','> ($ Id.VSub_DollarName '$clean_if_empty'))}
              arms: [
                (case_arm
                  pat_list: [{<clean> <Id.Lit_Comma ','>}]
                  action: [(C {<Id.Lit_Colon ':'>})]
                  spids: [204 206 210 -1]
                )
                (case_arm
                  pat_list: [{<clean> <Id.Lit_Comma ','> <Id.Lit_QMark '?'> <Id.Lit_Star '*'>}]
                  action: [(C {<false>})]
                  spids: [213 217 221 -1]
                )
                (case_arm
                  pat_list: [{<dirty> <Id.Lit_Comma ','>}]
                  action: [(C {<false>})]
                  spids: [224 226 230 -1]
                )
                (case_arm
                  pat_list: [{<dirty> <Id.Lit_Comma ','> <Id.Lit_QMark '?'> <Id.Lit_Star '*'>}]
                  action: [(C {<Id.Lit_Colon ':'>})]
                  spids: [233 237 241 -1]
                )
              ]
            )
          ]
        )
    )
    (command.Simple
      words: [{<cat>}]
      redirects: [
        (redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<bozbar-old>})
        (redir
          op: <Id.Redir_DLess '<<'>
          loc: (redir_loc.Fd fd:0)
          arg: 
            (redir_param.HereDoc
              here_begin: {(word_part.EscapedLiteral token:<Id.Lit_EscapedChar '\\E'>) <OF>}
              here_end_span_id: 264
              stdin_parts: [
                <'This is a sample file used in two-way fast-forward merge\n'>
                <'tests.  Its second line ends with a magic word bozbar\n'>
                <'which will be modified by the merged head to gnusto.\n'>
                <'It has some extra lines so that external tools can\n'>
                <'successfully merge independent changes made to later\n'>
                <'lines (such as this one), avoiding line conflicts.\n'>
              ]
            )
        )
      ]
      do_fork: T
    )
    (command.Simple
      words: [{<sed>} {<-e>} {(SQ <'s/bozbar/gnusto (earlier bozbar)/'>)} {<bozbar-old>}]
      redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<bozbar-new>})]
      do_fork: T
    )
    (C {<test_expect_success>} {<setup>} 
      {
        (SQ <'echo frotz >frotz &&\n'> <'     echo nitfol >nitfol &&\n'> 
          <'     cat bozbar-old >bozbar &&\n'> <'     echo rezrov >rezrov &&\n'> <'     echo yomin >yomin &&\n'> 
          <'     git update-index --add nitfol bozbar rezrov &&\n'> <'     treeH=$(git write-tree) &&\n'> <'     echo treeH $treeH &&\n'> <'     git ls-tree $treeH &&\n'> 
          <'\n'> <'     cat bozbar-new >bozbar &&\n'> 
          <'     git update-index --add frotz bozbar --force-remove rezrov &&\n'> <'     git ls-files --stage >M.out &&\n'> <'     treeM=$(git write-tree) &&\n'> 
          <'     echo treeM $treeM &&\n'> <'     git ls-tree $treeM &&\n'> <'     git diff-tree $treeH $treeM'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'1, 2, 3 - no carry forward'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_twoway $treeH $treeM &&\n'> 
          <'     git ls-files --stage >1-3.out &&\n'> <'     test_cmp M.out 1-3.out &&\n'> <'     check_cache_at bozbar dirty &&\n'> 
          <'     check_cache_at frotz dirty &&\n'> <'     check_cache_at nitfol dirty'>
        )
      }
    )
    (command.Simple
      words: [{<echo>} {(SQ <'+100644 X 0\tyomin'>)}]
      redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<expected>})]
      do_fork: T
    )
    (C {<test_expect_success>} {(SQ <'4 - carry forward local addition.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     git update-index --add yomin &&\n'> <'     read_tree_twoway $treeH $treeM &&\n'> 
          <'     git ls-files --stage >4.out &&\n'> <'     test_must_fail git diff --no-index M.out 4.out >4diff.out &&\n'> 
          <'     compare_change 4diff.out expected &&\n'> <'     check_cache_at yomin clean'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'5 - carry forward local addition.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo yomin >yomin &&\n'> <'     git update-index --add yomin &&\n'> 
          <'     echo yomin yomin >yomin &&\n'> <'     read_tree_twoway $treeH $treeM &&\n'> <'     git ls-files --stage >5.out &&\n'> 
          <'     test_must_fail git diff --no-index M.out 5.out >5diff.out &&\n'> <'     compare_change 5diff.out expected &&\n'> <'     check_cache_at yomin dirty'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'6 - local addition already has the same.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     git update-index --add frotz &&\n'> <'     read_tree_twoway $treeH $treeM &&\n'> 
          <'     git ls-files --stage >6.out &&\n'> <'     test_cmp M.out 6.out &&\n'> <'     check_cache_at frotz clean'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'7 - local addition already has the same.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo frotz >frotz &&\n'> <'     git update-index --add frotz &&\n'> 
          <'     echo frotz frotz >frotz &&\n'> <'     read_tree_twoway $treeH $treeM &&\n'> <'     git ls-files --stage >7.out &&\n'> 
          <'     test_cmp M.out 7.out &&\n'> <'     check_cache_at frotz dirty'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'8 - conflicting addition.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo frotz frotz >frotz &&\n'> <'     git update-index --add frotz &&\n'> 
          <'     if read_tree_twoway $treeH $treeM; then false; else :; fi'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'9 - conflicting addition.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo frotz frotz >frotz &&\n'> <'     git update-index --add frotz &&\n'> 
          <'     echo frotz >frotz &&\n'> <'     if read_tree_twoway $treeH $treeM; then false; else :; fi'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'10 - path removed.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo rezrov >rezrov &&\n'> <'     git update-index --add rezrov &&\n'> 
          <'     read_tree_twoway $treeH $treeM &&\n'> <'     git ls-files --stage >10.out &&\n'> <'     test_cmp M.out 10.out'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'11 - dirty path removed.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo rezrov >rezrov &&\n'> <'     git update-index --add rezrov &&\n'> 
          <'     echo rezrov rezrov >rezrov &&\n'> <'     if read_tree_twoway $treeH $treeM; then false; else :; fi'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'12 - unmatching local changes being removed.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo rezrov rezrov >rezrov &&\n'> <'     git update-index --add rezrov &&\n'> 
          <'     if read_tree_twoway $treeH $treeM; then false; else :; fi'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'13 - unmatching local changes being removed.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo rezrov rezrov >rezrov &&\n'> <'     git update-index --add rezrov &&\n'> 
          <'     echo rezrov >rezrov &&\n'> <'     if read_tree_twoway $treeH $treeM; then false; else :; fi'>
        )
      }
    )
    (command.Simple
      words: [{<cat>}]
      redirects: [
        (redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<expected>})
        (redir
          op: <Id.Redir_DLess '<<'>
          loc: (redir_loc.Fd fd:0)
          arg: 
            (redir_param.HereDoc
              here_begin: {<EOF>}
              here_end_span_id: 570
              stdin_parts: [<'-100644 X 0\tnitfol\n'> <'+100644 X 0\tnitfol\n'>]
            )
        )
      ]
      do_fork: T
    )
    (C {<test_expect_success>} {(SQ <'14 - unchanged in two heads.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo nitfol nitfol >nitfol &&\n'> <'     git update-index --add nitfol &&\n'> 
          <'     read_tree_twoway $treeH $treeM &&\n'> <'     git ls-files --stage >14.out &&\n'> 
          <'     test_must_fail git diff --no-index M.out 14.out >14diff.out &&\n'> <'     compare_change 14diff.out expected &&\n'> <'     check_cache_at nitfol clean'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'15 - unchanged in two heads.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo nitfol nitfol >nitfol &&\n'> <'     git update-index --add nitfol &&\n'> 
          <'     echo nitfol nitfol nitfol >nitfol &&\n'> <'     read_tree_twoway $treeH $treeM &&\n'> <'     git ls-files --stage >15.out &&\n'> 
          <'     test_must_fail git diff --no-index M.out 15.out >15diff.out &&\n'> <'     compare_change 15diff.out expected &&\n'> <'     check_cache_at nitfol dirty'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'16 - conflicting local change.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo bozbar bozbar >bozbar &&\n'> <'     git update-index --add bozbar &&\n'> 
          <'     if read_tree_twoway $treeH $treeM; then false; else :; fi'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'17 - conflicting local change.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     echo bozbar bozbar >bozbar &&\n'> <'     git update-index --add bozbar &&\n'> 
          <'     echo bozbar bozbar bozbar >bozbar &&\n'> <'     if read_tree_twoway $treeH $treeM; then false; else :; fi'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'18 - local change already having a good result.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     cat bozbar-new >bozbar &&\n'> <'     git update-index --add bozbar &&\n'> 
          <'     read_tree_twoway $treeH $treeM &&\n'> <'     git ls-files --stage >18.out &&\n'> <'     test_cmp M.out 18.out &&\n'> 
          <'     check_cache_at bozbar clean'>
        )
      }
    )
    (C {<test_expect_success>} 
      {(SQ <'19 - local change already having a good result, further modified.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     cat bozbar-new >bozbar &&\n'> <'     git update-index --add bozbar &&\n'> 
          <'     echo gnusto gnusto >bozbar &&\n'> <'     read_tree_twoway $treeH $treeM &&\n'> <'     git ls-files --stage >19.out &&\n'> 
          <'     test_cmp M.out 19.out &&\n'> <'     check_cache_at bozbar dirty'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'20 - no local change, use new tree.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     cat bozbar-old >bozbar &&\n'> <'     git update-index --add bozbar &&\n'> 
          <'     read_tree_twoway $treeH $treeM &&\n'> <'     git ls-files --stage >20.out &&\n'> <'     test_cmp M.out 20.out &&\n'> 
          <'     check_cache_at bozbar dirty'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'21 - no local change, dirty cache.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     cat bozbar-old >bozbar &&\n'> <'     git update-index --add bozbar &&\n'> 
          <'     echo gnusto gnusto >bozbar &&\n'> <'     if read_tree_twoway $treeH $treeM; then false; else :; fi'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'22 - local change cache updated.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     read_tree_must_succeed $treeH &&\n'> 
          <'     git checkout-index -u -f -q -a &&\n'> <'     sed -e "s/such as/SUCH AS/" bozbar-old >bozbar &&\n'> 
          <'     git update-index --add bozbar &&\n'> <'     if read_tree_twoway $treeH $treeM; then false; else :; fi'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'DF vs DF/DF case setup.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     echo DF >DF &&\n'> <'     git update-index --add DF &&\n'> 
          <'     treeDF=$(git write-tree) &&\n'> <'     echo treeDF $treeDF &&\n'> <'     git ls-tree $treeDF &&\n'> <'\n'> <'     rm -f DF &&\n'> 
          <'     mkdir DF &&\n'> <'     echo DF/DF >DF/DF &&\n'> <'     git update-index --add --remove DF DF/DF &&\n'> 
          <'     treeDFDF=$(git write-tree) &&\n'> <'     echo treeDFDF $treeDFDF &&\n'> <'     git ls-tree $treeDFDF &&\n'> 
          <'     git ls-files --stage >DFDF.out'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'DF vs DF/DF case test.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     rm -fr DF &&\n'> <'     echo DF >DF &&\n'> 
          <'     git update-index --add DF &&\n'> <'     read_tree_twoway $treeDF $treeDFDF &&\n'> <'     git ls-files --stage >DFDFcheck.out &&\n'> 
          <'     test_cmp DFDF.out DFDFcheck.out &&\n'> <'     check_cache_at DF/DF dirty &&\n'> <'     :'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'a/b (untracked) vs a case setup.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     : >a &&\n'> <'     git update-index --add a &&\n'> 
          <'     treeM=$(git write-tree) &&\n'> <'     echo treeM $treeM &&\n'> <'     git ls-tree $treeM &&\n'> 
          <'     git ls-files --stage >treeM.out &&\n'> <'\n'> <'     rm -f a &&\n'> <'     git update-index --remove a &&\n'> <'     mkdir a &&\n'> 
          <'     : >a/b &&\n'> <'     treeH=$(git write-tree) &&\n'> <'     echo treeH $treeH &&\n'> <'     git ls-tree $treeH'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'a/b (untracked) vs a, plus c/d case test.'>)} 
      {
        (SQ <'read_tree_u_must_fail -u -m "$treeH" "$treeM" &&\n'> <'     git ls-files --stage &&\n'> 
          <'     test -f a/b'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'a/b vs a, plus c/d case setup.'>)} 
      {
        (SQ <'rm -f .git/index &&\n'> <'     rm -fr a &&\n'> <'     : >a &&\n'> <'     mkdir c &&\n'> 
          <'     : >c/d &&\n'> <'     git update-index --add a c/d &&\n'> <'     treeM=$(git write-tree) &&\n'> 
          <'     echo treeM $treeM &&\n'> <'     git ls-tree $treeM &&\n'> <'     git ls-files --stage >treeM.out &&\n'> <'\n'> 
          <'     rm -f a &&\n'> <'     mkdir a &&\n'> <'     : >a/b &&\n'> <'     git update-index --add --remove a a/b &&\n'> 
          <'     treeH=$(git write-tree) &&\n'> <'     echo treeH $treeH &&\n'> <'     git ls-tree $treeH'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'a/b vs a, plus c/d case test.'>)} 
      {
        (SQ <'read_tree_u_must_succeed -u -m "$treeH" "$treeM" &&\n'> 
          <'     git ls-files --stage | tee >treeMcheck.out &&\n'> <'     test_cmp treeM.out treeMcheck.out'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'-m references the correct modified tree'>)} 
      {
        (SQ <'\n'> <'\techo >file-a &&\n'> <'\techo >file-b &&\n'> <'\tgit add file-a file-b &&\n'> 
          <'\tgit commit -a -m "test for correct modified tree" &&\n'> <'\tgit branch initial-mod &&\n'> <'\techo b >file-b &&\n'> <'\tgit commit -a -m "B" &&\n'> 
          <'\techo a >file-a &&\n'> <'\tgit add file-a &&\n'> <'\tgit ls-tree $(git write-tree) file-a >expect &&\n'> 
          <'\tread_tree_must_succeed -m HEAD initial-mod &&\n'> <'\tgit ls-tree $(git write-tree) file-a >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_done>})
  ]
)