(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: 16777215
          body: 
            {
              (DQ ('#!') ($ VSub_Name '$SHELL_PATH') ('\n') ('tr ') 
                ("  'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ") ("  'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'\n")
              )
            }
          do_expansion: True
          here_end: EOF
          was_filled: T
          spids: [17]
        )
        (Redir op_id:Redir_Great fd:16777215 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: [76]
        )
      ]
      spids: [76]
    )
    (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)})
  ]
)