(command.CommandList
  children: [
    (command.ShAssignment
      pairs: [
        (assign_pair
          lhs: (sh_lhs_expr.Name name:test_description)
          op: assign_op.Equal
          rhs: {(SQ (Token id:Id.Lit_Chars val:'commit-msg hook' span_id:6))}
          spids: [4]
        )
      ]
    )
    (C {(.)} {(./test-lib.sh)})
    (C {(test_expect_success)} {(SQ (Token id:Id.Lit_Chars val:'with no hook' span_id:18))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:22) (Token id:Id.Lit_Chars val:'\n' span_id:23) 
          (Token id:Id.Lit_Chars val:'\techo "foo" > file &&\n' span_id:24) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:25) 
          (Token id:Id.Lit_Chars val:'\tgit commit -m "first"\n' span_id:26) (Token id:Id.Lit_Chars val:'\n' span_id:27)
        )
      }
    )
    (command.Simple
      words: [{(cat)}]
      redirects: [
        (redir.Redir
          op: (Token id:Id.Redir_Great val:'>' span_id:36)
          fd: -1
          arg_word: {(fake-editor)}
        )
        (redir.HereDoc
          op: (Token id:Id.Redir_DLess val:'<<' span_id:40)
          fd: -1
          here_begin: {(SQ (Token id:Id.Lit_Chars val:EOF span_id:42))}
          here_end_span_id: 48
          stdin_parts: [('#!/bin/sh\n') ('cp FAKE_MSG "$1"\n') ('exit 0\n')]
        )
      ]
    )
    (C {(chmod)} {(Id.Lit_Other '+') (x)} {(fake-editor)})
    (command.ShAssignment
      pairs: [
        (assign_pair
          lhs: (sh_lhs_expr.Name name:FAKE_EDITOR)
          op: assign_op.Equal
          rhs: 
            {
              (DQ 
                (command_sub
                  left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:65)
                  command_list: (command.CommandList children:[(C {(pwd)})])
                ) (/fake-editor)
              )
            }
          spids: [63]
        )
      ]
    )
    (C {(export)} {(FAKE_EDITOR)})
    (C {(test_expect_success)} {(SQ (Token id:Id.Lit_Chars val:'with no hook (editor)' span_id:79))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:83) (Token id:Id.Lit_Chars val:'\n' span_id:84) 
          (Token id:Id.Lit_Chars val:'\techo "more foo" >> file &&\n' span_id:85) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:86) 
          (Token id:Id.Lit_Chars val:'\techo "more foo" > FAKE_MSG &&\n' span_id:87) (Token id:Id.Lit_Chars val:'\tGIT_EDITOR="\\"\\$FAKE_EDITOR\\"" git commit\n' span_id:88) 
          (Token id:Id.Lit_Chars val:'\n' span_id:89)
        )
      }
    )
    (C {(test_expect_success)} {(SQ (Token id:Id.Lit_Chars val:'--no-verify with no hook' span_id:96))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:100) (Token id:Id.Lit_Chars val:'\n' span_id:101) 
          (Token id:Id.Lit_Chars val:'\techo "bar" > file &&\n' span_id:102) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:103) 
          (Token id:Id.Lit_Chars val:'\tgit commit --no-verify -m "bar"\n' span_id:104) (Token id:Id.Lit_Chars val:'\n' span_id:105)
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'--no-verify with no hook (editor)' span_id:112))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:116) (Token id:Id.Lit_Chars val:'\n' span_id:117) 
          (Token id:Id.Lit_Chars val:'\techo "more bar" > file &&\n' span_id:118) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:119) 
          (Token id:Id.Lit_Chars val:'\techo "more bar" > FAKE_MSG &&\n' span_id:120) 
          (Token
            id: Id.Lit_Chars
            val: '\tGIT_EDITOR="\\"\\$FAKE_EDITOR\\"" git commit --no-verify\n'
            span_id: 121
          ) (Token id:Id.Lit_Chars val:'\n' span_id:122)
        )
      }
    )
    (command.ShAssignment
      pairs: [
        (assign_pair
          lhs: (sh_lhs_expr.Name name:HOOKDIR)
          op: assign_op.Equal
          rhs: 
            {
              (DQ 
                (command_sub
                  left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:131)
                  command_list: 
                    (command.CommandList
                      children: [(C {(git)} {(rev-parse)} {(--git-dir)})]
                    )
                ) (/hooks)
              )
            }
          spids: [129]
        )
      ]
    )
    (command.ShAssignment
      pairs: [
        (assign_pair
          lhs: (sh_lhs_expr.Name name:HOOK)
          op: assign_op.Equal
          rhs: {(DQ ($ Id.VSub_DollarName '$HOOKDIR') (/commit-msg))}
          spids: [141]
        )
      ]
    )
    (C {(mkdir)} {(-p)} {(DQ ($ Id.VSub_DollarName '$HOOKDIR'))})
    (command.Simple
      words: [{(cat)}]
      redirects: [
        (redir.Redir
          op: (Token id:Id.Redir_Great val:'>' span_id:157)
          fd: -1
          arg_word: {(DQ ($ Id.VSub_DollarName '$HOOK'))}
        )
        (redir.HereDoc
          op: (Token id:Id.Redir_DLess val:'<<' span_id:163)
          fd: -1
          here_begin: {(EOF)}
          here_end_span_id: 169
          stdin_parts: [('#!/bin/sh\n') ('exit 0\n')]
        )
      ]
    )
    (C {(chmod)} {(Id.Lit_Other '+') (x)} {(DQ ($ Id.VSub_DollarName '$HOOK'))})
    (C {(test_expect_success)} {(SQ (Token id:Id.Lit_Chars val:'with succeeding hook' span_id:183))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:187) (Token id:Id.Lit_Chars val:'\n' span_id:188) 
          (Token id:Id.Lit_Chars val:'\techo "more" >> file &&\n' span_id:189) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:190) 
          (Token id:Id.Lit_Chars val:'\tgit commit -m "more"\n' span_id:191) (Token id:Id.Lit_Chars val:'\n' span_id:192)
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'with succeeding hook (editor)' span_id:199))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:203) (Token id:Id.Lit_Chars val:'\n' span_id:204) 
          (Token id:Id.Lit_Chars val:'\techo "more more" >> file &&\n' span_id:205) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:206) 
          (Token id:Id.Lit_Chars val:'\techo "more more" > FAKE_MSG &&\n' span_id:207) (Token id:Id.Lit_Chars val:'\tGIT_EDITOR="\\"\\$FAKE_EDITOR\\"" git commit\n' span_id:208) 
          (Token id:Id.Lit_Chars val:'\n' span_id:209)
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'--no-verify with succeeding hook' span_id:216))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:220) (Token id:Id.Lit_Chars val:'\n' span_id:221) 
          (Token id:Id.Lit_Chars val:'\techo "even more" >> file &&\n' span_id:222) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:223) 
          (Token
            id: Id.Lit_Chars
            val: '\tgit commit --no-verify -m "even more"\n'
            span_id: 224
          ) (Token id:Id.Lit_Chars val:'\n' span_id:225)
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'--no-verify with succeeding hook (editor)' span_id:232))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:236) (Token id:Id.Lit_Chars val:'\n' span_id:237) 
          (Token id:Id.Lit_Chars val:'\techo "even more more" >> file &&\n' span_id:238) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:239) 
          (Token id:Id.Lit_Chars val:'\techo "even more more" > FAKE_MSG &&\n' span_id:240) 
          (Token
            id: Id.Lit_Chars
            val: '\tGIT_EDITOR="\\"\\$FAKE_EDITOR\\"" git commit --no-verify\n'
            span_id: 241
          ) (Token id:Id.Lit_Chars val:'\n' span_id:242)
        )
      }
    )
    (command.Simple
      words: [{(cat)}]
      redirects: [
        (redir.Redir
          op: (Token id:Id.Redir_Great val:'>' span_id:251)
          fd: -1
          arg_word: {(DQ ($ Id.VSub_DollarName '$HOOK'))}
        )
        (redir.HereDoc
          op: (Token id:Id.Redir_DLess val:'<<' span_id:257)
          fd: -1
          here_begin: {(EOF)}
          here_end_span_id: 263
          stdin_parts: [('#!/bin/sh\n') ('exit 1\n')]
        )
      ]
    )
    (C {(test_expect_success)} {(SQ (Token id:Id.Lit_Chars val:'with failing hook' span_id:268))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:272) (Token id:Id.Lit_Chars val:'\n' span_id:273) 
          (Token id:Id.Lit_Chars val:'\techo "another" >> file &&\n' span_id:274) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:275) 
          (Token
            id: Id.Lit_Chars
            val: '\ttest_must_fail git commit -m "another"\n'
            span_id: 276
          ) (Token id:Id.Lit_Chars val:'\n' span_id:277)
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'with failing hook (editor)' span_id:284))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:288) (Token id:Id.Lit_Chars val:'\n' span_id:289) 
          (Token id:Id.Lit_Chars val:'\techo "more another" >> file &&\n' span_id:290) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:291) 
          (Token id:Id.Lit_Chars val:'\techo "more another" > FAKE_MSG &&\n' span_id:292) (Token id:Id.Lit_Chars val:'\t! (GIT_EDITOR="\\"\\$FAKE_EDITOR\\"" git commit)\n' span_id:293) 
          (Token id:Id.Lit_Chars val:'\n' span_id:294)
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'--no-verify with failing hook' span_id:301))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:305) (Token id:Id.Lit_Chars val:'\n' span_id:306) 
          (Token id:Id.Lit_Chars val:'\techo "stuff" >> file &&\n' span_id:307) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:308) 
          (Token id:Id.Lit_Chars val:'\tgit commit --no-verify -m "stuff"\n' span_id:309) (Token id:Id.Lit_Chars val:'\n' span_id:310)
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'--no-verify with failing hook (editor)' span_id:317))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:321) (Token id:Id.Lit_Chars val:'\n' span_id:322) 
          (Token id:Id.Lit_Chars val:'\techo "more stuff" >> file &&\n' span_id:323) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:324) 
          (Token id:Id.Lit_Chars val:'\techo "more stuff" > FAKE_MSG &&\n' span_id:325) 
          (Token
            id: Id.Lit_Chars
            val: '\tGIT_EDITOR="\\"\\$FAKE_EDITOR\\"" git commit --no-verify\n'
            span_id: 326
          ) (Token id:Id.Lit_Chars val:'\n' span_id:327)
        )
      }
    )
    (C {(chmod)} {(-x)} {(DQ ($ Id.VSub_DollarName '$HOOK'))})
    (C {(test_expect_success)} {(POSIXPERM)} 
      {(SQ (Token id:Id.Lit_Chars val:'with non-executable hook' span_id:344))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:348) (Token id:Id.Lit_Chars val:'\n' span_id:349) 
          (Token id:Id.Lit_Chars val:'\techo "content" >> file &&\n' span_id:350) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:351) 
          (Token id:Id.Lit_Chars val:'\tgit commit -m "content"\n' span_id:352) (Token id:Id.Lit_Chars val:'\n' span_id:353)
        )
      }
    )
    (C {(test_expect_success)} {(POSIXPERM)} 
      {(SQ (Token id:Id.Lit_Chars val:'with non-executable hook (editor)' span_id:362))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:366) (Token id:Id.Lit_Chars val:'\n' span_id:367) 
          (Token id:Id.Lit_Chars val:'\techo "content again" >> file &&\n' span_id:368) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:369) 
          (Token id:Id.Lit_Chars val:'\techo "content again" > FAKE_MSG &&\n' span_id:370) 
          (Token
            id: Id.Lit_Chars
            val: '\tGIT_EDITOR="\\"\\$FAKE_EDITOR\\"" git commit -m "content again"\n'
            span_id: 371
          ) (Token id:Id.Lit_Chars val:'\n' span_id:372)
        )
      }
    )
    (C {(test_expect_success)} {(POSIXPERM)} 
      {(SQ (Token id:Id.Lit_Chars val:'--no-verify with non-executable hook' span_id:381))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:385) (Token id:Id.Lit_Chars val:'\n' span_id:386) 
          (Token id:Id.Lit_Chars val:'\techo "more content" >> file &&\n' span_id:387) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:388) 
          (Token
            id: Id.Lit_Chars
            val: '\tgit commit --no-verify -m "more content"\n'
            span_id: 389
          ) (Token id:Id.Lit_Chars val:'\n' span_id:390)
        )
      }
    )
    (C {(test_expect_success)} {(POSIXPERM)} 
      {(SQ (Token id:Id.Lit_Chars val:'--no-verify with non-executable hook (editor)' span_id:399))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:403) (Token id:Id.Lit_Chars val:'\n' span_id:404) 
          (Token id:Id.Lit_Chars val:'\techo "even more content" >> file &&\n' span_id:405) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:406) 
          (Token
            id: Id.Lit_Chars
            val: '\techo "even more content" > FAKE_MSG &&\n'
            span_id: 407
          ) 
          (Token
            id: Id.Lit_Chars
            val: '\tGIT_EDITOR="\\"\\$FAKE_EDITOR\\"" git commit --no-verify\n'
            span_id: 408
          ) (Token id:Id.Lit_Chars val:'\n' span_id:409)
        )
      }
    )
    (command.Simple
      words: [{(cat)}]
      redirects: [
        (redir.Redir
          op: (Token id:Id.Redir_Great val:'>' span_id:418)
          fd: -1
          arg_word: {(DQ ($ Id.VSub_DollarName '$HOOK'))}
        )
        (redir.HereDoc
          op: (Token id:Id.Redir_DLess val:'<<' span_id:424)
          fd: -1
          here_begin: {(SQ (Token id:Id.Lit_Chars val:EOF span_id:426))}
          here_end_span_id: 432
          stdin_parts: [('#!/bin/sh\n') ('echo "new message" > "$1"\n') ('exit 0\n')]
        )
      ]
    )
    (C {(chmod)} {(Id.Lit_Other '+') (x)} {(DQ ($ Id.VSub_DollarName '$HOOK'))})
    (command.ShFunction
      name: commit_msg_is
      body: 
        (command.BraceGroup
          children: [
            (C {(test)} 
              {
                (DQ 
                  (command_sub
                    left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:454)
                    command_list: 
                      (command.CommandList
                        children: [
                          (C {(git)} {(log)} 
                            {(--pretty) (Id.Lit_Equals '=') (format) (Id.Lit_Other ':') 
                              (Id.Lit_Other '%') (s) (Id.Lit_Other '%') (b)
                            } {(-1)}
                          )
                        ]
                      )
                  )
                )
              } {(Id.Lit_Equals '=')} {(DQ ($ Id.VSub_Number '$1'))}
            )
          ]
        )
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'hook edits commit message' span_id:484))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:488) (Token id:Id.Lit_Chars val:'\n' span_id:489) 
          (Token id:Id.Lit_Chars val:'\techo "additional" >> file &&\n' span_id:490) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:491) 
          (Token id:Id.Lit_Chars val:'\tgit commit -m "additional" &&\n' span_id:492) (Token id:Id.Lit_Chars val:'\tcommit_msg_is "new message"\n' span_id:493) 
          (Token id:Id.Lit_Chars val:'\n' span_id:494)
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'hook edits commit message (editor)' span_id:501))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:505) (Token id:Id.Lit_Chars val:'\n' span_id:506) 
          (Token
            id: Id.Lit_Chars
            val: '\techo "additional content" >> file &&\n'
            span_id: 507
          ) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:508) 
          (Token
            id: Id.Lit_Chars
            val: '\techo "additional content" > FAKE_MSG &&\n'
            span_id: 509
          ) (Token id:Id.Lit_Chars val:'\tGIT_EDITOR="\\"\\$FAKE_EDITOR\\"" git commit &&\n' span_id:510) 
          (Token id:Id.Lit_Chars val:'\tcommit_msg_is "new message"\n' span_id:511) (Token id:Id.Lit_Chars val:'\n' span_id:512)
        )
      }
    )
    (C {(test_expect_success)} {(DQ ("hook doesn't edit commit message"))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:523) (Token id:Id.Lit_Chars val:'\n' span_id:524) 
          (Token id:Id.Lit_Chars val:'\techo "plus" >> file &&\n' span_id:525) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:526) 
          (Token id:Id.Lit_Chars val:'\tgit commit --no-verify -m "plus" &&\n' span_id:527) (Token id:Id.Lit_Chars val:'\tcommit_msg_is "plus"\n' span_id:528) 
          (Token id:Id.Lit_Chars val:'\n' span_id:529)
        )
      }
    )
    (C {(test_expect_success)} {(DQ ("hook doesn't edit commit message (editor)"))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:540) (Token id:Id.Lit_Chars val:'\n' span_id:541) 
          (Token id:Id.Lit_Chars val:'\techo "more plus" >> file &&\n' span_id:542) (Token id:Id.Lit_Chars val:'\tgit add file &&\n' span_id:543) 
          (Token id:Id.Lit_Chars val:'\techo "more plus" > FAKE_MSG &&\n' span_id:544) 
          (Token
            id: Id.Lit_Chars
            val: '\tGIT_EDITOR="\\"\\$FAKE_EDITOR\\"" git commit --no-verify &&\n'
            span_id: 545
          ) (Token id:Id.Lit_Chars val:'\tcommit_msg_is "more plus"\n' span_id:546) 
          (Token id:Id.Lit_Chars val:'\n' span_id:547)
        )
      }
    )
    (C {(test_done)})
  ]
)