(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)}) ] )