(CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"test fetching over git protocol">)} spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (C {(.)} {(DQ ($ VSub_Name "$TEST_DIRECTORY")) (/lib-git-daemon.sh)}) (C {(start_git_daemon)}) (FuncDef name: check_verbose_connect body: (BraceGroup children: [ (AndOr children: [ (C {(grep)} {(-F)} {(DQ ("Looking up 127.0.0.1 ..."))} {(stderr)}) (AndOr children: [ (C {(grep)} {(-F)} {(DQ ("Connecting to 127.0.0.1 (port "))} {(stderr)}) (C {(grep)} {(-F)} {(DQ (done.))} {(stderr)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [29] ) spids: [24 28] ) (C {(test_expect_success)} {(SQ <"setup repository">)} { (SQ <"\n"> <"\tgit config push.default matching &&\n"> <"\techo content >file &&\n"> <"\tgit add file &&\n"> <"\tgit commit -m one\n"> ) } ) (C {(test_expect_success)} {(SQ <"create git-accessible bare repository">)} { (SQ <"\n"> <"\tmkdir \"$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git\" &&\n"> <"\t(cd \"$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git\" &&\n"> <"\t git --bare init &&\n"> <"\t : >git-daemon-export-ok\n"> <"\t) &&\n"> <"\tgit remote add public \"$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git\" &&\n"> <"\tgit push public master:master\n"> ) } ) (C {(test_expect_success)} {(SQ <"clone git repository">)} { (SQ <"\n"> <"\tgit clone -v \"$GIT_DAEMON_URL/repo.git\" clone 2>stderr &&\n"> <"\tcheck_verbose_connect &&\n"> <"\ttest_cmp file clone/file\n"> ) } ) (C {(test_expect_success)} {(SQ <"fetch changes via git protocol">)} { (SQ <"\n"> <"\techo content >>file &&\n"> <"\tgit commit -a -m two &&\n"> <"\tgit push public &&\n"> <"\t(cd clone && git pull -v) 2>stderr &&\n"> <"\tcheck_verbose_connect &&\n"> <"\ttest_cmp file clone/file\n"> ) } ) (C {(test_expect_success)} {(SQ <"no-op fetch -v stderr is as expected">)} {(SQ <"\n"> <"\t(cd clone && git fetch -v) 2>stderr &&\n"> <"\tcheck_verbose_connect\n">)} ) (C {(test_expect_success)} {(SQ <"no-op fetch without \"-v\" is quiet">)} {(SQ <"\n"> <"\t(cd clone && git fetch) 2>stderr &&\n"> <"\t! test -s stderr\n">)} ) (C {(test_expect_success)} {(SQ <"remote detects correct HEAD">)} { (SQ <"\n"> <"\tgit push public master:other &&\n"> <"\t(cd clone &&\n"> <"\t git remote set-head -d origin &&\n"> <"\t git remote set-head -a origin &&\n"> <"\t git symbolic-ref refs/remotes/origin/HEAD > output &&\n"> <"\t echo refs/remotes/origin/master > expect &&\n"> <"\t test_cmp expect output\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"prepare pack objects">)} { (SQ <"\n"> < "\tcp -R \"$GIT_DAEMON_DOCUMENT_ROOT_PATH\"/repo.git \"$GIT_DAEMON_DOCUMENT_ROOT_PATH\"/repo_pack.git &&\n" > <"\t(cd \"$GIT_DAEMON_DOCUMENT_ROOT_PATH\"/repo_pack.git &&\n"> <"\t git --bare repack -a -d\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"fetch notices corrupt pack">)} { (SQ <"\n"> < "\tcp -R \"$GIT_DAEMON_DOCUMENT_ROOT_PATH\"/repo_pack.git \"$GIT_DAEMON_DOCUMENT_ROOT_PATH\"/repo_bad1.git &&\n" > <"\t(cd \"$GIT_DAEMON_DOCUMENT_ROOT_PATH\"/repo_bad1.git &&\n"> <"\t p=$(ls objects/pack/pack-*.pack) &&\n"> <"\t chmod u+w $p &&\n"> <"\t printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc\n"> <"\t) &&\n"> <"\tmkdir repo_bad1.git &&\n"> <"\t(cd repo_bad1.git &&\n"> <"\t git --bare init &&\n"> <"\t test_must_fail git --bare fetch \"$GIT_DAEMON_URL/repo_bad1.git\" &&\n"> <"\t test 0 = $(ls objects/pack/pack-*.pack | wc -l)\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"fetch notices corrupt idx">)} { (SQ <"\n"> < "\tcp -R \"$GIT_DAEMON_DOCUMENT_ROOT_PATH\"/repo_pack.git \"$GIT_DAEMON_DOCUMENT_ROOT_PATH\"/repo_bad2.git &&\n" > <"\t(cd \"$GIT_DAEMON_DOCUMENT_ROOT_PATH\"/repo_bad2.git &&\n"> <"\t p=$(ls objects/pack/pack-*.idx) &&\n"> <"\t chmod u+w $p &&\n"> <"\t printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc\n"> <"\t) &&\n"> <"\tmkdir repo_bad2.git &&\n"> <"\t(cd repo_bad2.git &&\n"> <"\t git --bare init &&\n"> <"\t test_must_fail git --bare fetch \"$GIT_DAEMON_URL/repo_bad2.git\" &&\n"> <"\t test 0 = $(ls objects/pack | wc -l)\n"> <"\t)\n"> ) } ) (FuncDef name: test_remote_error body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:do_export) op: Equal rhs: {(YesPlease)} spids: [248] ) ] spids: [248] ) (While cond: [(C {(test)} {($ VSub_Pound "$#")} {(-gt)} {(0)})] body: (DoGroup children: [ (Case to_match: {($ VSub_Number "$1")} arms: [ (case_arm pat_list: [{(-x)}] action: [ (C {(shift)}) (C {(chmod)} {(-x)} {(DQ ($ VSub_Name "$GIT_DAEMON_DOCUMENT_ROOT_PATH") (/repo.git))} ) ] spids: [273 274 290 -1] ) (case_arm pat_list: [{(-n)}] action: [ (C {(shift)}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:do_export) op: Equal rhs: {(SQ )} spids: [300] ) ] spids: [300] ) ] spids: [293 294 303 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [(ControlFlow token:<ControlFlow_Break break>)] spids: [306 307 -1 313] ) ] spids: [266 270 313] ) ] spids: [263 316] ) ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:msg) op: Equal rhs: {($ VSub_Number "$1")} spids: [320] ) ] spids: [320] ) (C {(shift)}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:cmd) op: Equal rhs: {($ VSub_Number "$1")} spids: [327] ) ] spids: [327] ) (C {(shift)}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:repo) op: Equal rhs: {($ VSub_Number "$1")} spids: [334] ) ] spids: [334] ) (AndOr children: [(C {(shift)}) (C {(error)} {(DQ ("invalid number of arguments"))})] op_id: Op_DPipe ) (If arms: [ (if_arm cond: [ (C {(test)} {(-x)} {(DQ ($ VSub_Name "$GIT_DAEMON_DOCUMENT_ROOT_PATH") (/) ($ VSub_Name "$repo"))} ) ] action: [ (If arms: [ (if_arm cond: [(C {(test)} {(-n)} {(DQ ($ VSub_Name "$do_export"))})] action: [ (SimpleCommand words: [{(Lit_Other ":")}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: { (DQ ($ VSub_Name "$GIT_DAEMON_DOCUMENT_ROOT_PATH") (/) ($ VSub_Name "$repo") (/git-daemon-export-ok) ) } spids: [382] ) ] ) ] spids: [-1 377] ) ] else_action: [ (C {(rm)} {(-f)} { (DQ ($ VSub_Name "$GIT_DAEMON_DOCUMENT_ROOT_PATH") (/) ($ VSub_Name "$repo") (/git-daemon-export-ok) ) } ) ] spids: [391 406] ) ] spids: [-1 363] ) ] spids: [-1 409] ) (AndOr children: [ (SimpleCommand words: [ {(test_must_fail)} {(git)} {(DQ ($ VSub_Name "$cmd"))} {(DQ ($ VSub_Name "$GIT_DAEMON_URL") (/) ($ VSub_Name "$repo"))} {(DQ ($ VSub_At "$@"))} ] redirects: [(Redir op_id:Redir_Great fd:2 arg_word:{(output)} spids:[431])] ) (AndOr children: [ (C {(test_i18ngrep)} { (DQ ("fatal: remote error: ") ($ VSub_Name "$msg") (": /") ($ VSub_Name "$repo")) } {(output)} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:ret) op: Equal rhs: {($ VSub_QMark "$?")} spids: [451] ) ] spids: [451] ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) (C {(chmod)} {(Lit_Other "+") (x)} {(DQ ($ VSub_Name "$GIT_DAEMON_DOCUMENT_ROOT_PATH") (/repo.git))} ) (Subshell child:(C {(exit)} {($ VSub_Name "$ret")}) spids:[466470]) ] spids: [245] ) spids: [241 244] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:msg) op: Equal rhs: {(DQ ("access denied or repository not exported"))} spids: [475] ) ] spids: [475] ) (C {(test_expect_success)} {(SQ <"clone non-existent">)} {(DQ ("test_remote_error '") ($ VSub_Name "$msg") ("' clone nowhere.git "))} ) (C {(test_expect_success)} {(SQ <"push disabled">)} {(DQ ("test_remote_error '") ($ VSub_Name "$msg") ("' push repo.git master"))} ) (C {(test_expect_success)} {(SQ <"read access denied">)} {(DQ ("test_remote_error -x '") ($ VSub_Name "$msg") ("' fetch repo.git "))} ) (C {(test_expect_success)} {(SQ <"not exported">)} {(DQ ("test_remote_error -n '") ($ VSub_Name "$msg") ("' fetch repo.git "))} ) (C {(stop_git_daemon)}) (C {(start_git_daemon)} {(--informative-errors)}) (C {(test_expect_success)} {(SQ <"clone non-existent">)} {(DQ ("test_remote_error 'no such repository' clone nowhere.git "))} ) (C {(test_expect_success)} {(SQ <"push disabled">)} {(DQ ("test_remote_error 'service not enabled' push repo.git master"))} ) (C {(test_expect_success)} {(SQ <"read access denied">)} {(DQ ("test_remote_error -x 'no such repository' fetch repo.git "))} ) (C {(test_expect_success)} {(SQ <"not exported">)} {(DQ ("test_remote_error -n 'repository not exported' fetch repo.git "))} ) (C {(stop_git_daemon)}) (C {(start_git_daemon)} {(--interpolated-path) (Lit_Other "=") (DQ ($ VSub_Name "$GIT_DAEMON_DOCUMENT_ROOT_PATH") ("/%H%D")) } ) (C {(test_expect_success)} {(SQ <"access repo via interpolated hostname">)} { (SQ <"\n"> <"\trepo=\"$GIT_DAEMON_DOCUMENT_ROOT_PATH/localhost/interp.git\" &&\n"> <"\tgit init --bare \"$repo\" &&\n"> <"\tgit push \"$repo\" HEAD &&\n"> <"\t>\"$repo\"/git-daemon-export-ok &&\n"> <"\trm -rf tmp.git &&\n"> <"\tGIT_OVERRIDE_VIRTUAL_HOST=localhost \\\n"> <"\t\tgit clone --bare \"$GIT_DAEMON_URL/interp.git\" tmp.git &&\n"> <"\trm -rf tmp.git &&\n"> <"\tGIT_OVERRIDE_VIRTUAL_HOST=LOCALHOST \\\n"> <"\t\tgit clone --bare \"$GIT_DAEMON_URL/interp.git\" tmp.git\n"> ) } ) (C {(test_expect_success)} {(SQ <"hostname cannot break out of directory">)} { (SQ <"\n"> <"\trm -rf tmp.git &&\n"> <"\trepo=\"$GIT_DAEMON_DOCUMENT_ROOT_PATH/../escape.git\" &&\n"> <"\tgit init --bare \"$repo\" &&\n"> <"\tgit push \"$repo\" HEAD &&\n"> <"\t>\"$repo\"/git-daemon-export-ok &&\n"> <"\ttest_must_fail \\\n"> <"\t\tenv GIT_OVERRIDE_VIRTUAL_HOST=.. \\\n"> <"\t\tgit clone --bare \"$GIT_DAEMON_URL/escape.git\" tmp.git\n"> ) } ) (C {(stop_git_daemon)}) (C {(test_done)}) ] )