(command.CommandList
  children: [
    (command.ShAssignment
      pairs: [
        (assign_pair
          lhs: (sh_lhs_expr.Name name:test_description)
          op: assign_op.Equal
          rhs: 
            {
              (SQ <'git ls-files --others --exclude\n'> <'\n'> 
                <'This test runs git ls-files --others and tests --exclude patterns.\n'>
              )
            }
          spids: [13]
        )
      ]
    )
    (C {<.>} {<'./test-lib.sh'>})
    (C {<rm>} {<-fr>} {<one>} {<three>})
    (command.ForEach
      iter_name: dir
      iter_words: [{<.>} {<one>} {<'one/two'>} {<three>}]
      do_arg_iter: F
      body: 
        (command.DoGroup
          children: [
            (command.AndOr
              ops: [Id.Op_DAmp]
              children: [
                (C {<mkdir>} {<-p>} {($ Id.VSub_DollarName '$dir')})
                (command.ForEach
                  iter_name: i
                  iter_words: [{<1>} {<2>} {<3>} {<4>} {<5>} {<6>} {<7>} {<8>}]
                  do_arg_iter: F
                  body: 
                    (command.DoGroup
                      children: [
                        (command.Simple
                          redirects: [
                            (redir
                              op: <Id.Redir_Great '>'>
                              loc: (redir_loc.Fd fd:1)
                              arg: {($ Id.VSub_DollarName '$dir') <'/a.'> ($ Id.VSub_DollarName '$i')}
                            )
                          ]
                          do_fork: F
                        )
                      ]
                    )
                )
              ]
            )
          ]
        )
    )
    (command.Simple
      redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{(DQ <'#ignore1'>)})]
      do_fork: F
    )
    (command.Simple
      redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{(DQ <'#ignore2'>)})]
      do_fork: F
    )
    (command.Simple
      redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{(DQ <'#hidden'>)})]
      do_fork: F
    )
    (command.Simple
      words: [{<cat>}]
      redirects: [
        (redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<expect>})
        (redir
          op: <Id.Redir_DLess '<<'>
          loc: (redir_loc.Fd fd:0)
          arg: 
            (redir_param.MultiLine
              here_begin: {<EOF>}
              here_end_span_id: 139
              stdin_parts: [
                <'a.2\n'>
                <'a.4\n'>
                <'a.5\n'>
                <'a.8\n'>
                <'one/a.3\n'>
                <'one/a.4\n'>
                <'one/a.5\n'>
                <'one/a.7\n'>
                <'one/two/a.2\n'>
                <'one/two/a.3\n'>
                <'one/two/a.5\n'>
                <'one/two/a.7\n'>
                <'one/two/a.8\n'>
                <'three/a.2\n'>
                <'three/a.3\n'>
                <'three/a.4\n'>
                <'three/a.5\n'>
                <'three/a.8\n'>
              ]
            )
        )
      ]
      do_fork: T
    )
    (command.Simple
      words: [
        {<echo>}
        {
          (SQ <'.gitignore\n'> <'\\#ignore1\n'> <'\\#ignore2*\n'> <'\\#hid*n\n'> <'output\n'> <'expect\n'> 
            <'.gitignore\n'> <'*.7\n'> <'!*.8'>
          )
        }
      ]
      redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<'.git/ignore'>})]
      do_fork: T
    )
    (command.Simple
      words: [{<echo>} {(SQ <'*.1\n'> <'/*.3\n'> <'!*.6'>)}]
      redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<.gitignore>})]
      do_fork: T
    )
    (command.Simple
      words: [{<echo>} {(SQ <'*.2\n'> <'two/*.4\n'> <'!*.7\n'> <'*.8'>)}]
      redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<'one/.gitignore'>})]
      do_fork: T
    )
    (command.Simple
      words: [{<echo>} {(SQ <'!*.2\n'> <'!*.8'>)}]
      redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<'one/two/.gitignore'>})]
      do_fork: T
    )
    (command.ShAssignment
      pairs: [
        (assign_pair
          lhs: (sh_lhs_expr.Name name:allignores)
          op: assign_op.Equal
          rhs: {(SQ <'.gitignore one/.gitignore one/two/.gitignore'>)}
          spids: [193]
        )
      ]
    )
    (C {<test_expect_success>} {(SQ <'git ls-files --others with various exclude options.'>)} 
      {
        (SQ <'git ls-files --others \\\n'> <'       --exclude=\\*.6 \\\n'> 
          <'       --exclude-per-directory=.gitignore \\\n'> <'       --exclude-from=.git/ignore \\\n'> <'       >output &&\n'> <'     test_cmp expect output'>
        )
      }
    )
    (command.Simple
      words: [{<printf>} {(SQ <'*.1\\r\\n/*.3\\r\\n!*.6\\r\\n'>)}]
      redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<.gitignore>})]
      do_fork: T
    )
    (C {<test_expect_success>} {(SQ <'git ls-files --others with \\r\\n line endings.'>)} 
      {
        (SQ <'git ls-files --others \\\n'> <'       --exclude=\\*.6 \\\n'> 
          <'       --exclude-per-directory=.gitignore \\\n'> <'       --exclude-from=.git/ignore \\\n'> <'       >output &&\n'> <'     test_cmp expect output'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'setup skip-worktree gitignore'>)} 
      {
        (SQ <'\n'> <'\tgit add $allignores &&\n'> 
          <'\tgit update-index --skip-worktree $allignores &&\n'> <'\trm $allignores\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'git ls-files --others with various exclude options.'>)} 
      {
        (SQ <'git ls-files --others \\\n'> <'       --exclude=\\*.6 \\\n'> 
          <'       --exclude-per-directory=.gitignore \\\n'> <'       --exclude-from=.git/ignore \\\n'> <'       >output &&\n'> <'     test_cmp expect output'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'restore gitignore'>)} 
      {
        (SQ <'\n'> <'\tgit checkout --ignore-skip-worktree-bits $allignores &&\n'> 
          <'\trm .git/index\n'>
        )
      }
    )
    (command.Simple
      words: [{<cat>}]
      redirects: [
        (redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<excludes-file>})
        (redir
          op: <Id.Redir_DLess '<<'>
          loc: (redir_loc.Fd fd:0)
          arg: 
            (redir_param.MultiLine
              here_begin: {(word_part.EscapedLiteral token:<Id.Lit_EscapedChar '\\E'>) <OF>}
              here_end_span_id: 312
              stdin_parts: [<'*.[1-8]\n'> <'e*\n'> <'\\#*\n'>]
            )
        )
      ]
      do_fork: T
    )
    (C {<git>} {<config>} {<core.excludesFile>} {<excludes-file>})
    (command.Pipeline
      children: [
        (C {<git>} {<-c>} {<status.displayCommentPrefix> <Id.Lit_Equals '='> <true>} {<status>})
        (command.Simple
          words: [{<grep>} {(DQ <'^#\t'>)}]
          redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<output>})]
          do_fork: T
        )
      ]
      negated: F
    )
    (command.Simple
      words: [{<cat>}]
      redirects: [
        (redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<expect>})
        (redir
          op: <Id.Redir_DLess '<<'>
          loc: (redir_loc.Fd fd:0)
          arg: 
            (redir_param.MultiLine
              here_begin: {<EOF>}
              here_end_span_id: 362
              stdin_parts: [
                <'#\t.gitignore\n'>
                <'#\ta.6\n'>
                <'#\tone/\n'>
                <'#\toutput\n'>
                <'#\tthree/\n'>
              ]
            )
        )
      ]
      do_fork: T
    )
    (C {<test_expect_success>} {(SQ <'git status honors core.excludesfile'>)} 
      {(SQ <'test_cmp expect output'>)}
    )
    (C {<test_expect_success>} {(SQ <'trailing slash in exclude allows directory match(1)'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tgit ls-files --others --exclude=one/ >output &&\n'> 
          <'\tif grep "^one/" output\n'> <'\tthen\n'> <'\t\techo Ooops\n'> <'\t\tfalse\n'> <'\telse\n'> <'\t\t: happy\n'> <'\tfi\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'trailing slash in exclude allows directory match (2)'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tgit ls-files --others --exclude=one/two/ >output &&\n'> 
          <'\tif grep "^one/two/" output\n'> <'\tthen\n'> <'\t\techo Ooops\n'> <'\t\tfalse\n'> <'\telse\n'> <'\t\t: happy\n'> <'\tfi\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'trailing slash in exclude forces directory match (1)'>)} 
      {
        (SQ <'\n'> <'\n'> <'\t>two &&\n'> <'\tgit ls-files --others --exclude=two/ >output &&\n'> 
          <'\tgrep "^two" output\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'trailing slash in exclude forces directory match (2)'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tgit ls-files --others --exclude=one/a.1/ >output &&\n'> 
          <'\tgrep "^one/a.1" output\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'negated exclude matches can override previous ones'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tgit ls-files --others --exclude="a.*" --exclude="!a.1" >output &&\n'> 
          <'\tgrep "^a.1" output\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'excluded directory overrides content patterns'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tgit ls-files --others --exclude="one" --exclude="!one/a.1" >output &&\n'> 
          <'\tif grep "^one/a.1" output\n'> <'\tthen\n'> <'\t\tfalse\n'> <'\tfi\n'>
        )
      }
    )
    (C {<test_expect_success>} 
      {(SQ <'negated directory doesn'>) (word_part.EscapedLiteral token:<Id.Lit_EscapedChar '\\\''>) 
        (SQ <'t affect content patterns'>)
      } 
      {
        (SQ <'\n'> <'\n'> <'\tgit ls-files --others --exclude="!one" --exclude="one/a.1" >output &&\n'> 
          <'\tif grep "^one/a.1" output\n'> <'\tthen\n'> <'\t\tfalse\n'> <'\tfi\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'subdirectory ignore (setup)'>)} 
      {
        (SQ <'\n'> <'\tmkdir -p top/l1/l2 &&\n'> <'\t(\n'> <'\t\tcd top &&\n'> <'\t\tgit init &&\n'> 
          <'\t\techo /.gitignore >.gitignore &&\n'> <'\t\techo l1 >>.gitignore &&\n'> <'\t\techo l2 >l1/.gitignore &&\n'> <'\t\t>l1/l2/l1\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'subdirectory ignore (toplevel)'>)} 
      {
        (SQ <'\n'> <'\t(\n'> <'\t\tcd top &&\n'> <'\t\tgit ls-files -o --exclude-standard\n'> 
          <'\t) >actual &&\n'> <'\t>expect &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'subdirectory ignore (l1/l2)'>)} 
      {
        (SQ <'\n'> <'\t(\n'> <'\t\tcd top/l1/l2 &&\n'> <'\t\tgit ls-files -o --exclude-standard\n'> 
          <'\t) >actual &&\n'> <'\t>expect &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'subdirectory ignore (l1)'>)} 
      {
        (SQ <'\n'> <'\t(\n'> <'\t\tcd top/l1 &&\n'> <'\t\tgit ls-files -o --exclude-standard\n'> 
          <'\t) >actual &&\n'> <'\t>expect &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'show/hide empty ignored directory (setup)'>)} 
      {(SQ <'\n'> <'\trm top/l1/l2/l1 &&\n'> <'\trm top/l1/.gitignore\n'>)}
    )
    (C {<test_expect_success>} {(SQ <'show empty ignored directory with --directory'>)} 
      {
        (SQ <'\n'> <'\t(\n'> <'\t\tcd top &&\n'> <'\t\tgit ls-files -o -i --exclude l1 --directory\n'> 
          <'\t) >actual &&\n'> <'\techo l1/ >expect &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'hide empty ignored directory with --no-empty-directory'>)} 
      {
        (SQ <'\n'> <'\t(\n'> <'\t\tcd top &&\n'> 
          <'\t\tgit ls-files -o -i --exclude l1 --directory --no-empty-directory\n'> <'\t) >actual &&\n'> <'\t>expect &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'show/hide empty ignored sub-directory (setup)'>)} 
      {
        (SQ <'\n'> <'\t> top/l1/tracked &&\n'> <'\t(\n'> <'\t\tcd top &&\n'> 
          <'\t\tgit add -f l1/tracked\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'show empty ignored sub-directory with --directory'>)} 
      {
        (SQ <'\n'> <'\t(\n'> <'\t\tcd top &&\n'> <'\t\tgit ls-files -o -i --exclude l1 --directory\n'> 
          <'\t) >actual &&\n'> <'\techo l1/l2/ >expect &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'hide empty ignored sub-directory with --no-empty-directory'>)} 
      {
        (SQ <'\n'> <'\t(\n'> <'\t\tcd top &&\n'> 
          <'\t\tgit ls-files -o -i --exclude l1 --directory --no-empty-directory\n'> <'\t) >actual &&\n'> <'\t>expect &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'pattern matches prefix completely'>)} 
      {
        (SQ <'\n'> <'\t: >expect &&\n'> 
          <'\tgit ls-files -i -o --exclude "/three/a.3[abc]" >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'ls-files with "**" patterns'>)} 
      {
        (SQ <'\n'> <'\tcat <<\\EOF >expect &&\n'> <'a.1\n'> <'one/a.1\n'> <'one/two/a.1\n'> 
          <'three/a.1\n'> <'EOF\n'> <'\tgit ls-files -o -i --exclude "**/a.1" >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'ls-files with "**" patterns and no slashes'>)} 
      {
        (SQ <'\n'> <'\t: >expect &&\n'> <'\tgit ls-files -o -i --exclude "one**a.1" >actual &&\n'> 
          <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_done>})
  ]
)