(command.CommandList
  children: [
    (command.Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (lhs_expr.LhsName name:test_description spids:[21])
          op: Equal
          rhs: {(SQ <'concurrent git svn dcommit'>)}
          spids: [21]
        )
      ]
      spids: [21]
    )
    (C {(.)} {(./lib-git-svn.sh)})
    (C {(test_expect_success)} {(SQ <'setup svn repository'>)} 
      {
        (SQ <'\n'> <'\tsvn_cmd checkout "$svnrepo" work.svn &&\n'> <'\t(\n'> <'\t\tcd work.svn &&\n'> 
          <'\t\techo >file && echo > auto_updated_file\n'> <'\t\tsvn_cmd add file auto_updated_file &&\n'> <'\t\tsvn_cmd commit -m "initial commit"\n'> 
          <'\t) &&\n'> <'\tsvn_cmd checkout "$svnrepo" work-auto-commits.svn\n'>
        )
      }
    )
    (command.Assignment
      keyword: Assign_None
      pairs: [(assign_pair lhs:(lhs_expr.LhsName name:N spids:[51]) op:Equal rhs:{(0)} spids:[51])]
      spids: [51]
    )
    (command.FuncDef
      name: next_N
      body: 
        (command.BraceGroup
          children: [
            (command.Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (lhs_expr.LhsName name:N spids:[61])
                  op: Equal
                  rhs: 
                    {
                      (word_part.ArithSubPart
                        anode: 
                          (arith_expr.ArithBinary
                            op_id: Arith_Plus
                            left: (arith_expr.ArithWord w:{($ VSub_Name '$N')})
                            right: (arith_expr.ArithWord w:{(Lit_Digits 1)})
                          )
                        spids: [62 71]
                      )
                    }
                  spids: [61]
                )
              ]
              spids: [61]
            )
          ]
          spids: [58]
        )
      spids: [54 57]
    )
    (command.FuncDef
      name: setup_hook
      body: 
        (command.BraceGroup
          children: [
            (command.Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (lhs_expr.LhsName name:hook_type spids:[116])
                  op: Equal
                  rhs: {(DQ ($ VSub_Number '$1'))}
                  spids: [116]
                )
              ]
              spids: [116]
            )
            (command.Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (lhs_expr.LhsName name:skip_revs spids:[125])
                  op: Equal
                  rhs: {(DQ ($ VSub_Number '$2'))}
                  spids: [125]
                )
              ]
              spids: [125]
            )
            (command.AndOr
              ops: [Op_DPipe Op_DPipe]
              children: [
                (C {(Lit_Other '[')} {(DQ ($ VSub_Name '$hook_type'))} {(Lit_Other '=')} 
                  {(DQ (pre-commit))} {(Lit_Other ']')}
                )
                (C {(Lit_Other '[')} {(DQ ($ VSub_Name '$hook_type'))} {(Lit_Other '=')} 
                  {(DQ (post-commit))} {(Lit_Other ']')}
                )
                (command.BraceGroup
                  children: [
                    (command.Sentence
                      child: 
                        (command.SimpleCommand
                          words: [
                            {(echo)}
                            {(DQ ('ERROR: invalid argument (') ($ VSub_Name '$hook_type') (')'))}
                            {(DQ ('passed to setup_hook'))}
                          ]
                          redirects: [(redir.Redir op:<Redir_GreatAnd '>&'> fd:16777215 arg_word:{(2)})]
                        )
                      terminator: <Op_Semi ';'>
                    )
                    (command.Sentence
                      child: (command.ControlFlow token:<ControlFlow_Return return> arg_word:{(1)})
                      terminator: <Op_Semi ';'>
                    )
                  ]
                  spids: [165]
                )
              ]
            )
            (command.SimpleCommand
              words: [{(echo)} {(DQ ('cnt=') ($ VSub_Name '$skip_revs'))}]
              redirects: [
                (redir.Redir
                  op: <Redir_Great '>'>
                  fd: 16777215
                  arg_word: {(DQ ($ VSub_Name '$hook_type') (-counter))}
                )
              ]
            )
            (C {(rm)} {(-f)} {(DQ ($ VSub_Name '$rawsvnrepo') (/hooks/)) (Lit_Other '*') (-commit)})
            (command.Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (lhs_expr.LhsName name:hook spids:[224])
                  op: Equal
                  rhs: {(DQ ($ VSub_Name '$rawsvnrepo') (/hooks/) ($ VSub_Name '$hook_type'))}
                  spids: [224]
                )
              ]
              spids: [224]
            )
            (command.SimpleCommand
              words: [{(cat)}]
              redirects: [
                (redir.Redir
                  op: <Redir_Great '>'>
                  fd: 16777215
                  arg_word: {(DQ ($ VSub_Name '$hook'))}
                )
                (redir.HereDoc
                  op: <Redir_DLessDash '<<-'>
                  fd: 16777215
                  here_begin: {(SQ <EOF1>)}
                  here_end_span_id: 257
                  stdin_parts: [
                    ('#!/bin/sh\n')
                    ('set -e\n')
                    ('cd "$1/.."  # "$1" is repository location\n')
                    ('exec >> svn-hook.log 2>&1\n')
                    ('hook="$(basename "$0")"\n')
                    ('echo "*** Executing $hook $@"\n')
                    ('set -x\n')
                    ('. ./$hook-counter\n')
                    ('cnt="$(($cnt - 1))"\n')
                    ('echo "cnt=$cnt" > ./$hook-counter\n')
                    ('[ "$cnt" = "0" ] || exit 0\n')
                  ]
                )
              ]
            )
            (command.If
              arms: [
                (if_arm
                  cond: [
                    (command.Sentence
                      child: 
                        (C {(Lit_Other '[')} {(DQ ($ VSub_Name '$hook_type'))} {(Lit_Other '=')} 
                          {(DQ (pre-commit))} {(Lit_Other ']')}
                        )
                      terminator: <Op_Semi ';'>
                    )
                  ]
                  action: [
                    (command.SimpleCommand
                      words: [{(echo)} {(DQ ("echo 'commit disallowed' >&2; exit 1"))}]
                      redirects: [
                        (redir.Redir
                          op: <Redir_DGreat '>>'>
                          fd: 16777215
                          arg_word: {(DQ ($ VSub_Name '$hook'))}
                        )
                      ]
                    )
                  ]
                  spids: [16777215 276]
                )
              ]
              else_action: [
                (command.SimpleCommand
                  words: [
                    {(echo)}
                    {
                      (DQ ('PATH=') (word_part.EscapedLiteralPart token:<Lit_EscapedChar '\\"'>) 
                        ($ VSub_Name '$PATH') (word_part.EscapedLiteralPart token:<Lit_EscapedChar '\\"'>) ('; export PATH')
                      )
                    }
                  ]
                  redirects: [
                    (redir.Redir
                      op: <Redir_DGreat '>>'>
                      fd: 16777215
                      arg_word: {(DQ ($ VSub_Name '$hook'))}
                    )
                  ]
                )
                (command.SimpleCommand
                  words: [
                    {(echo)}
                    {
                      (DQ ('svnconf=') (word_part.EscapedLiteralPart token:<Lit_EscapedChar '\\"'>) 
                        ($ VSub_Name '$svnconf') (word_part.EscapedLiteralPart token:<Lit_EscapedChar '\\"'>)
                      )
                    }
                  ]
                  redirects: [
                    (redir.Redir
                      op: <Redir_DGreat '>>'>
                      fd: 16777215
                      arg_word: {(DQ ($ VSub_Name '$hook'))}
                    )
                  ]
                )
                (command.SimpleCommand
                  words: [{(cat)}]
                  redirects: [
                    (redir.Redir
                      op: <Redir_DGreat '>>'>
                      fd: 16777215
                      arg_word: {(DQ ($ VSub_Name '$hook'))}
                    )
                    (redir.HereDoc
                      op: <Redir_DLessDash '<<-'>
                      fd: 16777215
                      here_begin: {(SQ <EOF2>)}
                      here_end_span_id: 344
                      stdin_parts: [
                        ('cd work-auto-commits.svn\n')
                        ('svn up --config-dir "$svnconf"\n')
                        ('echo "$$" >> auto_updated_file\n')
                        ('svn commit --config-dir "$svnconf" \\\n')
                        ('-m "auto-committing concurrent change"\n')
                        ('exit 0\n')
                      ]
                    )
                  ]
                )
              ]
              spids: [291 346]
            )
            (C {(chmod)} {(755)} {(DQ ($ VSub_Name '$hook'))})
          ]
          spids: [113]
        )
      spids: [109 112]
    )
    (command.FuncDef
      name: check_contents
      body: 
        (command.BraceGroup
          children: [
            (command.Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (lhs_expr.LhsName name:gitdir spids:[367])
                  op: Equal
                  rhs: {(DQ ($ VSub_Number '$1'))}
                  spids: [367]
                )
              ]
              spids: [367]
            )
            (command.AndOr
              ops: [Op_DAmp Op_DAmp]
              children: [
                (command.Subshell
                  child: 
                    (command.AndOr
                      ops: [Op_DAmp]
                      children: [(C {(cd)} {(../work.svn)}) (C {(svn_cmd)} {(up)})]
                    )
                  spids: [373 383]
                )
                (C {(test_cmp)} {(file)} {(../work.svn/file)})
                (C {(test_cmp)} {(auto_updated_file)} {(../work.svn/auto_updated_file)})
              ]
            )
          ]
          spids: [364]
        )
      spids: [360 363]
    )
    (C {(test_expect_success)} {(SQ <'check if post-commit hook creates a concurrent commit'>)} 
      {
        (SQ <'\n'> <'\tsetup_hook post-commit 1 &&\n'> <'\t(\n'> <'\t\tcd work.svn &&\n'> 
          <'\t\tcp auto_updated_file au_file_saved &&\n'> <'\t\techo 1 >> file &&\n'> <'\t\tsvn_cmd commit -m "changing file" &&\n'> <'\t\tsvn_cmd up &&\n'> 
          <'\t\ttest_must_fail test_cmp auto_updated_file au_file_saved\n'> <'\t)\n'>
        )
      }
    )
    (C {(test_expect_success)} {(SQ <'check if pre-commit hook fails'>)} 
      {
        (SQ <'\n'> <'\tsetup_hook pre-commit 2 &&\n'> <'\t(\n'> <'\t\tcd work.svn &&\n'> 
          <'\t\techo 2 >> file &&\n'> <'\t\tsvn_cmd commit -m "changing file once again" &&\n'> <'\t\techo 3 >> file &&\n'> 
          <'\t\ttest_must_fail svn_cmd commit -m "this commit should fail" &&\n'> <'\t\tsvn_cmd revert file\n'> <'\t)\n'>
        )
      }
    )
    (C {(test_expect_success)} {(SQ <'dcommit error handling'>)} 
      {
        (SQ <'\n'> <'\tsetup_hook pre-commit 2 &&\n'> 
          <'\tnext_N && git svn clone "$svnrepo" work$N.git &&\n'> <'\t(\n'> <'\t\tcd work$N.git &&\n'> <'\t\techo 1 >> file && git commit -am "commit change $N.1" &&\n'> 
          <'\t\techo 2 >> file && git commit -am "commit change $N.2" &&\n'> <'\t\techo 3 >> file && git commit -am "commit change $N.3" &&\n'> 
          <'\t\t# should fail to dcommit 2nd and 3rd change\n'> <'\t\t# but still should leave the repository in reasonable state\n'> 
          <'\t\ttest_must_fail git svn dcommit &&\n'> <'\t\tgit update-index --refresh &&\n'> <'\t\tgit show HEAD~2   | grep -q git-svn-id &&\n'> 
          <'\t\t! git show HEAD~1 | grep -q git-svn-id &&\n'> <'\t\t! git show HEAD   | grep -q git-svn-id\n'> <'\t)\n'>
        )
      }
    )
    (C {(test_expect_success)} {(SQ <'dcommit concurrent change in non-changed file'>)} 
      {
        (SQ <'\n'> <'\tsetup_hook post-commit 2 &&\n'> 
          <'\tnext_N && git svn clone "$svnrepo" work$N.git &&\n'> <'\t(\n'> <'\t\tcd work$N.git &&\n'> <'\t\techo 1 >> file && git commit -am "commit change $N.1" &&\n'> 
          <'\t\techo 2 >> file && git commit -am "commit change $N.2" &&\n'> <'\t\techo 3 >> file && git commit -am "commit change $N.3" &&\n'> 
          <'\t\t# should rebase and leave the repository in reasonable state\n'> <'\t\tgit svn dcommit &&\n'> <'\t\tgit update-index --refresh &&\n'> <'\t\tcheck_contents &&\n'> 
          <'\t\tgit show HEAD~3 | grep -q git-svn-id &&\n'> <'\t\tgit show HEAD~2 | grep -q git-svn-id &&\n'> 
          <'\t\tgit show HEAD~1 | grep -q auto-committing &&\n'> <'\t\tgit show HEAD   | grep -q git-svn-id\n'> <'\t)\n'>
        )
      }
    )
    (command.FuncDef
      name: delete_first_line
      body: 
        (command.BraceGroup
          children: [
            (command.AndOr
              ops: [Op_DAmp Op_DAmp Op_DAmp]
              children: [
                (command.Assignment
                  keyword: Assign_None
                  pairs: [
                    (assign_pair
                      lhs: (lhs_expr.LhsName name:file spids:[509])
                      op: Equal
                      rhs: {(DQ ($ VSub_Number '$1'))}
                      spids: [509]
                    )
                  ]
                  spids: [509]
                )
                (command.SimpleCommand
                  words: [{(sed)} {(1d)}]
                  redirects: [
                    (redir.Redir
                      op: <Redir_Less '<'>
                      fd: 16777215
                      arg_word: {(DQ ($ VSub_Name '$file'))}
                    )
                    (redir.Redir
                      op: <Redir_Great '>'>
                      fd: 16777215
                      arg_word: {(DQ (${ VSub_Name file) (.tmp))}
                    )
                  ]
                )
                (C {(rm)} {(DQ ($ VSub_Name '$file'))})
                (C {(mv)} {(DQ (${ VSub_Name file) (.tmp))} {(DQ ($ VSub_Name '$file'))})
              ]
            )
          ]
          spids: [506]
        )
      spids: [502 505]
    )
    (C {(test_expect_success)} {(SQ <'dcommit concurrent non-conflicting change'>)} 
      {
        (SQ <'\n'> <'\tsetup_hook post-commit 2 &&\n'> 
          <'\tnext_N && git svn clone "$svnrepo" work$N.git &&\n'> <'\t(\n'> <'\t\tcd work$N.git &&\n'> <'\t\tcat file >> auto_updated_file &&\n'> 
          <'\t\t\tgit commit -am "commit change $N.1" &&\n'> <'\t\tdelete_first_line auto_updated_file &&\n'> <'\t\t\tgit commit -am "commit change $N.2" &&\n'> 
          <'\t\tdelete_first_line auto_updated_file &&\n'> <'\t\t\tgit commit -am "commit change $N.3" &&\n'> 
          <'\t\t# should rebase and leave the repository in reasonable state\n'> <'\t\tgit svn dcommit &&\n'> <'\t\tgit update-index --refresh &&\n'> <'\t\tcheck_contents &&\n'> 
          <'\t\tgit show HEAD~3 | grep -q git-svn-id &&\n'> <'\t\tgit show HEAD~2 | grep -q git-svn-id &&\n'> 
          <'\t\tgit show HEAD~1 | grep -q auto-committing &&\n'> <'\t\tgit show HEAD   | grep -q git-svn-id\n'> <'\t)\n'>
        )
      }
    )
    (C {(test_expect_success)} {(SQ <'dcommit --no-rebase concurrent non-conflicting change'>)} 
      {
        (SQ <'\n'> <'\tsetup_hook post-commit 2 &&\n'> 
          <'\tnext_N && git svn clone "$svnrepo" work$N.git &&\n'> <'\t(\n'> <'\t\tcd work$N.git &&\n'> <'\t\tcat file >> auto_updated_file &&\n'> 
          <'\t\t\tgit commit -am "commit change $N.1" &&\n'> <'\t\tdelete_first_line auto_updated_file &&\n'> <'\t\t\tgit commit -am "commit change $N.2" &&\n'> 
          <'\t\tdelete_first_line auto_updated_file &&\n'> <'\t\t\tgit commit -am "commit change $N.3" &&\n'> <'\t\t# should fail as rebase is needed\n'> 
          <'\t\ttest_must_fail git svn dcommit --no-rebase &&\n'> <'\t\t# but should leave HEAD unchanged\n'> <'\t\tgit update-index --refresh &&\n'> 
          <'\t\t! git show HEAD~2 | grep -q git-svn-id &&\n'> <'\t\t! git show HEAD~1 | grep -q git-svn-id &&\n'> <'\t\t! git show HEAD   | grep -q git-svn-id\n'> 
          <'\t)\n'>
        )
      }
    )
    (C {(test_expect_success)} {(SQ <'dcommit fails on concurrent conflicting change'>)} 
      {
        (SQ <'\n'> <'\tsetup_hook post-commit 1 &&\n'> 
          <'\tnext_N && git svn clone "$svnrepo" work$N.git &&\n'> <'\t(\n'> <'\t\tcd work$N.git &&\n'> <'\t\techo a >> file &&\n'> 
          <'\t\t\tgit commit -am "commit change $N.1" &&\n'> <'\t\techo b >> auto_updated_file &&\n'> <'\t\t\tgit commit -am "commit change $N.2" &&\n'> 
          <'\t\techo c >> auto_updated_file &&\n'> <'\t\t\tgit commit -am "commit change $N.3" &&\n'> 
          <'\t\ttest_must_fail git svn dcommit && # rebase should fail\n'> <'\t\ttest_must_fail git update-index --refresh\n'> <'\t)\n'>
        )
      }
    )
    (C {(test_done)})
  ]
)