(CommandList
  children: [
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:test_description)
          op: Equal
          rhs: {(SQ <"blob conversion via gitattributes">)}
          spids: [4]
        )
      ]
      spids: [4]
    )
    (C {(.)} {(./test-lib.sh)})
    (SimpleCommand
      words: [{(cat)}]
      redirects: [
        (HereDoc
          op_id: Redir_DLess
          fd: -1
          body: 
            {
              (DQ ("#!") ($ VSub_Name "$SHELL_PATH") ("\n") ("tr ") 
                ("  'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ") ("  'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'\n")
              )
            }
          do_expansion: True
          here_end: EOF
          was_filled: True
          spids: [17]
        )
        (Redir op_id:Redir_Great fd:-1 arg_word:{(rot13.sh)} spids:[20])
      ]
    )
    (C {(chmod)} {(Lit_Other "+") (x)} {(rot13.sh)})
    (C {(test_expect_success)} {(setup)} 
      {
        (SQ <"\n"> <"\tgit config filter.rot13.smudge ./rot13.sh &&\n"> 
          <"\tgit config filter.rot13.clean ./rot13.sh &&\n"> <"\n"> <"\t{\n"> <"\t    echo \"*.t filter=rot13\"\n"> <"\t    echo \"*.i ident\"\n"> 
          <"\t} >.gitattributes &&\n"> <"\n"> <"\t{\n"> <"\t    echo a b c d e f g h i j k l m\n"> <"\t    echo n o p q r s t u v w x y z\n"> 
          <"\t    echo ">
        ) (EscapedLiteralPart token:<Lit_EscapedChar "\\'">) (SQ <"$Id$">) 
        (EscapedLiteralPart token:<Lit_EscapedChar "\\'">) 
        (SQ <"\n"> <"\t} >test &&\n"> <"\tcat test >test.t &&\n"> <"\tcat test >test.o &&\n"> 
          <"\tcat test >test.i &&\n"> <"\tgit add test test.t test.i &&\n"> <"\trm -f test test.t test.i &&\n"> 
          <"\tgit checkout -- test test.t test.i\n">
        )
      }
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:script)
          op: Equal
          rhs: {(SQ <"s/^\\$Id: \\([0-9a-f]*\\) \\$/\\1/p">)}
          spids: [75]
        )
      ]
      spids: [75]
    )
    (C {(test_expect_success)} {(check)} 
      {
        (SQ <"\n"> <"\n"> <"\tcmp test.o test &&\n"> <"\tcmp test.o test.t &&\n"> <"\n"> 
          <"\t# ident should be stripped in the repository\n"> <"\tgit diff --raw --exit-code :test :test.i &&\n"> <"\tid=$(git rev-parse --verify :test) &&\n"> 
          <"\tembedded=$(sed -ne \"$script\" test.i) &&\n"> <"\ttest \"z$id\" = \"z$embedded\" &&\n"> <"\n"> <"\tgit cat-file blob :test.t > test.r &&\n"> <"\n"> 
          <"\t./rot13.sh < test.o > test.t &&\n"> <"\tcmp test.r test.t\n">
        )
      }
    )
    (C {(test_expect_success)} {(expanded_in_repo)} 
      {
        (SQ <"\n"> <"\t{\n"> <"\t\techo \"File with expanded keywords\"\n"> <"\t\techo \"\\$Id\\$\"\n"> 
          <"\t\techo \"\\$Id:\\$\"\n"> <"\t\techo \"\\$Id: 0000000000000000000000000000000000000000 \\$\"\n"> 
          <"\t\techo \"\\$Id: NoSpaceAtEnd\\$\"\n"> <"\t\techo \"\\$Id:NoSpaceAtFront \\$\"\n"> <"\t\techo \"\\$Id:NoSpaceAtEitherEnd\\$\"\n"> 
          <"\t\techo \"\\$Id: NoTerminatingSymbol\"\n"> <"\t\techo \"\\$Id: Foreign Commit With Spaces \\$\"\n"> <"\t} >expanded-keywords.0 &&\n"> <"\n"> 
          <"\t{\n"> <"\t\tcat expanded-keywords.0 &&\n"> <"\t\tprintf \"\\$Id: NoTerminatingSymbolAtEOF\"\n"> 
          <"\t} >expanded-keywords &&\n"> <"\tcat expanded-keywords >expanded-keywords-crlf &&\n"> 
          <"\tgit add expanded-keywords expanded-keywords-crlf &&\n"> <"\tgit commit -m \"File with keywords expanded\" &&\n"> 
          <"\tid=$(git rev-parse --verify :expanded-keywords) &&\n"> <"\n"> <"\t{\n"> <"\t\techo \"File with expanded keywords\"\n"> <"\t\techo \"\\$Id: $id \\$\"\n"> 
          <"\t\techo \"\\$Id: $id \\$\"\n"> <"\t\techo \"\\$Id: $id \\$\"\n"> <"\t\techo \"\\$Id: $id \\$\"\n"> <"\t\techo \"\\$Id: $id \\$\"\n"> 
          <"\t\techo \"\\$Id: $id \\$\"\n"> <"\t\techo \"\\$Id: NoTerminatingSymbol\"\n"> <"\t\techo \"\\$Id: Foreign Commit With Spaces \\$\"\n"> 
          <"\t} >expected-output.0 &&\n"> <"\t{\n"> <"\t\tcat expected-output.0 &&\n"> <"\t\tprintf \"\\$Id: NoTerminatingSymbolAtEOF\"\n"> 
          <"\t} >expected-output &&\n"> <"\t{\n"> <"\t\tappend_cr <expected-output.0 &&\n"> 
          <"\t\tprintf \"\\$Id: NoTerminatingSymbolAtEOF\"\n"> <"\t} >expected-output-crlf &&\n"> <"\t{\n"> <"\t\techo \"expanded-keywords ident\"\n"> 
          <"\t\techo \"expanded-keywords-crlf ident text eol=crlf\"\n"> <"\t} >>.gitattributes &&\n"> <"\n"> <"\trm -f expanded-keywords expanded-keywords-crlf &&\n"> <"\n"> 
          <"\tgit checkout -- expanded-keywords &&\n"> <"\ttest_cmp expanded-keywords expected-output &&\n"> <"\n"> 
          <"\tgit checkout -- expanded-keywords-crlf &&\n"> <"\ttest_cmp expanded-keywords-crlf expected-output-crlf\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"filter shell-escaped filenames">)} 
      {
        (SQ <"\n"> <"\tcat >argc.sh <<-EOF &&\n"> <"\t#!$SHELL_PATH\n"> <"\tcat >/dev/null\n"> 
          <"\techo argc: \\$# \"\\$@\"\n"> <"\tEOF\n"> <"\tnormal=name-no-magic &&\n"> <"\tspecial=\"name  with ">
        ) (EscapedLiteralPart token:<Lit_EscapedChar "\\'">) (SQ <sq>) 
        (EscapedLiteralPart token:<Lit_EscapedChar "\\'">) 
        (SQ <" and \\$x\" &&\n"> <"\techo some test text >\"$normal\" &&\n"> 
          <"\techo some test text >\"$special\" &&\n"> <"\tgit add \"$normal\" \"$special\" &&\n"> <"\tgit commit -q -m \"add files\" &&\n"> 
          <"\techo \"name* filter=argc\" >.gitattributes &&\n"> <"\n"> <"\t# delete the files and check them out again, using a smudge filter\n"> 
          <"\t# that will count the args and echo the command-line back to us\n"> <"\tgit config filter.argc.smudge \"sh ./argc.sh %f\" &&\n"> <"\trm \"$normal\" \"$special\" &&\n"> 
          <"\tgit checkout -- \"$normal\" \"$special\" &&\n"> <"\n"> <"\t# make sure argc.sh counted the right number of args\n"> 
          <"\techo \"argc: 1 $normal\" >expect &&\n"> <"\ttest_cmp expect \"$normal\" &&\n"> <"\techo \"argc: 1 $special\" >expect &&\n"> 
          <"\ttest_cmp expect \"$special\" &&\n"> <"\n"> <"\t# do the same thing, but with more args in the filter expression\n"> 
          <"\tgit config filter.argc.smudge \"sh ./argc.sh %f --my-extra-arg\" &&\n"> <"\trm \"$normal\" \"$special\" &&\n"> <"\tgit checkout -- \"$normal\" \"$special\" &&\n"> <"\n"> 
          <"\t# make sure argc.sh counted the right number of args\n"> <"\techo \"argc: 2 $normal --my-extra-arg\" >expect &&\n"> <"\ttest_cmp expect \"$normal\" &&\n"> 
          <"\techo \"argc: 2 $special --my-extra-arg\" >expect &&\n"> <"\ttest_cmp expect \"$special\" &&\n"> <"\t:\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"required filter should filter data">)} 
      {
        (SQ <"\n"> <"\tgit config filter.required.smudge ./rot13.sh &&\n"> 
          <"\tgit config filter.required.clean ./rot13.sh &&\n"> <"\tgit config filter.required.required true &&\n"> <"\n"> 
          <"\techo \"*.r filter=required\" >.gitattributes &&\n"> <"\n"> <"\tcat test.o >test.r &&\n"> <"\tgit add test.r &&\n"> <"\n"> <"\trm -f test.r &&\n"> 
          <"\tgit checkout -- test.r &&\n"> <"\tcmp test.o test.r &&\n"> <"\n"> <"\t./rot13.sh <test.o >expected &&\n"> 
          <"\tgit cat-file blob :test.r >actual &&\n"> <"\tcmp expected actual\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"required filter smudge failure">)} 
      {
        (SQ <"\n"> <"\tgit config filter.failsmudge.smudge false &&\n"> 
          <"\tgit config filter.failsmudge.clean cat &&\n"> <"\tgit config filter.failsmudge.required true &&\n"> <"\n"> 
          <"\techo \"*.fs filter=failsmudge\" >.gitattributes &&\n"> <"\n"> <"\techo test >test.fs &&\n"> <"\tgit add test.fs &&\n"> <"\trm -f test.fs &&\n"> 
          <"\ttest_must_fail git checkout -- test.fs\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"required filter clean failure">)} 
      {
        (SQ <"\n"> <"\tgit config filter.failclean.smudge cat &&\n"> 
          <"\tgit config filter.failclean.clean false &&\n"> <"\tgit config filter.failclean.required true &&\n"> <"\n"> 
          <"\techo \"*.fc filter=failclean\" >.gitattributes &&\n"> <"\n"> <"\techo test >test.fc &&\n"> <"\ttest_must_fail git add test.fc\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"filtering large input to small output should use little memory">)} 
      {
        (SQ <"\n"> <"\tgit config filter.devnull.clean \"cat >/dev/null\" &&\n"> 
          <"\tgit config filter.devnull.required true &&\n"> <"\tfor i in $(test_seq 1 30); do printf \"%1048576d\" 1; done >30MB &&\n"> 
          <"\techo \"30MB filter=devnull\" >.gitattributes &&\n"> <"\tGIT_MMAP_LIMIT=1m GIT_ALLOC_LIMIT=1m git add 30MB\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"filter that does not read is fine">)} 
      {
        (SQ <"\n"> <"\ttest-genrandom foo $((128 * 1024 + 1)) >big &&\n"> 
          <"\techo \"big filter=epipe\" >.gitattributes &&\n"> <"\tgit config filter.epipe.clean \"echo xyzzy\" &&\n"> <"\tgit add big &&\n"> 
          <"\tgit cat-file blob :big >actual &&\n"> <"\techo xyzzy >expect &&\n"> <"\ttest_cmp expect actual\n">
        )
      }
    )
    (C {(test_expect_success)} {(EXPENSIVE)} {(SQ <"filter large file">)} 
      {
        (SQ <"\n"> <"\tgit config filter.largefile.smudge cat &&\n"> 
          <"\tgit config filter.largefile.clean cat &&\n"> <"\tfor i in $(test_seq 1 2048); do printf \"%1048576d\" 1; done >2GB &&\n"> 
          <"\techo \"2GB filter=largefile\" >.gitattributes &&\n"> <"\tgit add 2GB 2>err &&\n"> <"\t! test -s err &&\n"> <"\trm -f 2GB &&\n"> 
          <"\tgit checkout -- 2GB 2>err &&\n"> <"\t! test -s err\n">
        )
      }
    )
    (C {(test_expect_success)} {(DQ ("filter: clean empty file"))} 
      {
        (SQ <"\n"> <"\tgit config filter.in-repo-header.clean  \"echo cleaned && cat\" &&\n"> 
          <"\tgit config filter.in-repo-header.smudge \"sed 1d\" &&\n"> <"\n"> <"\techo \"empty-in-worktree    filter=in-repo-header\" >>.gitattributes &&\n"> 
          <"\t>empty-in-worktree &&\n"> <"\n"> <"\techo cleaned >expected &&\n"> <"\tgit add empty-in-worktree &&\n"> 
          <"\tgit show :empty-in-worktree >actual &&\n"> <"\ttest_cmp expected actual\n">
        )
      }
    )
    (C {(test_expect_success)} {(DQ ("filter: smudge empty file"))} 
      {
        (SQ <"\n"> <"\tgit config filter.empty-in-repo.clean \"cat >/dev/null\" &&\n"> 
          <"\tgit config filter.empty-in-repo.smudge \"echo smudged && cat\" &&\n"> <"\n"> <"\techo \"empty-in-repo filter=empty-in-repo\" >>.gitattributes &&\n"> 
          <"\techo dead data walking >empty-in-repo &&\n"> <"\tgit add empty-in-repo &&\n"> <"\n"> <"\techo smudged >expected &&\n"> 
          <"\tgit checkout-index --prefix=filtered- empty-in-repo &&\n"> <"\ttest_cmp expected filtered-empty-in-repo\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"disable filter with empty override">)} 
      {
        (SQ <"\n"> <"\ttest_config_global filter.disable.smudge false &&\n"> 
          <"\ttest_config_global filter.disable.clean false &&\n"> <"\ttest_config filter.disable.smudge false &&\n"> <"\ttest_config filter.disable.clean false &&\n"> 
          <"\n"> <"\techo \"*.disable filter=disable\" >.gitattributes &&\n"> <"\n"> <"\techo test >test.disable &&\n"> 
          <"\tgit -c filter.disable.clean= add test.disable 2>err &&\n"> <"\ttest_must_be_empty err &&\n"> <"\trm -f test.disable &&\n"> 
          <"\tgit -c filter.disable.smudge= checkout -- test.disable 2>err &&\n"> <"\ttest_must_be_empty err\n">
        )
      }
    )
    (C {(test_expect_success)} {(SQ <"diff does not reuse worktree files that need cleaning">)} 
      {
        (SQ <"\n"> <"\ttest_config filter.counter.clean \"echo . >>count; sed s/^/clean:/\" &&\n"> 
          <"\techo \"file filter=counter\" >.gitattributes &&\n"> <"\ttest_commit one file &&\n"> <"\ttest_commit two file &&\n"> <"\n"> <"\t>count &&\n"> 
          <"\tgit diff-tree -p HEAD &&\n"> <"\ttest_line_count = 0 count\n">
        )
      }
    )
    (C {(test_done)})
  ]
)