(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: 'paths written by git-apply cannot escape the working tree'
                  span_id: 6
                )
              )
            }
          spids: [4]
        )
      ]
    )
    (C {(.)} {(./test-lib.sh)})
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'bump git repo one level down' span_id:26))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:30) 
          (Token id:Id.Lit_Chars val:'\tmkdir inside &&\n' span_id:31) (Token id:Id.Lit_Chars val:'\tmv .git inside/ &&\n' span_id:32) 
          (Token id:Id.Lit_Chars val:'\tcd inside\n' span_id:33)
        )
      }
    )
    (command.ShFunction
      name: mkpatch_add
      body: 
        (command.BraceGroup
          children: [
            (command.AndOr
              ops: [Id.Op_DAmp]
              children: [
                (C {(rm)} {(-f)} 
                  {
                    (DQ 
                      (braced_var_sub
                        token: (Token id:Id.VSub_Number val:2 span_id:57)
                        suffix_op: 
                          (suffix_op.Unary
                            op_id: Id.VTest_ColonHyphen
                            arg_word: {($ Id.VSub_Number '$1')}
                          )
                      )
                    )
                  }
                )
                (command.Simple
                  words: [{(cat)}]
                  redirects: [
                    (redir.HereDoc
                      op: (Token id:Id.Redir_DLessDash val:'<<-' span_id:68)
                      fd: -1
                      here_begin: {(EOF)}
                      here_end_span_id: 85
                      stdin_parts: [
                        ('diff --git a/')
                        ($ Id.VSub_Number '$1')
                        (' b/')
                        ($ Id.VSub_Number '$1')
                        ('\n')
                        ('new file mode 100644\n')
                        ('index 0000000..53c74cd\n')
                        ('--- /dev/null\n')
                        ('+++ b/')
                        ($ Id.VSub_Number '$1')
                        ('\n')
                        ('@@ -0,0 +1 @@\n')
                        ('+evil\n')
                      ]
                    )
                  ]
                )
              ]
            )
          ]
        )
    )
    (command.ShFunction
      name: mkpatch_del
      body: 
        (command.BraceGroup
          children: [
            (command.AndOr
              ops: [Id.Op_DAmp]
              children: [
                (command.Simple
                  words: [{(echo)} {(evil)}]
                  redirects: [
                    (redir.Redir
                      op: (Token id:Id.Redir_Great val:'>' span_id:101)
                      fd: -1
                      arg_word: 
                        {
                          (DQ 
                            (braced_var_sub
                              token: (Token id:Id.VSub_Number val:2 span_id:104)
                              suffix_op: 
                                (suffix_op.Unary
                                  op_id: Id.VTest_ColonHyphen
                                  arg_word: {($ Id.VSub_Number '$1')}
                                )
                            )
                          )
                        }
                    )
                  ]
                )
                (command.Simple
                  words: [{(cat)}]
                  redirects: [
                    (redir.HereDoc
                      op: (Token id:Id.Redir_DLessDash val:'<<-' span_id:115)
                      fd: -1
                      here_begin: {(EOF)}
                      here_end_span_id: 132
                      stdin_parts: [
                        ('diff --git a/')
                        ($ Id.VSub_Number '$1')
                        (' b/')
                        ($ Id.VSub_Number '$1')
                        ('\n')
                        ('deleted file mode 100644\n')
                        ('index 53c74cd..0000000\n')
                        ('--- a/')
                        ($ Id.VSub_Number '$1')
                        ('\n')
                        ('+++ /dev/null\n')
                        ('@@ -1 +0,0 @@\n')
                        ('-evil\n')
                      ]
                    )
                  ]
                )
              ]
            )
          ]
        )
    )
    (command.ShFunction
      name: mkpatch_symlink
      body: 
        (command.BraceGroup
          children: [
            (command.AndOr
              ops: [Id.Op_DAmp]
              children: [
                (C {(rm)} {(-f)} {(DQ ($ Id.VSub_Number '$1'))})
                (command.Simple
                  words: [{(cat)}]
                  redirects: [
                    (redir.HereDoc
                      op: (Token id:Id.Redir_DLessDash val:'<<-' span_id:163)
                      fd: -1
                      here_begin: {(EOF)}
                      here_end_span_id: 204
                      stdin_parts: [
                        ('diff --git a/')
                        ($ Id.VSub_Number '$1')
                        (' b/')
                        ($ Id.VSub_Number '$1')
                        ('\n')
                        ('new file mode 120000\n')
                        ('index 0000000..')
                        (command_sub
                          left_token: (Token id:Id.Left_DollarParen val:'$(' span_id:173)
                          command_list: 
                            (command.CommandList
                              children: [
                                (command.Pipeline
                                  children: [
                                    (C {(printf)} {(DQ ('%s'))} {(DQ ($ Id.VSub_Number '$2'))})
                                    (C {(git)} {(hash-object)} {(--stdin)})
                                  ]
                                  negated: F
                                )
                              ]
                            )
                        )
                        ('\n')
                        ('--- /dev/null\n')
                        ('+++ b/')
                        ($ Id.VSub_Number '$1')
                        ('\n')
                        ('@@ -0,0 +1 @@\n')
                        ('+')
                        ($ Id.VSub_Number '$2')
                        ('\n')
                        (Id.Lit_Other '\\')
                        (' No newline at end of file\n')
                      ]
                    )
                  ]
                )
              ]
            )
          ]
        )
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'cannot create file containing ..' span_id:211))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:215) 
          (Token id:Id.Lit_Chars val:'\tmkpatch_add ../foo >patch &&\n' span_id:216) (Token id:Id.Lit_Chars val:'\ttest_must_fail git apply patch &&\n' span_id:217) 
          (Token id:Id.Lit_Chars val:'\ttest_path_is_missing ../foo\n' span_id:218)
        )
      }
    )
    (C {(test_expect_success)} 
      {
        (SQ 
          (Token
            id: Id.Lit_Chars
            val: 'can create file containing .. with --unsafe-paths'
            span_id: 225
          )
        )
      } 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:229) 
          (Token id:Id.Lit_Chars val:'\tmkpatch_add ../foo >patch &&\n' span_id:230) (Token id:Id.Lit_Chars val:'\tgit apply --unsafe-paths patch &&\n' span_id:231) 
          (Token id:Id.Lit_Chars val:'\ttest_path_is_file ../foo\n' span_id:232)
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'cannot create file containing .. (index)' span_id:239))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:243) 
          (Token id:Id.Lit_Chars val:'\tmkpatch_add ../foo >patch &&\n' span_id:244) (Token id:Id.Lit_Chars val:'\ttest_must_fail git apply --index patch &&\n' span_id:245) 
          (Token id:Id.Lit_Chars val:'\ttest_path_is_missing ../foo\n' span_id:246)
        )
      }
    )
    (C {(test_expect_success)} 
      {
        (SQ 
          (Token
            id: Id.Lit_Chars
            val: 'cannot create file containing .. with --unsafe-paths (index)'
            span_id: 253
          )
        )
      } 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:257) 
          (Token id:Id.Lit_Chars val:'\tmkpatch_add ../foo >patch &&\n' span_id:258) 
          (Token
            id: Id.Lit_Chars
            val: '\ttest_must_fail git apply --index --unsafe-paths patch &&\n'
            span_id: 259
          ) (Token id:Id.Lit_Chars val:'\ttest_path_is_missing ../foo\n' span_id:260)
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'cannot delete file containing ..' span_id:267))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:271) 
          (Token id:Id.Lit_Chars val:'\tmkpatch_del ../foo >patch &&\n' span_id:272) (Token id:Id.Lit_Chars val:'\ttest_must_fail git apply patch &&\n' span_id:273) 
          (Token id:Id.Lit_Chars val:'\ttest_path_is_file ../foo\n' span_id:274)
        )
      }
    )
    (C {(test_expect_success)} 
      {
        (SQ 
          (Token
            id: Id.Lit_Chars
            val: 'can delete file containing .. with --unsafe-paths'
            span_id: 281
          )
        )
      } 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:285) 
          (Token id:Id.Lit_Chars val:'\tmkpatch_del ../foo >patch &&\n' span_id:286) (Token id:Id.Lit_Chars val:'\tgit apply --unsafe-paths patch &&\n' span_id:287) 
          (Token id:Id.Lit_Chars val:'\ttest_path_is_missing ../foo\n' span_id:288)
        )
      }
    )
    (C {(test_expect_success)} 
      {(SQ (Token id:Id.Lit_Chars val:'cannot delete file containing .. (index)' span_id:295))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:299) 
          (Token id:Id.Lit_Chars val:'\tmkpatch_del ../foo >patch &&\n' span_id:300) (Token id:Id.Lit_Chars val:'\ttest_must_fail git apply --index patch &&\n' span_id:301) 
          (Token id:Id.Lit_Chars val:'\ttest_path_is_file ../foo\n' span_id:302)
        )
      }
    )
    (C {(test_expect_success)} {(SYMLINKS)} 
      {(SQ (Token id:Id.Lit_Chars val:'symlink escape via ..' span_id:311))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:315) 
          (Token id:Id.Lit_Chars val:'\t{\n' span_id:316) (Token id:Id.Lit_Chars val:'\t\tmkpatch_symlink tmp .. &&\n' span_id:317) 
          (Token id:Id.Lit_Chars val:'\t\tmkpatch_add tmp/foo ../foo\n' span_id:318) (Token id:Id.Lit_Chars val:'\t} >patch &&\n' span_id:319) 
          (Token id:Id.Lit_Chars val:'\ttest_must_fail git apply patch &&\n' span_id:320) (Token id:Id.Lit_Chars val:'\ttest_path_is_missing tmp &&\n' span_id:321) 
          (Token id:Id.Lit_Chars val:'\ttest_path_is_missing ../foo\n' span_id:322)
        )
      }
    )
    (C {(test_expect_success)} {(SYMLINKS)} 
      {(SQ (Token id:Id.Lit_Chars val:'symlink escape via .. (index)' span_id:331))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:335) 
          (Token id:Id.Lit_Chars val:'\t{\n' span_id:336) (Token id:Id.Lit_Chars val:'\t\tmkpatch_symlink tmp .. &&\n' span_id:337) 
          (Token id:Id.Lit_Chars val:'\t\tmkpatch_add tmp/foo ../foo\n' span_id:338) (Token id:Id.Lit_Chars val:'\t} >patch &&\n' span_id:339) 
          (Token
            id: Id.Lit_Chars
            val: '\ttest_must_fail git apply --index patch &&\n'
            span_id: 340
          ) (Token id:Id.Lit_Chars val:'\ttest_path_is_missing tmp &&\n' span_id:341) 
          (Token id:Id.Lit_Chars val:'\ttest_path_is_missing ../foo\n' span_id:342)
        )
      }
    )
    (C {(test_expect_success)} {(SYMLINKS)} 
      {(SQ (Token id:Id.Lit_Chars val:'symlink escape via absolute path' span_id:351))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:355) 
          (Token id:Id.Lit_Chars val:'\t{\n' span_id:356) (Token id:Id.Lit_Chars val:'\t\tmkpatch_symlink tmp "$(pwd)" &&\n' span_id:357) 
          (Token id:Id.Lit_Chars val:'\t\tmkpatch_add tmp/foo ../foo\n' span_id:358) (Token id:Id.Lit_Chars val:'\t} >patch &&\n' span_id:359) 
          (Token id:Id.Lit_Chars val:'\ttest_must_fail git apply patch &&\n' span_id:360) (Token id:Id.Lit_Chars val:'\ttest_path_is_missing tmp &&\n' span_id:361) 
          (Token id:Id.Lit_Chars val:'\ttest_path_is_missing ../foo\n' span_id:362)
        )
      }
    )
    (C {(test_expect_success)} {(SYMLINKS)} 
      {(SQ (Token id:Id.Lit_Chars val:'symlink escape via absolute path (index)' span_id:371))} 
      {
        (SQ (Token id:Id.Lit_Chars val:'\n' span_id:375) 
          (Token id:Id.Lit_Chars val:'\t{\n' span_id:376) (Token id:Id.Lit_Chars val:'\t\tmkpatch_symlink tmp "$(pwd)" &&\n' span_id:377) 
          (Token id:Id.Lit_Chars val:'\t\tmkpatch_add tmp/foo ../foo\n' span_id:378) (Token id:Id.Lit_Chars val:'\t} >patch &&\n' span_id:379) 
          (Token
            id: Id.Lit_Chars
            val: '\ttest_must_fail git apply --index patch &&\n'
            span_id: 380
          ) (Token id:Id.Lit_Chars val:'\ttest_path_is_missing tmp &&\n' span_id:381) 
          (Token id:Id.Lit_Chars val:'\ttest_path_is_missing ../foo\n' span_id:382)
        )
      }
    )
    (C {(test_done)})
  ]
)