(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:'concurrent git svn dcommit' span_id:15))} spids: [13] ) ] ) (C {(.)} {(./lib-git-svn.sh)}) (C {(test_expect_success)} {(SQ (Token id:Id.Lit_Chars val:'setup svn repository' span_id:28))} { (SQ (Token id:Id.Lit_Chars val:'\n' span_id:32) (Token id: Id.Lit_Chars val: '\tsvn_cmd checkout "$svnrepo" work.svn &&\n' span_id: 33 ) (Token id:Id.Lit_Chars val:'\t(\n' span_id:34) (Token id:Id.Lit_Chars val:'\t\tcd work.svn &&\n' span_id:35) (Token id:Id.Lit_Chars val:'\t\techo >file && echo > auto_updated_file\n' span_id:36) (Token id: Id.Lit_Chars val: '\t\tsvn_cmd add file auto_updated_file &&\n' span_id: 37 ) (Token id:Id.Lit_Chars val:'\t\tsvn_cmd commit -m "initial commit"\n' span_id:38) (Token id:Id.Lit_Chars val:'\t) &&\n' span_id:39) (Token id:Id.Lit_Chars val:'\tsvn_cmd checkout "$svnrepo" work-auto-commits.svn\n' span_id:40) ) } ) (command.ShAssignment pairs: [(assign_pair lhs:(sh_lhs_expr.Name name:N) op:assign_op.Equal rhs:{(0)} spids:[43])] ) (command.ShFunction name: next_N body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:N) op: assign_op.Equal rhs: { (word_part.ArithSub anode: (arith_expr.Binary op_id: Id.Arith_Plus left: (arith_expr.ArithWord w:{($ Id.VSub_DollarName '$N')}) right: (arith_expr.ArithWord w:{(Id.Lit_Digits 1)}) ) ) } spids: [53] ) ] ) ] ) ) (command.ShFunction name: setup_hook body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:hook_type) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_Number '$1'))} spids: [108] ) ] ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:skip_revs) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_Number '$2'))} spids: [117] ) ] ) (command.AndOr ops: [Id.Op_DPipe Id.Op_DPipe] children: [ (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$hook_type'))} {(Id.Lit_Equals '=')} {(DQ (pre-commit))} {(Id.Lit_RBracket ']')} ) (C {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$hook_type'))} {(Id.Lit_Equals '=')} {(DQ (post-commit))} {(Id.Lit_RBracket ']')} ) (command.BraceGroup children: [ (command.Sentence child: (command.Simple words: [ {(echo)} { (DQ ('ERROR: invalid argument (') ($ Id.VSub_DollarName '$hook_type') (')') ) } {(DQ ('passed to setup_hook'))} ] redirects: [ (redir.Redir op: (Token id:Id.Redir_GreatAnd val:'>&' span_id:173) fd: -1 arg_word: {(2)} ) ] ) terminator: (Token id:Id.Op_Semi val:';' span_id:176) ) (command.Sentence child: (command.ControlFlow token: (Token id:Id.ControlFlow_Return val:return span_id:178) arg_word: {(1)} ) terminator: (Token id:Id.Op_Semi val:';' span_id:181) ) ] ) ] ) (command.Simple words: [{(echo)} {(DQ ('cnt=') ($ Id.VSub_DollarName '$skip_revs'))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:193) fd: -1 arg_word: {(DQ ($ Id.VSub_DollarName '$hook_type') (-counter))} ) ] ) (C {(rm)} {(-f)} {(DQ ($ Id.VSub_DollarName '$rawsvnrepo') (/hooks/)) (Id.Lit_Star '*') (-commit)} ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:hook) op: assign_op.Equal rhs: { (DQ ($ Id.VSub_DollarName '$rawsvnrepo') (/hooks/) ($ Id.VSub_DollarName '$hook_type') ) } spids: [216] ) ] ) (command.Simple words: [{(cat)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:226) fd: -1 arg_word: {(DQ ($ Id.VSub_DollarName '$hook'))} ) (redir.HereDoc op: (Token id:Id.Redir_DLessDash val:'<<-' span_id:232) fd: -1 here_begin: {(SQ (Token id:Id.Lit_Chars val:EOF1 span_id:235))} here_end_span_id: 249 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 {(Id.Lit_LBracket '[')} {(DQ ($ Id.VSub_DollarName '$hook_type'))} {(Id.Lit_Equals '=')} {(DQ (pre-commit))} {(Id.Lit_RBracket ']')} ) terminator: (Token id:Id.Op_Semi val:';' span_id:266) ) ] action: [ (command.Simple words: [{(echo)} {(DQ ("echo 'commit disallowed' >&2; exit 1"))}] redirects: [ (redir.Redir op: (Token id:Id.Redir_DGreat val:'>>' span_id:277) fd: -1 arg_word: {(DQ ($ Id.VSub_DollarName '$hook'))} ) ] ) ] spids: [251 268] ) ] else_action: [ (command.Simple words: [ {(echo)} { (DQ ('PATH=') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:290) ) ($ Id.VSub_DollarName '$PATH') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:292) ) ('; export PATH') ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_DGreat val:'>>' span_id:296) fd: -1 arg_word: {(DQ ($ Id.VSub_DollarName '$hook'))} ) ] ) (command.Simple words: [ {(echo)} { (DQ ('svnconf=') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:306) ) ($ Id.VSub_DollarName '$svnconf') (word_part.EscapedLiteral token: (Token id:Id.Lit_EscapedChar val:'\\"' span_id:308) ) ) } ] redirects: [ (redir.Redir op: (Token id:Id.Redir_DGreat val:'>>' span_id:311) fd: -1 arg_word: {(DQ ($ Id.VSub_DollarName '$hook'))} ) ] ) (command.Simple words: [{(cat)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_DGreat val:'>>' span_id:319) fd: -1 arg_word: {(DQ ($ Id.VSub_DollarName '$hook'))} ) (redir.HereDoc op: (Token id:Id.Redir_DLessDash val:'<<-' span_id:324) fd: -1 here_begin: {(SQ (Token id:Id.Lit_Chars val:EOF2 span_id:327))} here_end_span_id: 336 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') ] ) ] ) ] ) (C {(chmod)} {(755)} {(DQ ($ Id.VSub_DollarName '$hook'))}) ] ) ) (command.ShFunction name: check_contents body: (command.BraceGroup children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:gitdir) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_Number '$1'))} spids: [359] ) ] ) (command.AndOr ops: [Id.Op_DAmp Id.Op_DAmp] children: [ (command.Subshell command_list: (command.CommandList children: [ (command.AndOr ops: [Id.Op_DAmp] children: [(C {(cd)} {(../work.svn)}) (C {(svn_cmd)} {(up)})] ) ] ) ) (C {(test_cmp)} {(file)} {(../work.svn/file)}) (C {(test_cmp)} {(auto_updated_file)} {(../work.svn/auto_updated_file)}) ] ) ] ) ) (C {(test_expect_success)} { (SQ (Token id: Id.Lit_Chars val: 'check if post-commit hook creates a concurrent commit' span_id: 401 ) ) } { (SQ (Token id:Id.Lit_Chars val:'\n' span_id:405) (Token id:Id.Lit_Chars val:'\tsetup_hook post-commit 1 &&\n' span_id:406) (Token id:Id.Lit_Chars val:'\t(\n' span_id:407) (Token id:Id.Lit_Chars val:'\t\tcd work.svn &&\n' span_id:408) (Token id:Id.Lit_Chars val:'\t\tcp auto_updated_file au_file_saved &&\n' span_id:409) (Token id:Id.Lit_Chars val:'\t\techo 1 >> file &&\n' span_id:410) (Token id:Id.Lit_Chars val:'\t\tsvn_cmd commit -m "changing file" &&\n' span_id:411) (Token id:Id.Lit_Chars val:'\t\tsvn_cmd up &&\n' span_id:412) (Token id: Id.Lit_Chars val: '\t\ttest_must_fail test_cmp auto_updated_file au_file_saved\n' span_id: 413 ) (Token id:Id.Lit_Chars val:'\t)\n' span_id:414) ) } ) (C {(test_expect_success)} {(SQ (Token id:Id.Lit_Chars val:'check if pre-commit hook fails' span_id:421))} { (SQ (Token id:Id.Lit_Chars val:'\n' span_id:425) (Token id:Id.Lit_Chars val:'\tsetup_hook pre-commit 2 &&\n' span_id:426) (Token id:Id.Lit_Chars val:'\t(\n' span_id:427) (Token id:Id.Lit_Chars val:'\t\tcd work.svn &&\n' span_id:428) (Token id:Id.Lit_Chars val:'\t\techo 2 >> file &&\n' span_id:429) (Token id: Id.Lit_Chars val: '\t\tsvn_cmd commit -m "changing file once again" &&\n' span_id: 430 ) (Token id:Id.Lit_Chars val:'\t\techo 3 >> file &&\n' span_id:431) (Token id: Id.Lit_Chars val: '\t\ttest_must_fail svn_cmd commit -m "this commit should fail" &&\n' span_id: 432 ) (Token id:Id.Lit_Chars val:'\t\tsvn_cmd revert file\n' span_id:433) (Token id:Id.Lit_Chars val:'\t)\n' span_id:434) ) } ) (C {(test_expect_success)} {(SQ (Token id:Id.Lit_Chars val:'dcommit error handling' span_id:441))} { (SQ (Token id:Id.Lit_Chars val:'\n' span_id:445) (Token id:Id.Lit_Chars val:'\tsetup_hook pre-commit 2 &&\n' span_id:446) (Token id:Id.Lit_Chars val:'\tnext_N && git svn clone "$svnrepo" work$N.git &&\n' span_id:447) (Token id:Id.Lit_Chars val:'\t(\n' span_id:448) (Token id:Id.Lit_Chars val:'\t\tcd work$N.git &&\n' span_id:449) (Token id: Id.Lit_Chars val: '\t\techo 1 >> file && git commit -am "commit change $N.1" &&\n' span_id: 450 ) (Token id: Id.Lit_Chars val: '\t\techo 2 >> file && git commit -am "commit change $N.2" &&\n' span_id: 451 ) (Token id: Id.Lit_Chars val: '\t\techo 3 >> file && git commit -am "commit change $N.3" &&\n' span_id: 452 ) (Token id:Id.Lit_Chars val:'\t\t# should fail to dcommit 2nd and 3rd change\n' span_id:453) (Token id: Id.Lit_Chars val: '\t\t# but still should leave the repository in reasonable state\n' span_id: 454 ) (Token id:Id.Lit_Chars val:'\t\ttest_must_fail git svn dcommit &&\n' span_id:455) (Token id:Id.Lit_Chars val:'\t\tgit update-index --refresh &&\n' span_id:456) (Token id:Id.Lit_Chars val:'\t\tgit show HEAD~2 | grep -q git-svn-id &&\n' span_id:457) (Token id: Id.Lit_Chars val: '\t\t! git show HEAD~1 | grep -q git-svn-id &&\n' span_id: 458 ) (Token id:Id.Lit_Chars val:'\t\t! git show HEAD | grep -q git-svn-id\n' span_id:459) (Token id:Id.Lit_Chars val:'\t)\n' span_id:460) ) } ) (C {(test_expect_success)} {(SQ (Token id:Id.Lit_Chars val:'dcommit concurrent change in non-changed file' span_id:467))} { (SQ (Token id:Id.Lit_Chars val:'\n' span_id:471) (Token id:Id.Lit_Chars val:'\tsetup_hook post-commit 2 &&\n' span_id:472) (Token id:Id.Lit_Chars val:'\tnext_N && git svn clone "$svnrepo" work$N.git &&\n' span_id:473) (Token id:Id.Lit_Chars val:'\t(\n' span_id:474) (Token id:Id.Lit_Chars val:'\t\tcd work$N.git &&\n' span_id:475) (Token id: Id.Lit_Chars val: '\t\techo 1 >> file && git commit -am "commit change $N.1" &&\n' span_id: 476 ) (Token id: Id.Lit_Chars val: '\t\techo 2 >> file && git commit -am "commit change $N.2" &&\n' span_id: 477 ) (Token id: Id.Lit_Chars val: '\t\techo 3 >> file && git commit -am "commit change $N.3" &&\n' span_id: 478 ) (Token id: Id.Lit_Chars val: '\t\t# should rebase and leave the repository in reasonable state\n' span_id: 479 ) (Token id:Id.Lit_Chars val:'\t\tgit svn dcommit &&\n' span_id:480) (Token id:Id.Lit_Chars val:'\t\tgit update-index --refresh &&\n' span_id:481) (Token id:Id.Lit_Chars val:'\t\tcheck_contents &&\n' span_id:482) (Token id: Id.Lit_Chars val: '\t\tgit show HEAD~3 | grep -q git-svn-id &&\n' span_id: 483 ) (Token id:Id.Lit_Chars val:'\t\tgit show HEAD~2 | grep -q git-svn-id &&\n' span_id:484) (Token id: Id.Lit_Chars val: '\t\tgit show HEAD~1 | grep -q auto-committing &&\n' span_id: 485 ) (Token id:Id.Lit_Chars val:'\t\tgit show HEAD | grep -q git-svn-id\n' span_id:486) (Token id:Id.Lit_Chars val:'\t)\n' span_id:487) ) } ) (command.ShFunction name: delete_first_line body: (command.BraceGroup children: [ (command.AndOr ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp] children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:file) op: assign_op.Equal rhs: {(DQ ($ Id.VSub_Number '$1'))} spids: [501] ) ] ) (command.Simple words: [{(sed)} {(1d)}] redirects: [ (redir.Redir op: (Token id:Id.Redir_Less val:'<' span_id:513) fd: -1 arg_word: {(DQ ($ Id.VSub_DollarName '$file'))} ) (redir.Redir op: (Token id:Id.Redir_Great val:'>' span_id:519) fd: -1 arg_word: {(DQ (${ Id.VSub_Name file) (.tmp))} ) ] ) (C {(rm)} {(DQ ($ Id.VSub_DollarName '$file'))}) (C {(mv)} {(DQ (${ Id.VSub_Name file) (.tmp))} {(DQ ($ Id.VSub_DollarName '$file'))}) ] ) ] ) ) (C {(test_expect_success)} {(SQ (Token id:Id.Lit_Chars val:'dcommit concurrent non-conflicting change' span_id:559))} { (SQ (Token id:Id.Lit_Chars val:'\n' span_id:563) (Token id:Id.Lit_Chars val:'\tsetup_hook post-commit 2 &&\n' span_id:564) (Token id:Id.Lit_Chars val:'\tnext_N && git svn clone "$svnrepo" work$N.git &&\n' span_id:565) (Token id:Id.Lit_Chars val:'\t(\n' span_id:566) (Token id:Id.Lit_Chars val:'\t\tcd work$N.git &&\n' span_id:567) (Token id:Id.Lit_Chars val:'\t\tcat file >> auto_updated_file &&\n' span_id:568) (Token id:Id.Lit_Chars val:'\t\t\tgit commit -am "commit change $N.1" &&\n' span_id:569) (Token id: Id.Lit_Chars val: '\t\tdelete_first_line auto_updated_file &&\n' span_id: 570 ) (Token id:Id.Lit_Chars val:'\t\t\tgit commit -am "commit change $N.2" &&\n' span_id:571) (Token id: Id.Lit_Chars val: '\t\tdelete_first_line auto_updated_file &&\n' span_id: 572 ) (Token id:Id.Lit_Chars val:'\t\t\tgit commit -am "commit change $N.3" &&\n' span_id:573) (Token id: Id.Lit_Chars val: '\t\t# should rebase and leave the repository in reasonable state\n' span_id: 574 ) (Token id:Id.Lit_Chars val:'\t\tgit svn dcommit &&\n' span_id:575) (Token id:Id.Lit_Chars val:'\t\tgit update-index --refresh &&\n' span_id:576) (Token id:Id.Lit_Chars val:'\t\tcheck_contents &&\n' span_id:577) (Token id: Id.Lit_Chars val: '\t\tgit show HEAD~3 | grep -q git-svn-id &&\n' span_id: 578 ) (Token id:Id.Lit_Chars val:'\t\tgit show HEAD~2 | grep -q git-svn-id &&\n' span_id:579) (Token id: Id.Lit_Chars val: '\t\tgit show HEAD~1 | grep -q auto-committing &&\n' span_id: 580 ) (Token id:Id.Lit_Chars val:'\t\tgit show HEAD | grep -q git-svn-id\n' span_id:581) (Token id:Id.Lit_Chars val:'\t)\n' span_id:582) ) } ) (C {(test_expect_success)} { (SQ (Token id: Id.Lit_Chars val: 'dcommit --no-rebase concurrent non-conflicting change' span_id: 589 ) ) } { (SQ (Token id:Id.Lit_Chars val:'\n' span_id:593) (Token id:Id.Lit_Chars val:'\tsetup_hook post-commit 2 &&\n' span_id:594) (Token id:Id.Lit_Chars val:'\tnext_N && git svn clone "$svnrepo" work$N.git &&\n' span_id:595) (Token id:Id.Lit_Chars val:'\t(\n' span_id:596) (Token id:Id.Lit_Chars val:'\t\tcd work$N.git &&\n' span_id:597) (Token id:Id.Lit_Chars val:'\t\tcat file >> auto_updated_file &&\n' span_id:598) (Token id:Id.Lit_Chars val:'\t\t\tgit commit -am "commit change $N.1" &&\n' span_id:599) (Token id: Id.Lit_Chars val: '\t\tdelete_first_line auto_updated_file &&\n' span_id: 600 ) (Token id:Id.Lit_Chars val:'\t\t\tgit commit -am "commit change $N.2" &&\n' span_id:601) (Token id: Id.Lit_Chars val: '\t\tdelete_first_line auto_updated_file &&\n' span_id: 602 ) (Token id:Id.Lit_Chars val:'\t\t\tgit commit -am "commit change $N.3" &&\n' span_id:603) (Token id:Id.Lit_Chars val:'\t\t# should fail as rebase is needed\n' span_id:604) (Token id:Id.Lit_Chars val:'\t\ttest_must_fail git svn dcommit --no-rebase &&\n' span_id:605) (Token id:Id.Lit_Chars val:'\t\t# but should leave HEAD unchanged\n' span_id:606) (Token id:Id.Lit_Chars val:'\t\tgit update-index --refresh &&\n' span_id:607) (Token id: Id.Lit_Chars val: '\t\t! git show HEAD~2 | grep -q git-svn-id &&\n' span_id: 608 ) (Token id:Id.Lit_Chars val:'\t\t! git show HEAD~1 | grep -q git-svn-id &&\n' span_id:609) (Token id: Id.Lit_Chars val: '\t\t! git show HEAD | grep -q git-svn-id\n' span_id: 610 ) (Token id:Id.Lit_Chars val:'\t)\n' span_id:611) ) } ) (C {(test_expect_success)} {(SQ (Token id:Id.Lit_Chars val:'dcommit fails on concurrent conflicting change' span_id:618))} { (SQ (Token id:Id.Lit_Chars val:'\n' span_id:622) (Token id:Id.Lit_Chars val:'\tsetup_hook post-commit 1 &&\n' span_id:623) (Token id:Id.Lit_Chars val:'\tnext_N && git svn clone "$svnrepo" work$N.git &&\n' span_id:624) (Token id:Id.Lit_Chars val:'\t(\n' span_id:625) (Token id:Id.Lit_Chars val:'\t\tcd work$N.git &&\n' span_id:626) (Token id:Id.Lit_Chars val:'\t\techo a >> file &&\n' span_id:627) (Token id:Id.Lit_Chars val:'\t\t\tgit commit -am "commit change $N.1" &&\n' span_id:628) (Token id:Id.Lit_Chars val:'\t\techo b >> auto_updated_file &&\n' span_id:629) (Token id:Id.Lit_Chars val:'\t\t\tgit commit -am "commit change $N.2" &&\n' span_id:630) (Token id:Id.Lit_Chars val:'\t\techo c >> auto_updated_file &&\n' span_id:631) (Token id:Id.Lit_Chars val:'\t\t\tgit commit -am "commit change $N.3" &&\n' span_id:632) (Token id: Id.Lit_Chars val: '\t\ttest_must_fail git svn dcommit && # rebase should fail\n' span_id: 633 ) (Token id:Id.Lit_Chars val:'\t\ttest_must_fail git update-index --refresh\n' span_id:634) (Token id:Id.Lit_Chars val:'\t)\n' span_id:635) ) } ) (C {(test_done)}) ] )