(CommandList
  children: [
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:test_description)
          op: Equal
          rhs: {(gitattributes)}
          spids: [4]
        )
      ]
      spids: [4]
    )
    (C {(.)} {(./test-lib.sh)})
    (FuncDef
      name: attr_check
      body: 
        (BraceGroup
          children: [
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:path)
                  op: Equal
                  rhs: {(DQ ($ VSub_Number "$1"))}
                  spids: [21]
                )
                (assign_pair
                  lhs: (LhsName name:expect)
                  op: Equal
                  rhs: {(DQ ($ VSub_Number "$2"))}
                  spids: [26]
                )
              ]
              spids: [21]
            )
            (AndOr
              children: [
                (SimpleCommand
                  words: [
                    {(git)}
                    {($ VSub_Number "$3")}
                    {(check-attr)}
                    {(test)}
                    {(--)}
                    {(DQ ($ VSub_Name "$path"))}
                  ]
                  redirects: [
                    (Redir
                      op_id: Redir_Great
                      fd: -1
                      arg_word: {(actual)}
                      spids: [47]
                    )
                    (Redir op_id:Redir_Great fd:2 arg_word:{(err)} spids:[50])
                  ]
                )
                (AndOr
                  children: [
                    (SimpleCommand
                      words: [{(echo)} {(DQ ($ VSub_Name "$path") (": test: ") ($ VSub_Number "$2"))}]
                      redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(expect)} spids:[64])]
                    )
                    (AndOr
                      children: [
                        (C {(test_cmp)} {(expect)} {(actual)})
                        (C {(test_line_count)} {(Lit_Other "=")} {(0)} {(err)})
                      ]
                      op_id: Op_DAmp
                    )
                  ]
                  op_id: Op_DAmp
                )
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [18]
        )
      spids: [13 17]
    )
    (C {(test_expect_success)} {(SQ <setup>)} 
      {
        (SQ <"\n"> <"\tmkdir -p a/b/d a/c b &&\n"> <"\t(\n"> <"\t\techo \"[attr]notest !test\"\n"> 
          <"\t\techo \"f\ttest=f\"\n"> <"\t\techo \"a/i test=a/i\"\n"> <"\t\techo \"onoff test -test\"\n"> <"\t\techo \"offon -test test\"\n"> 
          <"\t\techo \"no notest\"\n"> <"\t\techo \"A/e/F test=A/e/F\"\n"> <"\t) >.gitattributes &&\n"> <"\t(\n"> 
          <"\t\techo \"g test=a/g\" &&\n"> <"\t\techo \"b/g test=a/b/g\"\n"> <"\t) >a/.gitattributes &&\n"> <"\t(\n"> 
          <"\t\techo \"h test=a/b/h\" &&\n"> <"\t\techo \"d/* test=a/b/d/*\"\n"> <"\t\techo \"d/yes notest\"\n"> <"\t) >a/b/.gitattributes &&\n"> 
          <"\t(\n"> <"\t\techo \"global test=global\"\n"> <"\t) >\"$HOME\"/global-gitattributes &&\n"> 
          <"\tcat <<-EOF >expect-all\n"> <"\tf: test: f\n"> <"\ta/f: test: f\n"> <"\ta/c/f: test: f\n"> <"\ta/g: test: a/g\n"> 
          <"\ta/b/g: test: a/b/g\n"> <"\tb/g: test: unspecified\n"> <"\ta/b/h: test: a/b/h\n"> <"\ta/b/d/g: test: a/b/d/*\n"> 
          <"\tonoff: test: unset\n"> <"\toffon: test: set\n"> <"\tno: notest: set\n"> <"\tno: test: unspecified\n"> 
          <"\ta/b/d/no: notest: set\n"> <"\ta/b/d/no: test: a/b/d/*\n"> <"\ta/b/d/yes: notest: set\n"> <"\ta/b/d/yes: test: unspecified\n"> 
          <"\tEOF\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"command line checks">)} 
      {
        (SQ <"\n"> <"\ttest_must_fail git check-attr &&\n"> <"\ttest_must_fail git check-attr -- &&\n"> 
          <"\ttest_must_fail git check-attr test &&\n"> <"\ttest_must_fail git check-attr test -- &&\n"> <"\ttest_must_fail git check-attr -- f &&\n"> 
          <"\techo \"f\" | test_must_fail git check-attr --stdin &&\n"> <"\techo \"f\" | test_must_fail git check-attr --stdin -- f &&\n"> 
          <"\techo \"f\" | test_must_fail git check-attr --stdin test -- f &&\n"> <"\ttest_must_fail git check-attr \"\" -- f\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"attribute test">)} 
      {
        (SQ <"\n"> <"\tattr_check f f &&\n"> <"\tattr_check a/f f &&\n"> <"\tattr_check a/c/f f &&\n"> 
          <"\tattr_check a/g a/g &&\n"> <"\tattr_check a/b/g a/b/g &&\n"> <"\tattr_check b/g unspecified &&\n"> 
          <"\tattr_check a/b/h a/b/h &&\n"> <"\tattr_check a/b/d/g \"a/b/d/*\" &&\n"> <"\tattr_check onoff unset &&\n"> 
          <"\tattr_check offon set &&\n"> <"\tattr_check no unspecified &&\n"> <"\tattr_check a/b/d/no \"a/b/d/*\" &&\n"> 
          <"\tattr_check a/b/d/yes unspecified\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"attribute matching is case sensitive when core.ignorecase=0">)} 
      {
        (SQ <"\n"> <"\n"> <"\ttest_must_fail attr_check F f \"-c core.ignorecase=0\" &&\n"> 
          <"\ttest_must_fail attr_check a/F f \"-c core.ignorecase=0\" &&\n"> <"\ttest_must_fail attr_check a/c/F f \"-c core.ignorecase=0\" &&\n"> 
          <"\ttest_must_fail attr_check a/G a/g \"-c core.ignorecase=0\" &&\n"> <"\ttest_must_fail attr_check a/B/g a/b/g \"-c core.ignorecase=0\" &&\n"> 
          <"\ttest_must_fail attr_check a/b/G a/b/g \"-c core.ignorecase=0\" &&\n"> <"\ttest_must_fail attr_check a/b/H a/b/h \"-c core.ignorecase=0\" &&\n"> 
          <"\ttest_must_fail attr_check a/b/D/g \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n"> <"\ttest_must_fail attr_check oNoFf unset \"-c core.ignorecase=0\" &&\n"> 
          <"\ttest_must_fail attr_check oFfOn set \"-c core.ignorecase=0\" &&\n"> <"\tattr_check NO unspecified \"-c core.ignorecase=0\" &&\n"> 
          <"\ttest_must_fail attr_check a/b/D/NO \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n"> <"\tattr_check a/b/d/YES a/b/d/* \"-c core.ignorecase=0\" &&\n"> 
          <"\ttest_must_fail attr_check a/E/f \"A/e/F\" \"-c core.ignorecase=0\"\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"attribute matching is case insensitive when core.ignorecase=1">)} 
      {
        (SQ <"\n"> <"\n"> <"\tattr_check F f \"-c core.ignorecase=1\" &&\n"> 
          <"\tattr_check a/F f \"-c core.ignorecase=1\" &&\n"> <"\tattr_check a/c/F f \"-c core.ignorecase=1\" &&\n"> 
          <"\tattr_check a/G a/g \"-c core.ignorecase=1\" &&\n"> <"\tattr_check a/B/g a/b/g \"-c core.ignorecase=1\" &&\n"> 
          <"\tattr_check a/b/G a/b/g \"-c core.ignorecase=1\" &&\n"> <"\tattr_check a/b/H a/b/h \"-c core.ignorecase=1\" &&\n"> 
          <"\tattr_check a/b/D/g \"a/b/d/*\" \"-c core.ignorecase=1\" &&\n"> <"\tattr_check oNoFf unset \"-c core.ignorecase=1\" &&\n"> 
          <"\tattr_check oFfOn set \"-c core.ignorecase=1\" &&\n"> <"\tattr_check NO unspecified \"-c core.ignorecase=1\" &&\n"> 
          <"\tattr_check a/b/D/NO \"a/b/d/*\" \"-c core.ignorecase=1\" &&\n"> <"\tattr_check a/b/d/YES unspecified \"-c core.ignorecase=1\" &&\n"> 
          <"\tattr_check a/E/f \"A/e/F\" \"-c core.ignorecase=1\"\n"> <"\n">
        )
      }
    )
    (C {(test_expect_success)} {(CASE_INSENSITIVE_FS)} {(SQ <"additional case insensitivity tests">)} 
      {
        (SQ <"\n"> <"\ttest_must_fail attr_check a/B/D/g \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n"> 
          <"\ttest_must_fail attr_check A/B/D/NO \"a/b/d/*\" \"-c core.ignorecase=0\" &&\n"> <"\tattr_check A/b/h a/b/h \"-c core.ignorecase=1\" &&\n"> 
          <"\tattr_check a/B/D/g \"a/b/d/*\" \"-c core.ignorecase=1\" &&\n"> <"\tattr_check A/B/D/NO \"a/b/d/*\" \"-c core.ignorecase=1\"\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"unnormalized paths">)} 
      {
        (SQ <"\n"> <"\tattr_check ./f f &&\n"> <"\tattr_check ./a/g a/g &&\n"> 
          <"\tattr_check a/./g a/g &&\n"> <"\tattr_check a/c/../b/g a/b/g\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"relative paths">)} 
      {
        (SQ <"\n"> <"\t(cd a && attr_check ../f f) &&\n"> <"\t(cd a && attr_check f f) &&\n"> 
          <"\t(cd a && attr_check i a/i) &&\n"> <"\t(cd a && attr_check g a/g) &&\n"> <"\t(cd a && attr_check b/g a/b/g) &&\n"> 
          <"\t(cd b && attr_check ../a/f f) &&\n"> <"\t(cd b && attr_check ../a/g a/g) &&\n"> <"\t(cd b && attr_check ../a/b/g a/b/g)\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"prefixes are not confused with leading directories">)} 
      {
        (SQ <"\n"> <"\tattr_check a_plus/g unspecified &&\n"> <"\tcat >expect <<-\\EOF &&\n"> 
          <"\ta/g: test: a/g\n"> <"\ta_plus/g: test: unspecified\n"> <"\tEOF\n"> <"\tgit check-attr test a/g a_plus/g >actual &&\n"> 
          <"\ttest_cmp expect actual\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <core.attributesfile>)} 
      {
        (SQ <"\n"> <"\tattr_check global unspecified &&\n"> 
          <"\tgit config core.attributesfile \"$HOME/global-gitattributes\" &&\n"> <"\tattr_check global global &&\n"> 
          <"\tgit config core.attributesfile \"~/global-gitattributes\" &&\n"> <"\tattr_check global global &&\n"> <"\techo \"global test=precedence\" >>.gitattributes &&\n"> 
          <"\tattr_check global precedence\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"attribute test: read paths from stdin">)} 
      {
        (SQ <"\n"> <"\tgrep -v notest <expect-all >expect &&\n"> 
          <"\tsed -e \"s/:.*//\" <expect | git check-attr --stdin test >actual &&\n"> <"\ttest_cmp expect actual\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"attribute test: --all option">)} 
      {
        (SQ <"\n"> <"\tgrep -v unspecified <expect-all | sort >specified-all &&\n"> 
          <"\tsed -e \"s/:.*//\" <expect-all | uniq >stdin-all &&\n"> <"\tgit check-attr --stdin --all <stdin-all | sort >actual &&\n"> 
          <"\ttest_cmp specified-all actual\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"attribute test: --cached option">)} 
      {
        (SQ <"\n"> <"\t: >empty &&\n"> 
          <"\tgit check-attr --cached --stdin --all <stdin-all | sort >actual &&\n"> <"\ttest_cmp empty actual &&\n"> <"\tgit add .gitattributes a/.gitattributes a/b/.gitattributes &&\n"> 
          <"\tgit check-attr --cached --stdin --all <stdin-all | sort >actual &&\n"> <"\ttest_cmp specified-all actual\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"root subdir attribute test">)} 
      {(SQ <"\n"> <"\tattr_check a/i a/i &&\n"> <"\tattr_check subdir/a/i unspecified\n">)}
    )
    (C {(test_expect_success)} {(SQ <"negative patterns">)} 
      {(SQ <"\n"> <"\techo \"!f test=bar\" >.gitattributes &&\n"> <"\tgit check-attr test -- ">) 
        (DQ ("'")) (SQ <"!f">) (DQ ("'")) 
        (SQ <" 2>errors &&\n"> <"\ttest_i18ngrep \"Negative patterns are ignored\" errors\n">)
      }
    )
    (C {(test_expect_success)} {(SQ <"patterns starting with exclamation">)} 
      {(SQ <"\n"> <"\techo \"\\!f test=foo\" >.gitattributes &&\n"> <"\tattr_check \"!f\" foo\n">)}
    )
    (C {(test_expect_success)} {(SQ <"\"**\" test">)} 
      {
        (SQ <"\n"> <"\techo \"**/f foo=bar\" >.gitattributes &&\n"> <"\tcat <<\\EOF >expect &&\n"> 
          <"f: foo: bar\n"> <"a/f: foo: bar\n"> <"a/b/f: foo: bar\n"> <"a/b/c/f: foo: bar\n"> <"EOF\n"> 
          <"\tgit check-attr foo -- \"f\" >actual 2>err &&\n"> <"\tgit check-attr foo -- \"a/f\" >>actual 2>>err &&\n"> 
          <"\tgit check-attr foo -- \"a/b/f\" >>actual 2>>err &&\n"> <"\tgit check-attr foo -- \"a/b/c/f\" >>actual 2>>err &&\n"> <"\ttest_cmp expect actual &&\n"> 
          <"\ttest_line_count = 0 err\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"\"**\" with no slashes test">)} 
      {
        (SQ <"\n"> <"\techo \"a**f foo=bar\" >.gitattributes &&\n"> 
          <"\tgit check-attr foo -- \"f\" >actual &&\n"> <"\tcat <<\\EOF >expect &&\n"> <"f: foo: unspecified\n"> <"af: foo: bar\n"> <"axf: foo: bar\n"> 
          <"a/f: foo: unspecified\n"> <"a/b/f: foo: unspecified\n"> <"a/b/c/f: foo: unspecified\n"> <"EOF\n"> 
          <"\tgit check-attr foo -- \"f\" >actual 2>err &&\n"> <"\tgit check-attr foo -- \"af\" >>actual 2>err &&\n"> 
          <"\tgit check-attr foo -- \"axf\" >>actual 2>err &&\n"> <"\tgit check-attr foo -- \"a/f\" >>actual 2>>err &&\n"> 
          <"\tgit check-attr foo -- \"a/b/f\" >>actual 2>>err &&\n"> <"\tgit check-attr foo -- \"a/b/c/f\" >>actual 2>>err &&\n"> <"\ttest_cmp expect actual &&\n"> 
          <"\ttest_line_count = 0 err\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"using --git-dir and --work-tree">)} 
      {
        (SQ <"\n"> <"\tmkdir unreal real &&\n"> <"\tgit init real &&\n"> 
          <"\techo \"file test=in-real\" >real/.gitattributes &&\n"> <"\t(\n"> <"\t\tcd unreal &&\n"> 
          <"\t\tattr_check file in-real \"--git-dir ../real/.git --work-tree ../real\"\n"> <"\t)\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"setup bare">)} {(SQ <"\n"> <"\tgit clone --bare . bare.git\n">)})
    (C {(test_expect_success)} {(SQ <"bare repository: check that .gitattribute is ignored">)} 
      {
        (SQ <"\n"> <"\t(\n"> <"\t\tcd bare.git &&\n"> <"\t\t(\n"> <"\t\t\techo \"f\ttest=f\"\n"> 
          <"\t\t\techo \"a/i test=a/i\"\n"> <"\t\t) >.gitattributes &&\n"> <"\t\tattr_check f unspecified &&\n"> 
          <"\t\tattr_check a/f unspecified &&\n"> <"\t\tattr_check a/c/f unspecified &&\n"> <"\t\tattr_check a/i unspecified &&\n"> 
          <"\t\tattr_check subdir/a/i unspecified\n"> <"\t)\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"bare repository: check that --cached honors index">)} 
      {
        (SQ <"\n"> <"\t(\n"> <"\t\tcd bare.git &&\n"> <"\t\tGIT_INDEX_FILE=../.git/index \\\n"> 
          <"\t\tgit check-attr --cached --stdin --all <../stdin-all |\n"> <"\t\tsort >actual &&\n"> <"\t\ttest_cmp ../specified-all actual\n"> <"\t)\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"bare repository: test info/attributes">)} 
      {
        (SQ <"\n"> <"\t(\n"> <"\t\tcd bare.git &&\n"> <"\t\t(\n"> <"\t\t\techo \"f\ttest=f\"\n"> 
          <"\t\t\techo \"a/i test=a/i\"\n"> <"\t\t) >info/attributes &&\n"> <"\t\tattr_check f f &&\n"> <"\t\tattr_check a/f f &&\n"> 
          <"\t\tattr_check a/c/f f &&\n"> <"\t\tattr_check a/i a/i &&\n"> <"\t\tattr_check subdir/a/i unspecified\n"> <"\t)\n">
        )
      }
    )
    (C {(test_done)})
  ]
)