(CommandList
  children: [
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:test_description)
          op: Equal
          rhs: {(SQ <'git cat-file'>)}
          spids: [4]
        )
      ]
      spids: [4]
    )
    (C {(.)} {(./test-lib.sh)})
    (FuncDef
      name: echo_without_newline
      body: (BraceGroup children:[(C {(printf)} {(SQ <'%s'>)} {(DQ ($ VSub_Star '$*'))})] spids:[20])
      spids: [15 19]
    )
    (FuncDef
      name: strlen
      body: 
        (BraceGroup
          children: [
            (Pipeline
              children: [
                (C {(echo_without_newline)} {(DQ ($ VSub_Number '$1'))})
                (C {(wc)} {(-c)})
                (C {(sed)} {(-e)} {(SQ <'s/^ *//'>)})
              ]
              negated: False
            )
          ]
          spids: [41]
        )
      spids: [36 40]
    )
    (FuncDef
      name: maybe_remove_timestamp
      body: 
        (BraceGroup
          children: [
            (If
              arms: [
                (if_arm
                  cond: [
                    (Sentence
                      child: (C {(test)} {(-z)} {(DQ ($ VSub_Number '$2'))})
                      terminator: <Op_Semi ';'>
                    )
                  ]
                  action: [(C {(echo_without_newline)} {(DQ ($ VSub_Number '$1'))})]
                  spids: [-1 88]
                )
              ]
              else_action: [
                (C {(echo_without_newline)} 
                  {
                    (DQ 
                      (CommandSubPart
                        command_list: 
                          (CommandList
                            children: [
                              (Pipeline
                                children: [
                                  (C {(printf)} {(SQ <'%s\\n'>)} {(DQ ($ VSub_Number '$1'))})
                                  (C {(sed)} {(-e)} {(SQ <'s/ [0-9][0-9]* [-+][0-9][0-9][0-9][0-9]$//'>)})
                                ]
                                negated: False
                              )
                            ]
                          )
                        left_token: <Left_CommandSub '$('>
                        spids: [104 124]
                      )
                    )
                  }
                )
              ]
              spids: [98 128]
            )
          ]
          spids: [74]
        )
      spids: [69 73]
    )
    (FuncDef
      name: run_tests
      body: 
        (BraceGroup
          children: [
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:type)
                  op: Equal
                  rhs: {($ VSub_Number '$1')}
                  spids: [141]
                )
              ]
              spids: [141]
            )
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:sha1)
                  op: Equal
                  rhs: {($ VSub_Number '$2')}
                  spids: [145]
                )
              ]
              spids: [145]
            )
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:size)
                  op: Equal
                  rhs: {($ VSub_Number '$3')}
                  spids: [149]
                )
              ]
              spids: [149]
            )
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:content)
                  op: Equal
                  rhs: {($ VSub_Number '$4')}
                  spids: [153]
                )
              ]
              spids: [153]
            )
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:pretty_content)
                  op: Equal
                  rhs: {($ VSub_Number '$5')}
                  spids: [157]
                )
              ]
              spids: [157]
            )
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:no_ts)
                  op: Equal
                  rhs: {($ VSub_Number '$6')}
                  spids: [161]
                )
              ]
              spids: [161]
            )
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:batch_output)
                  op: Equal
                  rhs: 
                    {
                      (DQ ($ VSub_Name '$sha1') (' ') ($ VSub_Name '$type') (' ') ($ VSub_Name '$size') 
                        ('\n') ($ VSub_Name '$content')
                      )
                    }
                  spids: [166]
                )
              ]
              spids: [166]
            )
            (C {(test_expect_success)} {(DQ ($ VSub_Name '$type') (' exists'))} 
              {(SQ <'\n'> <'\tgit cat-file -e $sha1\n'> <'    '>)}
            )
            (C {(test_expect_success)} {(DQ ('Type of ') ($ VSub_Name '$type') (' is correct'))} 
              {
                (SQ <'\n'> <'\techo $type >expect &&\n'> <'\tgit cat-file -t $sha1 >actual &&\n'> 
                  <'\ttest_cmp expect actual\n'> <'    '>
                )
              }
            )
            (C {(test_expect_success)} {(DQ ('Size of ') ($ VSub_Name '$type') (' is correct'))} 
              {
                (SQ <'\n'> <'\techo $size >expect &&\n'> <'\tgit cat-file -s $sha1 >actual &&\n'> 
                  <'\ttest_cmp expect actual\n'> <'    '>
                )
              }
            )
            (C {(test_expect_success)} 
              {(DQ ('Type of ') ($ VSub_Name '$type') (' is correct using --allow-unknown-type'))} 
              {
                (SQ <'\n'> <'\techo $type >expect &&\n'> 
                  <'\tgit cat-file -t --allow-unknown-type $sha1 >actual &&\n'> <'\ttest_cmp expect actual\n'> <'    '>
                )
              }
            )
            (C {(test_expect_success)} 
              {(DQ ('Size of ') ($ VSub_Name '$type') (' is correct using --allow-unknown-type'))} 
              {
                (SQ <'\n'> <'\techo $size >expect &&\n'> 
                  <'\tgit cat-file -s --allow-unknown-type $sha1 >actual &&\n'> <'\ttest_cmp expect actual\n'> <'    '>
                )
              }
            )
            (AndOr
              children: [
                (C {(test)} {(-z)} {(DQ ($ VSub_Name '$content'))})
                (C {(test_expect_success)} {(DQ ('Content of ') ($ VSub_Name '$type') (' is correct'))} 
                  {
                    (SQ <'\n'> <'\tmaybe_remove_timestamp "$content" $no_ts >expect &&\n'> 
                      <
'\tmaybe_remove_timestamp "$(git cat-file $type $sha1)" $no_ts >actual &&\n'
                      > <'\ttest_cmp expect actual\n'> <'    '>
                    )
                  }
                )
              ]
              op_id: Op_DPipe
            )
            (C {(test_expect_success)} 
              {(DQ ('Pretty content of ') ($ VSub_Name '$type') (' is correct'))} 
              {
                (SQ <'\n'> <'\tmaybe_remove_timestamp "$pretty_content" $no_ts >expect &&\n'> 
                  <'\tmaybe_remove_timestamp "$(git cat-file -p $sha1)" $no_ts >actual &&\n'> <'\ttest_cmp expect actual\n'> <'    '>
                )
              }
            )
            (AndOr
              children: [
                (C {(test)} {(-z)} {(DQ ($ VSub_Name '$content'))})
                (C {(test_expect_success)} 
                  {(DQ ('--batch output of ') ($ VSub_Name '$type') (' is correct'))} 
                  {
                    (SQ <'\n'> <'\tmaybe_remove_timestamp "$batch_output" $no_ts >expect &&\n'> 
                      <
'\tmaybe_remove_timestamp "$(echo $sha1 | git cat-file --batch)" $no_ts >actual &&\n'
                      > <'\ttest_cmp expect actual\n'> <'    '>
                    )
                  }
                )
              ]
              op_id: Op_DPipe
            )
            (C {(test_expect_success)} 
              {(DQ ('--batch-check output of ') ($ VSub_Name '$type') (' is correct'))} 
              {
                (SQ <'\n'> <'\techo "$sha1 $type $size" >expect &&\n'> 
                  <'\techo_without_newline $sha1 | git cat-file --batch-check >actual &&\n'> <'\ttest_cmp expect actual\n'> <'    '>
                )
              }
            )
            (C {(test_expect_success)} {(DQ ('custom --batch-check format'))} 
              {
                (SQ <'\n'> <'\techo "$type $sha1" >expect &&\n'> 
                  <
'\techo $sha1 | git cat-file --batch-check="%(objecttype) %(objectname)" >actual &&\n'
                  > <'\ttest_cmp expect actual\n'> <'    '>
                )
              }
            )
            (C {(test_expect_success)} {(SQ <'--batch-check with %(rest)'>)} 
              {
                (SQ <'\n'> <'\techo "$type this is some extra content" >expect &&\n'> 
                  <'\techo "$sha1    this is some extra content" |\n'> <'\t\tgit cat-file --batch-check="%(objecttype) %(rest)" >actual &&\n'> <'\ttest_cmp expect actual\n'> 
                  <'    '>
                )
              }
            )
            (AndOr
              children: [
                (C {(test)} {(-z)} {(DQ ($ VSub_Name '$content'))})
                (C {(test_expect_success)} {(DQ ('--batch without type (') ($ VSub_Name '$type') (')'))} 
                  {
                    (SQ <'\n'> <'\t{\n'> <'\t\techo "$size" &&\n'> 
                      <'\t\tmaybe_remove_timestamp "$content" $no_ts\n'> <'\t} >expect &&\n'> <'\techo $sha1 | git cat-file --batch="%(objectsize)" >actual.full &&\n'> 
                      <'\tmaybe_remove_timestamp "$(cat actual.full)" $no_ts >actual &&\n'> <'\ttest_cmp expect actual\n'> <'    '>
                    )
                  }
                )
              ]
              op_id: Op_DPipe
            )
            (AndOr
              children: [
                (C {(test)} {(-z)} {(DQ ($ VSub_Name '$content'))})
                (C {(test_expect_success)} {(DQ ('--batch without size (') ($ VSub_Name '$type') (')'))} 
                  {
                    (SQ <'\n'> <'\t{\n'> <'\t\techo "$type" &&\n'> 
                      <'\t\tmaybe_remove_timestamp "$content" $no_ts\n'> <'\t} >expect &&\n'> <'\techo $sha1 | git cat-file --batch="%(objecttype)" >actual.full &&\n'> 
                      <'\tmaybe_remove_timestamp "$(cat actual.full)" $no_ts >actual &&\n'> <'\ttest_cmp expect actual\n'> <'    '>
                    )
                  }
                )
              ]
              op_id: Op_DPipe
            )
          ]
          spids: [138]
        )
      spids: [133 137]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:hello_content)
          op: Equal
          rhs: {(DQ ('Hello World'))}
          spids: [460]
        )
      ]
      spids: [460]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:hello_size)
          op: Equal
          rhs: 
            {
              (CommandSubPart
                command_list: 
                  (CommandList
                    children: [(C {(strlen)} {(DQ ($ VSub_Name '$hello_content'))})]
                  )
                left_token: <Left_CommandSub '$('>
                spids: [466 472]
              )
            }
          spids: [465]
        )
      ]
      spids: [465]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:hello_sha1)
          op: Equal
          rhs: 
            {
              (CommandSubPart
                command_list: 
                  (CommandList
                    children: [
                      (Pipeline
                        children: [
                          (C {(echo_without_newline)} {(DQ ($ VSub_Name '$hello_content'))})
                          (C {(git)} {(hash-object)} {(--stdin)})
                        ]
                        negated: False
                      )
                    ]
                  )
                left_token: <Left_CommandSub '$('>
                spids: [475 489]
              )
            }
          spids: [474]
        )
      ]
      spids: [474]
    )
    (C {(test_expect_success)} {(DQ (setup))} 
      {
        (SQ <'\n'> <'\techo_without_newline "$hello_content" > hello &&\n'> 
          <'\tgit update-index --add hello\n'>
        )
      }
    )
    (C {(run_tests)} {(SQ <blob>)} {($ VSub_Name '$hello_sha1')} {($ VSub_Name '$hello_size')} 
      {(DQ ($ VSub_Name '$hello_content'))} {(DQ ($ VSub_Name '$hello_content'))}
    )
    (C {(test_expect_success)} {(SQ <'--batch-check without %(rest) considers whole line'>)} 
      {
        (SQ <'\n'> <'\techo "$hello_sha1 blob $hello_size" >expect &&\n'> 
          <'\tgit update-index --add --cacheinfo 100644 $hello_sha1 "white space" &&\n'> <'\ttest_when_finished "git update-index --remove \\"white space\\"" &&\n'> 
          <'\techo ":white space" | git cat-file --batch-check >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:tree_sha1)
          op: Equal
          rhs: 
            {
              (CommandSubPart
                command_list: (CommandList children:[(C {(git)} {(write-tree)})])
                left_token: <Left_CommandSub '$('>
                spids: [541 545]
              )
            }
          spids: [540]
        )
      ]
      spids: [540]
    )
    (Assignment
      keyword: Assign_None
      pairs: [(assign_pair lhs:(LhsName name:tree_size) op:Equal rhs:{(33)} spids:[547])]
      spids: [547]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:tree_pretty_content)
          op: Equal
          rhs: {(DQ ('100644 blob ') ($ VSub_Name '$hello_sha1') ('\thello'))}
          spids: [550]
        )
      ]
      spids: [550]
    )
    (C {(run_tests)} {(SQ <tree>)} {($ VSub_Name '$tree_sha1')} {($ VSub_Name '$tree_size')} {(DQ )} 
      {(DQ ($ VSub_Name '$tree_pretty_content'))}
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:commit_message)
          op: Equal
          rhs: {(DQ ('Initial commit'))}
          spids: [576]
        )
      ]
      spids: [576]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:commit_sha1)
          op: Equal
          rhs: 
            {
              (CommandSubPart
                command_list: 
                  (CommandList
                    children: [
                      (Pipeline
                        children: [
                          (C {(echo_without_newline)} {(DQ ($ VSub_Name '$commit_message'))})
                          (C {(git)} {(commit-tree)} {($ VSub_Name '$tree_sha1')})
                        ]
                        negated: False
                      )
                    ]
                  )
                left_token: <Left_CommandSub '$('>
                spids: [582 596]
              )
            }
          spids: [581]
        )
      ]
      spids: [581]
    )
    (Assignment
      keyword: Assign_None
      pairs: [(assign_pair lhs:(LhsName name:commit_size) op:Equal rhs:{(177)} spids:[598])]
      spids: [598]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:commit_content)
          op: Equal
          rhs: 
            {
              (DQ ('tree ') ($ VSub_Name '$tree_sha1') ('\n') ('author ') 
                ($ VSub_Name '$GIT_AUTHOR_NAME') (' <') ($ VSub_Name '$GIT_AUTHOR_EMAIL') ('> 0000000000 +0000\n') ('committer ') 
                ($ VSub_Name '$GIT_COMMITTER_NAME') (' <') ($ VSub_Name '$GIT_COMMITTER_EMAIL') ('> 0000000000 +0000\n') ('\n') 
                ($ VSub_Name '$commit_message')
              )
            }
          spids: [601]
        )
      ]
      spids: [601]
    )
    (C {(run_tests)} {(SQ <commit>)} {($ VSub_Name '$commit_sha1')} {($ VSub_Name '$commit_size')} 
      {(DQ ($ VSub_Name '$commit_content'))} {(DQ ($ VSub_Name '$commit_content'))} {(1)}
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:tag_header_without_timestamp)
          op: Equal
          rhs: 
            {
              (DQ ('object ') ($ VSub_Name '$hello_sha1') ('\n') ('type blob\n') ('tag hellotag\n') 
                ('tagger ') ($ VSub_Name '$GIT_COMMITTER_NAME') (' <') ($ VSub_Name '$GIT_COMMITTER_EMAIL') ('>')
              )
            }
          spids: [642]
        )
      ]
      spids: [642]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:tag_description)
          op: Equal
          rhs: {(DQ ('This is a tag'))}
          spids: [656]
        )
      ]
      spids: [656]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:tag_content)
          op: Equal
          rhs: 
            {
              (DQ ($ VSub_Name '$tag_header_without_timestamp') (' 0000000000 +0000\n') ('\n') 
                ($ VSub_Name '$tag_description')
              )
            }
          spids: [661]
        )
      ]
      spids: [661]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:tag_sha1)
          op: Equal
          rhs: 
            {
              (CommandSubPart
                command_list: 
                  (CommandList
                    children: [
                      (Pipeline
                        children: [
                          (C {(echo_without_newline)} {(DQ ($ VSub_Name '$tag_content'))})
                          (C {(git)} {(mktag)})
                        ]
                        negated: False
                      )
                    ]
                  )
                left_token: <Left_CommandSub '$('>
                spids: [671 683]
              )
            }
          spids: [670]
        )
      ]
      spids: [670]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:tag_size)
          op: Equal
          rhs: 
            {
              (CommandSubPart
                command_list: 
                  (CommandList
                    children: [(C {(strlen)} {(DQ ($ VSub_Name '$tag_content'))})]
                  )
                left_token: <Left_CommandSub '$('>
                spids: [686 692]
              )
            }
          spids: [685]
        )
      ]
      spids: [685]
    )
    (C {(run_tests)} {(SQ <tag>)} {($ VSub_Name '$tag_sha1')} {($ VSub_Name '$tag_size')} 
      {(DQ ($ VSub_Name '$tag_content'))} {(DQ ($ VSub_Name '$tag_content'))} {(1)}
    )
    (C {(test_expect_success)} {(DQ ('Reach a blob from a tag pointing to it'))} 
      {
        (DQ ("test '") ($ VSub_Name '$hello_content') ("' = ") 
          (EscapedLiteralPart token:<Lit_EscapedChar '\\"'>) (EscapedLiteralPart token:<Lit_EscapedChar '\\$'>) ('(git cat-file blob ') ($ VSub_Name '$tag_sha1') 
          (')') (EscapedLiteralPart token:<Lit_EscapedChar '\\"'>)
        )
      }
    )
    (ForEach
      iter_name: batch
      iter_words: [{(batch)} {(batch-check)}]
      do_arg_iter: False
      body: 
        (DoGroup
          children: [
            (ForEach
              iter_name: opt
              iter_words: [{(t)} {(s)} {(e)} {(p)}]
              do_arg_iter: False
              body: 
                (DoGroup
                  children: [
                    (C {(test_expect_success)} 
                      {
                        (DQ ('Passing -') ($ VSub_Name '$opt') (' with --') ($ VSub_Name '$batch') 
                          (' fails')
                        )
                      } {(SQ <'\n'> <'\t    test_must_fail git cat-file --$batch -$opt $hello_sha1\n'> <'\t'>)}
                    )
                    (C {(test_expect_success)} 
                      {
                        (DQ ('Passing --') ($ VSub_Name '$batch') (' with -') ($ VSub_Name '$opt') 
                          (' fails')
                        )
                      } {(SQ <'\n'> <'\t    test_must_fail git cat-file -$opt --$batch $hello_sha1\n'> <'\t'>)}
                    )
                  ]
                  spids: [767 805]
                )
              spids: [757 -1]
            )
            (C {(test_expect_success)} 
              {(DQ ('Passing <type> with --') ($ VSub_Name '$batch') (' fails'))} {(SQ <'\n'> <'\ttest_must_fail git cat-file --$batch blob $hello_sha1\n'> <'    '>)}
            )
            (C {(test_expect_success)} 
              {(DQ ('Passing --') ($ VSub_Name '$batch') (' with <type> fails'))} {(SQ <'\n'> <'\ttest_must_fail git cat-file blob --$batch $hello_sha1\n'> <'    '>)}
            )
            (C {(test_expect_success)} {(DQ ('Passing sha1 with --') ($ VSub_Name '$batch') (' fails'))} 
              {(SQ <'\n'> <'\ttest_must_fail git cat-file --$batch $hello_sha1\n'> <'    '>)}
            )
          ]
          spids: [749 855]
        )
      spids: [744 -1]
    )
    (ForEach
      iter_name: opt
      iter_words: [{(t)} {(s)} {(e)} {(p)}]
      do_arg_iter: False
      body: 
        (DoGroup
          children: [
            (C {(test_expect_success)} 
              {(DQ ('Passing -') ($ VSub_Name '$opt') (' with --follow-symlinks fails'))} {(SQ <'\n'> <'\t    test_must_fail git cat-file --follow-symlinks -$opt $hello_sha1\n'> <'\t'>)}
            )
          ]
          spids: [872 889]
        )
      spids: [863 -1]
    )
    (C {(test_expect_success)} {(DQ ('--batch-check for a non-existent named object'))} 
      {
        (SQ <'\n'> <'    test "foobar42 missing\n'> <'foobar84 missing" = \\\n'> 
          <
'    "$( ( echo foobar42; echo_without_newline foobar84; ) | git cat-file --batch-check)"\n'
          >
        )
      }
    )
    (C {(test_expect_success)} {(DQ ('--batch-check for a non-existent hash'))} 
      {
        (SQ <'\n'> <'    test "0000000000000000000000000000000000000042 missing\n'> 
          <'0000000000000000000000000000000000000084 missing" = \\\n'> <'    "$( ( echo 0000000000000000000000000000000000000042;\n'> 
          <'         echo_without_newline 0000000000000000000000000000000000000084; ) \\\n'> <'       | git cat-file --batch-check)"\n'>
        )
      }
    )
    (C {(test_expect_success)} {(DQ ('--batch for an existent and a non-existent hash'))} 
      {
        (SQ <'\n'> <'    test "$tag_sha1 tag $tag_size\n'> <'$tag_content\n'> 
          <'0000000000000000000000000000000000000000 missing" = \\\n'> <'    "$( ( echo $tag_sha1;\n'> 
          <'         echo_without_newline 0000000000000000000000000000000000000000; ) \\\n'> <'       | git cat-file --batch)"\n'>
        )
      }
    )
    (C {(test_expect_success)} {(DQ ('--batch-check for an empty line'))} 
      {(SQ <'\n'> <'    test " missing" = "$(echo | git cat-file --batch-check)"\n'>)}
    )
    (C {(test_expect_success)} {(SQ <'empty --batch-check notices missing object'>)} 
      {
        (SQ <'\n'> <'\techo "$_z40 missing" >expect &&\n'> 
          <'\techo "$_z40" | git cat-file --batch-check="" >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:batch_input)
          op: Equal
          rhs: 
            {
              (DQ ($ VSub_Name '$hello_sha1') ('\n') ($ VSub_Name '$commit_sha1') ('\n') 
                ($ VSub_Name '$tag_sha1') ('\n') ('deadbeef\n') ('\n')
              )
            }
          spids: [965]
        )
      ]
      spids: [965]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:batch_output)
          op: Equal
          rhs: 
            {
              (DQ ($ VSub_Name '$hello_sha1') (' blob ') ($ VSub_Name '$hello_size') ('\n') 
                ($ VSub_Name '$hello_content') ('\n') ($ VSub_Name '$commit_sha1') (' commit ') ($ VSub_Name '$commit_size') ('\n') 
                ($ VSub_Name '$commit_content') ('\n') ($ VSub_Name '$tag_sha1') (' tag ') ($ VSub_Name '$tag_size') ('\n') ($ VSub_Name '$tag_content') 
                ('\n') ('deadbeef missing\n') (' missing')
              )
            }
          spids: [978]
        )
      ]
      spids: [978]
    )
    (C {(test_expect_success)} {(SQ <'--batch with multiple sha1s gives correct format'>)} 
      {
        (SQ <'\n'> 
          <
'\ttest "$(maybe_remove_timestamp "$batch_output" 1)" = "$(maybe_remove_timestamp "$(echo_without_newline "$batch_input" | git cat-file --batch)" 1)"\n'
          >
        )
      }
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:batch_check_input)
          op: Equal
          rhs: 
            {
              (DQ ($ VSub_Name '$hello_sha1') ('\n') ($ VSub_Name '$tree_sha1') ('\n') 
                ($ VSub_Name '$commit_sha1') ('\n') ($ VSub_Name '$tag_sha1') ('\n') ('deadbeef\n') ('\n')
              )
            }
          spids: [1015]
        )
      ]
      spids: [1015]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:batch_check_output)
          op: Equal
          rhs: 
            {
              (DQ ($ VSub_Name '$hello_sha1') (' blob ') ($ VSub_Name '$hello_size') ('\n') 
                ($ VSub_Name '$tree_sha1') (' tree ') ($ VSub_Name '$tree_size') ('\n') ($ VSub_Name '$commit_sha1') (' commit ') 
                ($ VSub_Name '$commit_size') ('\n') ($ VSub_Name '$tag_sha1') (' tag ') ($ VSub_Name '$tag_size') ('\n') ('deadbeef missing\n') 
                (' missing')
              )
            }
          spids: [1030]
        )
      ]
      spids: [1030]
    )
    (C {(test_expect_success)} {(DQ ('--batch-check with multiple sha1s gives correct format'))} 
      {
        (SQ <'\n'> <'    test "$batch_check_output" = \\\n'> 
          <'    "$(echo_without_newline "$batch_check_input" | git cat-file --batch-check)"\n'>
        )
      }
    )
    (C {(test_expect_success)} {(SQ <'setup blobs which are likely to delta'>)} 
      {
        (SQ <'\n'> <'\ttest-genrandom foo 10240 >foo &&\n'> 
          <'\t{ cat foo; echo plus; } >foo-plus &&\n'> <'\tgit add foo foo-plus &&\n'> <'\tgit commit -m foo &&\n'> <'\tcat >blobs <<-\\EOF\n'> 
          <'\tHEAD:foo\n'> <'\tHEAD:foo-plus\n'> <'\tEOF\n'>
        )
      }
    )
    (C {(test_expect_success)} {(SQ <'confirm that neither loose blob is a delta'>)} 
      {
        (SQ <'\n'> <'\tcat >expect <<-EOF &&\n'> <'\t$_z40\n'> <'\t$_z40\n'> <'\tEOF\n'> 
          <'\tgit cat-file --batch-check="%(deltabase)" <blobs >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} {(SQ <'%(deltabase) reports packed delta bases'>)} 
      {
        (SQ <'\n'> <'\tgit repack -ad &&\n'> 
          <'\tgit cat-file --batch-check="%(deltabase)" <blobs >actual &&\n'> <'\t{\n'> <'\t\tgrep "$(git rev-parse HEAD:foo)" actual ||\n'> 
          <'\t\tgrep "$(git rev-parse HEAD:foo-plus)" actual\n'> <'\t}\n'>
        )
      }
    )
    (Assignment
      keyword: Assign_None
      pairs: [(assign_pair lhs:(LhsName name:bogus_type) op:Equal rhs:{(DQ (bogus))} spids:[1134])]
      spids: [1134]
    )
    (Assignment
      keyword: Assign_None
      pairs: [(assign_pair lhs:(LhsName name:bogus_content) op:Equal rhs:{(DQ (bogus))} spids:[1139])]
      spids: [1139]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:bogus_size)
          op: Equal
          rhs: 
            {
              (CommandSubPart
                command_list: 
                  (CommandList
                    children: [(C {(strlen)} {(DQ ($ VSub_Name '$bogus_content'))})]
                  )
                left_token: <Left_CommandSub '$('>
                spids: [1145 1151]
              )
            }
          spids: [1144]
        )
      ]
      spids: [1144]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:bogus_sha1)
          op: Equal
          rhs: 
            {
              (CommandSubPart
                command_list: 
                  (CommandList
                    children: [
                      (Pipeline
                        children: [
                          (C {(echo_without_newline)} {(DQ ($ VSub_Name '$bogus_content'))})
                          (C {(git)} {(hash-object)} {(-t)} {($ VSub_Name '$bogus_type')} {(--literally)} 
                            {(-w)} {(--stdin)}
                          )
                        ]
                        negated: False
                      )
                    ]
                  )
                left_token: <Left_CommandSub '$('>
                spids: [1154 1176]
              )
            }
          spids: [1153]
        )
      ]
      spids: [1153]
    )
    (C {(test_expect_success)} {(DQ ('Type of broken object is correct'))} 
      {
        (SQ <'\n'> <'\techo $bogus_type >expect &&\n'> 
          <'\tgit cat-file -t --allow-unknown-type $bogus_sha1 >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} {(DQ ('Size of broken object is correct'))} 
      {
        (SQ <'\n'> <'\techo $bogus_size >expect &&\n'> 
          <'\tgit cat-file -s --allow-unknown-type $bogus_sha1 >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:bogus_type)
          op: Equal
          rhs: {(DQ (abcdefghijklmnopqrstuvwxyz1234679))}
          spids: [1206]
        )
      ]
      spids: [1206]
    )
    (Assignment
      keyword: Assign_None
      pairs: [(assign_pair lhs:(LhsName name:bogus_content) op:Equal rhs:{(DQ (bogus))} spids:[1211])]
      spids: [1211]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:bogus_size)
          op: Equal
          rhs: 
            {
              (CommandSubPart
                command_list: 
                  (CommandList
                    children: [(C {(strlen)} {(DQ ($ VSub_Name '$bogus_content'))})]
                  )
                left_token: <Left_CommandSub '$('>
                spids: [1217 1223]
              )
            }
          spids: [1216]
        )
      ]
      spids: [1216]
    )
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:bogus_sha1)
          op: Equal
          rhs: 
            {
              (CommandSubPart
                command_list: 
                  (CommandList
                    children: [
                      (Pipeline
                        children: [
                          (C {(echo_without_newline)} {(DQ ($ VSub_Name '$bogus_content'))})
                          (C {(git)} {(hash-object)} {(-t)} {($ VSub_Name '$bogus_type')} {(--literally)} 
                            {(-w)} {(--stdin)}
                          )
                        ]
                        negated: False
                      )
                    ]
                  )
                left_token: <Left_CommandSub '$('>
                spids: [1226 1248]
              )
            }
          spids: [1225]
        )
      ]
      spids: [1225]
    )
    (C {(test_expect_success)} {(DQ ('Type of broken object is correct when type is large'))} 
      {
        (SQ <'\n'> <'\techo $bogus_type >expect &&\n'> 
          <'\tgit cat-file -t --allow-unknown-type $bogus_sha1 >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} {(DQ ('Size of large broken object is correct when type is large'))} 
      {
        (SQ <'\n'> <'\techo $bogus_size >expect &&\n'> 
          <'\tgit cat-file -s --allow-unknown-type $bogus_sha1 >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} {(SQ <'prep for symlink tests'>)} 
      {
        (SQ <'\n'> <'\techo_without_newline "$hello_content" >morx &&\n'> 
          <'\ttest_ln_s_add morx same-dir-link &&\n'> <'\ttest_ln_s_add dir link-to-dir &&\n'> <'\ttest_ln_s_add ../fleem out-of-repo-link &&\n'> 
          <'\ttest_ln_s_add .. out-of-repo-link-dir &&\n'> <'\ttest_ln_s_add same-dir-link link-to-link &&\n'> <'\ttest_ln_s_add nope broken-same-dir-link &&\n'> 
          <'\tmkdir dir &&\n'> <'\ttest_ln_s_add ../morx dir/parent-dir-link &&\n'> <'\ttest_ln_s_add .. dir/link-dir &&\n'> 
          <'\ttest_ln_s_add ../../escape dir/out-of-repo-link &&\n'> <'\ttest_ln_s_add ../.. dir/out-of-repo-link-dir &&\n'> 
          <'\ttest_ln_s_add nope dir/broken-link-in-dir &&\n'> <'\tmkdir dir/subdir &&\n'> <'\ttest_ln_s_add ../../morx dir/subdir/grandparent-dir-link &&\n'> 
          <'\ttest_ln_s_add ../../../great-escape dir/subdir/out-of-repo-link &&\n'> <'\ttest_ln_s_add ../../.. dir/subdir/out-of-repo-link-dir &&\n'> 
          <'\ttest_ln_s_add ../../../ dir/subdir/out-of-repo-link-dir-trailing &&\n'> <'\ttest_ln_s_add ../parent-dir-link dir/subdir/parent-dir-link-to-link &&\n'> 
          <'\techo_without_newline "$hello_content" >dir/subdir/ind2 &&\n'> <'\techo_without_newline "$hello_content" >dir/ind1 &&\n'> <'\ttest_ln_s_add dir dirlink &&\n'> 
          <'\ttest_ln_s_add dir/subdir subdirlink &&\n'> <'\ttest_ln_s_add subdir/ind2 dir/link-to-child &&\n'> 
          <'\ttest_ln_s_add dir/link-to-child link-to-down-link &&\n'> <'\ttest_ln_s_add dir/.. up-down &&\n'> <'\ttest_ln_s_add dir/../ up-down-trailing &&\n'> 
          <'\ttest_ln_s_add dir/../morx up-down-file &&\n'> <'\ttest_ln_s_add dir/../../morx up-up-down-file &&\n'> 
          <'\ttest_ln_s_add subdirlink/../../morx up-two-down-file &&\n'> <'\ttest_ln_s_add loop1 loop2 &&\n'> <'\ttest_ln_s_add loop2 loop1 &&\n'> 
          <'\tgit add morx dir/subdir/ind2 dir/ind1 &&\n'> <'\tgit commit -am "test" &&\n'> <'\techo $hello_sha1 blob $hello_size >found\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for non-links'>)} 
      {
        (SQ <'\n'> <'\techo HEAD:morx | git cat-file --batch-check --follow-symlinks >actual &&\n'> 
          <'\ttest_cmp found actual &&\n'> <'\techo HEAD:nope missing >expect &&\n'> 
          <'\techo HEAD:nope | git cat-file --batch-check --follow-symlinks >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for in-repo, same-dir links'>)} 
      {
        (SQ <'\n'> 
          <'\techo HEAD:same-dir-link | git cat-file --batch-check --follow-symlinks >actual &&\n'> <'\ttest_cmp found actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for in-repo, links to dirs'>)} 
      {
        (SQ <'\n'> 
          <
'\techo HEAD:link-to-dir/ind1 | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp found actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {
        (SQ <'git cat-file --batch-check --follow-symlinks works for broken in-repo, same-dir links'>)
      } 
      {
        (SQ <'\n'> <'\techo dangling 25 >expect &&\n'> 
          <'\techo HEAD:broken-same-dir-link >>expect &&\n'> <'\techo HEAD:broken-same-dir-link | git cat-file --batch-check --follow-symlinks >actual &&\n'> 
          <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for same-dir links-to-links'>)} 
      {
        (SQ <'\n'> 
          <'\techo HEAD:link-to-link | git cat-file --batch-check --follow-symlinks >actual &&\n'> <'\ttest_cmp found actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for parent-dir links'>)} 
      {
        (SQ <'\n'> 
          <
'\techo HEAD:dir/parent-dir-link | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp found actual &&\n'> <'\techo notdir 29 >expect &&\n'> 
          <'\techo HEAD:dir/parent-dir-link/nope >>expect &&\n'> <'\techo HEAD:dir/parent-dir-link/nope | git cat-file --batch-check --follow-symlinks >actual &&\n'> 
          <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for .. links'>)} 
      {
        (SQ <'\n'> <'\techo dangling 22 >expect &&\n'> <'\techo HEAD:dir/link-dir/nope >>expect &&\n'> 
          <
'\techo HEAD:dir/link-dir/nope | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual &&\n'> 
          <
'\techo HEAD:dir/link-dir/morx | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp found actual &&\n'> <'\techo dangling 27 >expect &&\n'> 
          <'\techo HEAD:dir/broken-link-in-dir >>expect &&\n'> <'\techo HEAD:dir/broken-link-in-dir | git cat-file --batch-check --follow-symlinks >actual &&\n'> 
          <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for ../.. links'>)} 
      {
        (SQ <'\n'> <'\techo notdir 41 >expect &&\n'> 
          <'\techo HEAD:dir/subdir/grandparent-dir-link/nope >>expect &&\n'> 
          <
'\techo HEAD:dir/subdir/grandparent-dir-link/nope | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual &&\n'> 
          <
'\techo HEAD:dir/subdir/grandparent-dir-link | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp found actual &&\n'> 
          <
'\techo HEAD:dir/subdir/parent-dir-link-to-link | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp found actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for dir/ links'>)} 
      {
        (SQ <'\n'> <'\techo dangling 17 >expect &&\n'> <'\techo HEAD:dirlink/morx >>expect &&\n'> 
          <'\techo HEAD:dirlink/morx | git cat-file --batch-check --follow-symlinks >actual &&\n'> <'\ttest_cmp expect actual &&\n'> <'\techo $hello_sha1 blob $hello_size >expect &&\n'> 
          <'\techo HEAD:dirlink/ind1 | git cat-file --batch-check --follow-symlinks >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for dir/subdir links'>)} 
      {
        (SQ <'\n'> <'\techo dangling 20 >expect &&\n'> <'\techo HEAD:subdirlink/morx >>expect &&\n'> 
          <
'\techo HEAD:subdirlink/morx | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual &&\n'> 
          <
'\techo HEAD:subdirlink/ind2 | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp found actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for dir ->subdir links'>)} 
      {
        (SQ <'\n'> <'\techo notdir 27 >expect &&\n'> 
          <'\techo HEAD:dir/link-to-child/morx >>expect &&\n'> <'\techo HEAD:dir/link-to-child/morx | git cat-file --batch-check --follow-symlinks >actual &&\n'> 
          <'\ttest_cmp expect actual &&\n'> <'\techo HEAD:dir/link-to-child | git cat-file --batch-check --follow-symlinks >actual &&\n'> 
          <'\ttest_cmp found actual &&\n'> <'\techo HEAD:link-to-down-link | git cat-file --batch-check --follow-symlinks >actual &&\n'> 
          <'\ttest_cmp found actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for out-of-repo symlinks'>)} 
      {
        (SQ <'\n'> <'\techo symlink 8 >expect &&\n'> <'\techo ../fleem >>expect &&\n'> 
          <
'\techo HEAD:out-of-repo-link | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual &&\n'> <'\techo symlink 2 >expect &&\n'> <'\techo .. >>expect &&\n'> 
          <
'\techo HEAD:out-of-repo-link-dir | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for out-of-repo symlinks in dirs'>)} 
      {
        (SQ <'\n'> <'\techo symlink 9 >expect &&\n'> <'\techo ../escape >>expect &&\n'> 
          <
'\techo HEAD:dir/out-of-repo-link | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual &&\n'> <'\techo symlink 2 >expect &&\n'> <'\techo .. >>expect &&\n'> 
          <
'\techo HEAD:dir/out-of-repo-link-dir | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {
        (SQ 
          <
'git cat-file --batch-check --follow-symlinks works for out-of-repo symlinks in subdirs'
          >
        )
      } 
      {
        (SQ <'\n'> <'\techo symlink 15 >expect &&\n'> <'\techo ../great-escape >>expect &&\n'> 
          <
'\techo HEAD:dir/subdir/out-of-repo-link | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual &&\n'> <'\techo symlink 2 >expect &&\n'> <'\techo .. >>expect &&\n'> 
          <
'\techo HEAD:dir/subdir/out-of-repo-link-dir | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual &&\n'> <'\techo symlink 3 >expect &&\n'> <'\techo ../ >>expect &&\n'> 
          <
'\techo HEAD:dir/subdir/out-of-repo-link-dir-trailing | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch-check --follow-symlinks works for symlinks with internal ..'>)} 
      {
        (SQ <'\n'> <'\techo HEAD: | git cat-file --batch-check >expect &&\n'> 
          <'\techo HEAD:up-down | git cat-file --batch-check --follow-symlinks >actual &&\n'> <'\ttest_cmp expect actual &&\n'> 
          <
'\techo HEAD:up-down-trailing | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual &&\n'> 
          <'\techo HEAD:up-down-file | git cat-file --batch-check --follow-symlinks >actual &&\n'> <'\ttest_cmp found actual &&\n'> <'\techo symlink 7 >expect &&\n'> <'\techo ../morx >>expect &&\n'> 
          <
'\techo HEAD:up-up-down-file | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp expect actual &&\n'> 
          <
'\techo HEAD:up-two-down-file | git cat-file --batch-check --follow-symlinks >actual &&\n'
          > <'\ttest_cmp found actual\n'>
        )
      }
    )
    (C {(test_expect_success)} {(SQ <'git cat-file --batch-check --follow-symlink breaks loops'>)} 
      {
        (SQ <'\n'> <'\techo loop 10 >expect &&\n'> <'\techo HEAD:loop1 >>expect &&\n'> 
          <'\techo HEAD:loop1 | git cat-file --batch-check --follow-symlinks >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ <'git cat-file --batch --follow-symlink returns correct sha and mode'>)} 
      {
        (SQ <'\n'> <'\techo HEAD:morx | git cat-file --batch >expect &&\n'> 
          <'\techo HEAD:morx | git cat-file --batch --follow-symlinks >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_expect_success)} {(SQ <'cat-file --batch-all-objects shows all objects'>)} 
      {
        (SQ <'\n'> <'\t# make new repos so we know the full set of objects; we will\n'> 
          <'\t# also make sure that there are some packed and some loose\n'> <'\t# objects, some referenced and some not, and that there are\n'> 
          <'\t# some available only via alternates.\n'> <'\tgit init all-one &&\n'> <'\t(\n'> <'\t\tcd all-one &&\n'> <'\t\techo content >file &&\n'> 
          <'\t\tgit add file &&\n'> <'\t\tgit commit -qm base &&\n'> <'\t\tgit rev-parse HEAD HEAD^{tree} HEAD:file &&\n'> 
          <'\t\tgit repack -ad &&\n'> <'\t\techo not-cloned | git hash-object -w --stdin\n'> <'\t) >expect.unsorted &&\n'> 
          <'\tgit clone -s all-one all-two &&\n'> <'\t(\n'> <'\t\tcd all-two &&\n'> <'\t\techo local-unref | git hash-object -w --stdin\n'> 
          <'\t) >>expect.unsorted &&\n'> <'\tsort <expect.unsorted >expect &&\n'> <'\tgit -C all-two cat-file --batch-all-objects \\\n'> 
          <'\t\t\t\t--batch-check="%(objectname)" >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {(test_done)})
  ]
)