(CommandList
  children: [
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:test_description)
          op: Equal
          rhs: {(SQ <"concurrent git svn dcommit">)}
          spids: [13]
        )
      ]
      spids: [13]
    )
    (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">
        )
      }
    )
    (Assignment
      keyword: Assign_None
      pairs: [(assign_pair lhs:(LhsName name:N) op:Equal rhs:{(0)} spids:[43])]
      spids: [43]
    )
    (FuncDef
      name: next_N
      body: 
        (BraceGroup
          children: [
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:N)
                  op: Equal
                  rhs: 
                    {
                      (ArithSubPart
                        anode: 
                          (ArithBinary
                            op_id: Arith_Plus
                            left: (ArithWord w:{($ VSub_Name "$N")})
                            right: (ArithWord w:{(Lit_Digits 1)})
                          )
                        spids: [54 63]
                      )
                    }
                  spids: [53]
                )
              ]
              spids: [53]
            )
          ]
          spids: [50]
        )
      spids: [46 49]
    )
    (FuncDef
      name: setup_hook
      body: 
        (BraceGroup
          children: [
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:hook_type)
                  op: Equal
                  rhs: {(DQ ($ VSub_Number "$1"))}
                  spids: [108]
                )
              ]
              spids: [108]
            )
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:skip_revs)
                  op: Equal
                  rhs: {(DQ ($ VSub_Number "$2"))}
                  spids: [117]
                )
              ]
              spids: [117]
            )
            (AndOr
              children: [
                (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$hook_type"))} {(Lit_Other "=")} 
                  {(DQ (pre-commit))} {(Lit_Other "]")}
                )
                (AndOr
                  children: [
                    (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$hook_type"))} {(Lit_Other "=")} 
                      {(DQ (post-commit))} {(Lit_Other "]")}
                    )
                    (BraceGroup
                      children: [
                        (Sentence
                          child: 
                            (SimpleCommand
                              words: [
                                {(echo)}
                                {(DQ ("ERROR: invalid argument (") ($ VSub_Name "$hook_type") (")"))}
                                {(DQ ("passed to setup_hook"))}
                              ]
                              redirects: [
                                (Redir
                                  op_id: Redir_GreatAnd
                                  fd: -1
                                  arg_word: {(2)}
                                  spids: [173]
                                )
                              ]
                            )
                          terminator: <Op_Semi ";">
                        )
                        (Sentence
                          child: (ControlFlow token:<ControlFlow_Return return> arg_word:{(1)})
                          terminator: <Op_Semi ";">
                        )
                      ]
                      spids: [157]
                    )
                  ]
                  op_id: Op_DPipe
                )
              ]
              op_id: Op_DPipe
            )
            (SimpleCommand
              words: [{(echo)} {(DQ ("cnt=") ($ VSub_Name "$skip_revs"))}]
              redirects: [
                (Redir
                  op_id: Redir_Great
                  fd: -1
                  arg_word: {(DQ ($ VSub_Name "$hook_type") (-counter))}
                  spids: [193]
                )
              ]
            )
            (C {(rm)} {(-f)} {(DQ ($ VSub_Name "$rawsvnrepo") (/hooks/)) (Lit_Other "*") (-commit)})
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:hook)
                  op: Equal
                  rhs: {(DQ ($ VSub_Name "$rawsvnrepo") (/hooks/) ($ VSub_Name "$hook_type"))}
                  spids: [216]
                )
              ]
              spids: [216]
            )
            (SimpleCommand
              words: [{(cat)}]
              redirects: [
                (Redir
                  op_id: Redir_Great
                  fd: -1
                  arg_word: {(DQ ($ VSub_Name "$hook"))}
                  spids: [226]
                )
                (HereDoc
                  op_id: Redir_DLessDash
                  fd: -1
                  body: 
                    {("#!/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")
                    }
                  do_expansion: False
                  here_end: EOF1
                  was_filled: True
                  spids: [232]
                )
              ]
            )
            (If
              arms: [
                (if_arm
                  cond: [
                    (Sentence
                      child: 
                        (C {(Lit_Other "[")} {(DQ ($ VSub_Name "$hook_type"))} {(Lit_Other "=")} 
                          {(DQ (pre-commit))} {(Lit_Other "]")}
                        )
                      terminator: <Op_Semi ";">
                    )
                  ]
                  action: [
                    (SimpleCommand
                      words: [{(echo)} {(DQ ("echo 'commit disallowed' >&2; exit 1"))}]
                      redirects: [
                        (Redir
                          op_id: Redir_DGreat
                          fd: -1
                          arg_word: {(DQ ($ VSub_Name "$hook"))}
                          spids: [265]
                        )
                      ]
                    )
                  ]
                  spids: [-1 256]
                )
              ]
              else_action: [
                (SimpleCommand
                  words: [
                    {(echo)}
                    {
                      (DQ ("PATH=") (EscapedLiteralPart token:<Lit_EscapedChar "\\\"">) 
                        ($ VSub_Name "$PATH") (EscapedLiteralPart token:<Lit_EscapedChar "\\\"">) ("; export PATH")
                      )
                    }
                  ]
                  redirects: [
                    (Redir
                      op_id: Redir_DGreat
                      fd: -1
                      arg_word: {(DQ ($ VSub_Name "$hook"))}
                      spids: [284]
                    )
                  ]
                )
                (SimpleCommand
                  words: [
                    {(echo)}
                    {
                      (DQ ("svnconf=") (EscapedLiteralPart token:<Lit_EscapedChar "\\\"">) 
                        ($ VSub_Name "$svnconf") (EscapedLiteralPart token:<Lit_EscapedChar "\\\"">)
                      )
                    }
                  ]
                  redirects: [
                    (Redir
                      op_id: Redir_DGreat
                      fd: -1
                      arg_word: {(DQ ($ VSub_Name "$hook"))}
                      spids: [299]
                    )
                  ]
                )
                (SimpleCommand
                  words: [{(cat)}]
                  redirects: [
                    (Redir
                      op_id: Redir_DGreat
                      fd: -1
                      arg_word: {(DQ ($ VSub_Name "$hook"))}
                      spids: [307]
                    )
                    (HereDoc
                      op_id: Redir_DLessDash
                      fd: -1
                      body: 
                        {("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")
                        }
                      do_expansion: False
                      here_end: EOF2
                      was_filled: True
                      spids: [312]
                    )
                  ]
                )
              ]
              spids: [271 319]
            )
            (C {(chmod)} {(755)} {(DQ ($ VSub_Name "$hook"))})
          ]
          spids: [105]
        )
      spids: [101 104]
    )
    (FuncDef
      name: check_contents
      body: 
        (BraceGroup
          children: [
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:gitdir)
                  op: Equal
                  rhs: {(DQ ($ VSub_Number "$1"))}
                  spids: [340]
                )
              ]
              spids: [340]
            )
            (AndOr
              children: [
                (Subshell
                  child: 
                    (AndOr
                      children: [(C {(cd)} {(../work.svn)}) (C {(svn_cmd)} {(up)})]
                      op_id: Op_DAmp
                    )
                  spids: [346 356]
                )
                (AndOr
                  children: [
                    (C {(test_cmp)} {(file)} {(../work.svn/file)})
                    (C {(test_cmp)} {(auto_updated_file)} {(../work.svn/auto_updated_file)})
                  ]
                  op_id: Op_DAmp
                )
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [337]
        )
      spids: [333 336]
    )
    (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">
        )
      }
    )
    (FuncDef
      name: delete_first_line
      body: 
        (BraceGroup
          children: [
            (AndOr
              children: [
                (Assignment
                  keyword: Assign_None
                  pairs: [
                    (assign_pair
                      lhs: (LhsName name:file)
                      op: Equal
                      rhs: {(DQ ($ VSub_Number "$1"))}
                      spids: [482]
                    )
                  ]
                  spids: [482]
                )
                (AndOr
                  children: [
                    (SimpleCommand
                      words: [{(sed)} {(1d)}]
                      redirects: [
                        (Redir
                          op_id: Redir_Less
                          fd: -1
                          arg_word: {(DQ ($ VSub_Name "$file"))}
                          spids: [494]
                        )
                        (Redir
                          op_id: Redir_Great
                          fd: -1
                          arg_word: {(DQ (${ VSub_Name file) (.tmp))}
                          spids: [500]
                        )
                      ]
                    )
                    (AndOr
                      children: [
                        (C {(rm)} {(DQ ($ VSub_Name "$file"))})
                        (C {(mv)} {(DQ (${ VSub_Name file) (.tmp))} {(DQ ($ VSub_Name "$file"))})
                      ]
                      op_id: Op_DAmp
                    )
                  ]
                  op_id: Op_DAmp
                )
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [479]
        )
      spids: [475 478]
    )
    (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)})
  ]
)