(CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: { (SQ <"Basic fetch/push functionality.\n"> <"\n"> <"This test checks the following functionality:\n"> <"\n"> <"* command-line syntax\n"> <"* refspecs\n"> <"* fast-forward detection, and overriding it\n"> <"* configuration\n"> <"* hooks\n"> <"* --porcelain output format\n"> <"* hiderefs\n"> <"* reflogs\n"> ) } spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:D) op: Equal rhs: { (CommandSubPart command_list: (CommandList children:[(C {(pwd)})]) left_token: <Left_CommandSub "$("> spids: [27 29] ) } spids: [26] ) ] spids: [26] ) (FuncDef name: mk_empty body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:repo_name) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [40] ) ] spids: [40] ) (AndOr children: [ (C {(rm)} {(-fr)} {(DQ ($ VSub_Name "$repo_name"))}) (AndOr children: [ (C {(mkdir)} {(DQ ($ VSub_Name "$repo_name"))}) (Subshell child: (AndOr children: [ (C {(cd)} {(DQ ($ VSub_Name "$repo_name"))}) (AndOr children: [ (C {(git)} {(init)}) (AndOr children: [ (C {(git)} {(config)} {(receive.denyCurrentBranch)} {(warn)}) (C {(mv)} {(.git/hooks)} {(.git/hooks-disabled)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) spids: [66 103] ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [37] ) spids: [32 36] ) (FuncDef name: mk_test body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:repo_name) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [116] ) ] spids: [116] ) (C {(shift)}) (AndOr children: [ (C {(mk_empty)} {(DQ ($ VSub_Name "$repo_name"))}) (Subshell child: (AndOr children: [ (ForEach iter_name: ref iter_words: [{(DQ ($ VSub_At "$@"))}] do_arg_iter: False body: (DoGroup children: [ (AndOr children: [ (C {(git)} {(push)} {(DQ ($ VSub_Name "$repo_name"))} {($ VSub_Name "$the_first_commit") (Lit_Other ":") (refs/) ($ VSub_Name "$ref") } ) (C {(exit)}) ] op_id: Op_DPipe ) ] spids: [149 171] ) spids: [143 -1] ) (AndOr children: [ (C {(cd)} {(DQ ($ VSub_Name "$repo_name"))}) (AndOr children: [ (ForEach iter_name: ref iter_words: [{(DQ ($ VSub_At "$@"))}] do_arg_iter: False body: (DoGroup children: [ (AndOr children: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_Name "$the_first_commit"))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(expect)} spids: [205] ) ] ) (AndOr children: [ (SimpleCommand words: [ {(git)} {(show-ref)} {(-s)} {(--verify)} {(refs/) ($ VSub_Name "$ref")} ] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(actual)} spids: [222] ) ] ) (AndOr children: [ (C {(test_cmp)} {(expect)} {(actual)}) (C {(exit)}) ] op_id: Op_DPipe ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [196 240] ) spids: [190 -1] ) (C {(git)} {(fsck)} {(--full)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) spids: [135 252] ) ] op_id: Op_DAmp ) ] spids: [113] ) spids: [108 112] ) (FuncDef name: mk_test_with_hooks body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:repo_name) op: Equal rhs: {($ VSub_Number "$1")} spids: [264] ) ] spids: [264] ) (AndOr children: [ (C {(mk_test)} {(DQ ($ VSub_At "$@"))}) (Subshell child: (AndOr children: [ (C {(cd)} {(DQ ($ VSub_Name "$repo_name"))}) (AndOr children: [ (C {(mkdir)} {(.git/hooks)}) (AndOr children: [ (C {(cd)} {(.git/hooks)}) (AndOr children: [ (SimpleCommand words: [{(cat)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(pre-receive)} spids: [306] ) (HereDoc op_id: Redir_DLessDash fd: -1 body: {("#!/bin/sh\n") ("cat - >>pre-receive.actual\n")} do_expansion: False here_end: EOF was_filled: True spids: [309] ) ] ) (AndOr children: [ (SimpleCommand words: [{(cat)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(update)} spids: [320] ) (HereDoc op_id: Redir_DLessDash fd: -1 body: {("#!/bin/sh\n") ( "printf \"%s %s %s\\n\" \"$@\" >>update.actual\n" ) } do_expansion: False here_end: EOF was_filled: True spids: [323] ) ] ) (AndOr children: [ (SimpleCommand words: [{(cat)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(post-receive)} spids: [334] ) (HereDoc op_id: Redir_DLessDash fd: -1 body: {("#!/bin/sh\n") ("cat - >>post-receive.actual\n") } do_expansion: False here_end: EOF was_filled: True spids: [337] ) ] ) (AndOr children: [ (SimpleCommand words: [{(cat)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(post-update)} spids: [348] ) (HereDoc op_id: Redir_DLessDash fd: -1 body: {("#!/bin/sh\n") ("for ref in \"$@\"\n") ("do\n") ("printf \"%s\\n\" \"$ref\" >>post-update.actual\n") ("done\n") } do_expansion: False here_end: EOF was_filled: True spids: [351] ) ] ) (C {(chmod)} {(Lit_Other "+") (x)} {(pre-receive)} {(update)} {(post-receive)} {(post-update)} ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) spids: [277 374] ) ] op_id: Op_DAmp ) ] spids: [261] ) spids: [257 260] ) (FuncDef name: mk_child body: (BraceGroup children: [ (AndOr children: [ (C {(rm)} {(-rf)} {(DQ ($ VSub_Number "$2"))}) (C {(git)} {(clone)} {(DQ ($ VSub_Number "$1"))} {(DQ ($ VSub_Number "$2"))}) ] op_id: Op_DAmp ) ] spids: [383] ) spids: [379 382] ) (FuncDef name: check_push_result body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:repo_name) op: Equal rhs: {(DQ ($ VSub_Number "$1"))} spids: [420] ) ] spids: [420] ) (C {(shift)}) (Subshell child: (AndOr children: [ (C {(cd)} {(DQ ($ VSub_Name "$repo_name"))}) (AndOr children: [ (SimpleCommand words: [{(echo)} {(DQ ($ VSub_Number "$1"))}] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(expect)} spids:[448])] ) (AndOr children: [ (C {(shift)}) (AndOr children: [ (ForEach iter_name: ref iter_words: [{(DQ ($ VSub_At "$@"))}] do_arg_iter: False body: (DoGroup children: [ (AndOr children: [ (SimpleCommand words: [ {(git)} {(show-ref)} {(-s)} {(--verify)} {(refs/) ($ VSub_Name "$ref")} ] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(actual)} spids: [484] ) ] ) (AndOr children: [ (C {(test_cmp)} {(expect)} {(actual)}) (C {(exit)}) ] op_id: Op_DPipe ) ] op_id: Op_DAmp ) ] spids: [470 502] ) spids: [464 -1] ) (C {(git)} {(fsck)} {(--full)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) spids: [430 514] ) ] spids: [417] ) spids: [412 416] ) (C {(test_expect_success)} {(setup)} { (SQ <"\n"> <"\n"> <"\t>path1 &&\n"> <"\tgit add path1 &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -a -m repo &&\n"> <"\tthe_first_commit=$(git show-ref -s --verify refs/heads/master) &&\n"> <"\n"> <"\t>path2 &&\n"> <"\tgit add path2 &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -a -m second &&\n"> <"\tthe_commit=$(git show-ref -s --verify refs/heads/master)\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"fetch without wildcard">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit fetch .. refs/heads/master:refs/remotes/origin/master &&\n"> <"\n"> <"\t\techo \"$the_commit commit\trefs/remotes/origin/master\" >expect &&\n"> <"\t\tgit for-each-ref refs/remotes/origin >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"fetch with wildcard">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit config remote.up.url .. &&\n"> <"\t\tgit config remote.up.fetch \"refs/heads/*:refs/remotes/origin/*\" &&\n"> <"\t\tgit fetch up &&\n"> <"\n"> <"\t\techo \"$the_commit commit\trefs/remotes/origin/master\" >expect &&\n"> <"\t\tgit for-each-ref refs/remotes/origin >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"fetch with insteadOf">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\t(\n"> <"\t\tTRASH=$(pwd)/ &&\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit config \"url.$TRASH.insteadOf\" trash/ &&\n"> <"\t\tgit config remote.up.url trash/. &&\n"> <"\t\tgit config remote.up.fetch \"refs/heads/*:refs/remotes/origin/*\" &&\n"> <"\t\tgit fetch up &&\n"> <"\n"> <"\t\techo \"$the_commit commit\trefs/remotes/origin/master\" >expect &&\n"> <"\t\tgit for-each-ref refs/remotes/origin >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"fetch with pushInsteadOf (should not rewrite)">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\t(\n"> <"\t\tTRASH=$(pwd)/ &&\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit config \"url.trash/.pushInsteadOf\" \"$TRASH\" &&\n"> <"\t\tgit config remote.up.url \"$TRASH.\" &&\n"> <"\t\tgit config remote.up.fetch \"refs/heads/*:refs/remotes/origin/*\" &&\n"> <"\t\tgit fetch up &&\n"> <"\n"> <"\t\techo \"$the_commit commit\trefs/remotes/origin/master\" >expect &&\n"> <"\t\tgit for-each-ref refs/remotes/origin >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"push without wildcard">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\n"> <"\tgit push testrepo refs/heads/master:refs/remotes/origin/master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\techo \"$the_commit commit\trefs/remotes/origin/master\" >expect &&\n"> <"\t\tgit for-each-ref refs/remotes/origin >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with wildcard">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\n"> <"\tgit push testrepo \"refs/heads/*:refs/remotes/origin/*\" &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\techo \"$the_commit commit\trefs/remotes/origin/master\" >expect &&\n"> <"\t\tgit for-each-ref refs/remotes/origin >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with insteadOf">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\tTRASH=\"$(pwd)/\" &&\n"> <"\ttest_config \"url.$TRASH.insteadOf\" trash/ &&\n"> <"\tgit push trash/testrepo refs/heads/master:refs/remotes/origin/master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\techo \"$the_commit commit\trefs/remotes/origin/master\" >expect &&\n"> <"\t\tgit for-each-ref refs/remotes/origin >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with pushInsteadOf">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\tTRASH=\"$(pwd)/\" &&\n"> <"\ttest_config \"url.$TRASH.pushInsteadOf\" trash/ &&\n"> <"\tgit push trash/testrepo refs/heads/master:refs/remotes/origin/master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\techo \"$the_commit commit\trefs/remotes/origin/master\" >expect &&\n"> <"\t\tgit for-each-ref refs/remotes/origin >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with pushInsteadOf and explicit pushurl (pushInsteadOf should not rewrite)">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\ttest_config \"url.trash2/.pushInsteadOf\" testrepo/ &&\n"> <"\ttest_config \"url.trash3/.pushInsteadOf\" trash/wrong &&\n"> <"\ttest_config remote.r.url trash/wrong &&\n"> <"\ttest_config remote.r.pushurl \"testrepo/\" &&\n"> <"\tgit push r refs/heads/master:refs/remotes/origin/master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\techo \"$the_commit commit\trefs/remotes/origin/master\" >expect &&\n"> <"\t\tgit for-each-ref refs/remotes/origin >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with matching heads">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tgit push testrepo : &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with matching heads on the command line">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tgit push testrepo : &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"failed (non-fast-forward) push with matching heads">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tgit push testrepo : &&\n"> <"\tgit commit --amend -massaged &&\n"> <"\ttest_must_fail git push testrepo &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master &&\n"> <"\tgit reset --hard $the_commit\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --force with matching heads">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tgit push testrepo : &&\n"> <"\tgit commit --amend -massaged &&\n"> <"\tgit push --force testrepo : &&\n"> <"\t! check_push_result testrepo $the_commit heads/master &&\n"> <"\tgit reset --hard $the_commit\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with matching heads and forced update">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tgit push testrepo : &&\n"> <"\tgit commit --amend -massaged &&\n"> <"\tgit push testrepo +: &&\n"> <"\t! check_push_result testrepo $the_commit heads/master &&\n"> <"\tgit reset --hard $the_commit\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with no ambiguity (1)">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tgit push testrepo master:master &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with no ambiguity (2)">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo remotes/origin/master &&\n"> <"\tgit push testrepo master:origin/master &&\n"> <"\tcheck_push_result testrepo $the_commit remotes/origin/master\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with colon-less refspec, no ambiguity">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master heads/t/master &&\n"> <"\tgit branch -f t/master master &&\n"> <"\tgit push testrepo master &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master &&\n"> <"\tcheck_push_result testrepo $the_first_commit heads/t/master\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with weak ambiguity (1)">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master remotes/origin/master &&\n"> <"\tgit push testrepo master:master &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master &&\n"> <"\tcheck_push_result testrepo $the_first_commit remotes/origin/master\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with weak ambiguity (2)">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master remotes/origin/master remotes/another/master &&\n"> <"\tgit push testrepo master:master &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master &&\n"> <"\tcheck_push_result testrepo $the_first_commit remotes/origin/master remotes/another/master\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with ambiguity">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/frotz tags/frotz &&\n"> <"\ttest_must_fail git push testrepo master:frotz &&\n"> <"\tcheck_push_result testrepo $the_first_commit heads/frotz tags/frotz\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with colon-less refspec (1)">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/frotz tags/frotz &&\n"> <"\tgit branch -f frotz master &&\n"> <"\tgit push testrepo frotz &&\n"> <"\tcheck_push_result testrepo $the_commit heads/frotz &&\n"> <"\tcheck_push_result testrepo $the_first_commit tags/frotz\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with colon-less refspec (2)">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/frotz tags/frotz &&\n"> <"\tif git show-ref --verify -q refs/heads/frotz\n"> <"\tthen\n"> <"\t\tgit branch -D frotz\n"> <"\tfi &&\n"> <"\tgit tag -f frotz &&\n"> <"\tgit push -f testrepo frotz &&\n"> <"\tcheck_push_result testrepo $the_commit tags/frotz &&\n"> <"\tcheck_push_result testrepo $the_first_commit heads/frotz\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with colon-less refspec (3)">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo &&\n"> <"\tif git show-ref --verify -q refs/tags/frotz\n"> <"\tthen\n"> <"\t\tgit tag -d frotz\n"> <"\tfi &&\n"> <"\tgit branch -f frotz master &&\n"> <"\tgit push testrepo frotz &&\n"> <"\tcheck_push_result testrepo $the_commit heads/frotz &&\n"> <"\ttest 1 = $( cd testrepo && git show-ref | wc -l )\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with colon-less refspec (4)">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo &&\n"> <"\tif git show-ref --verify -q refs/heads/frotz\n"> <"\tthen\n"> <"\t\tgit branch -D frotz\n"> <"\tfi &&\n"> <"\tgit tag -f frotz &&\n"> <"\tgit push testrepo frotz &&\n"> <"\tcheck_push_result testrepo $the_commit tags/frotz &&\n"> <"\ttest 1 = $( cd testrepo && git show-ref | wc -l )\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push head with non-existent, incomplete dest">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo &&\n"> <"\tgit push testrepo master:branch &&\n"> <"\tcheck_push_result testrepo $the_commit heads/branch\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push tag with non-existent, incomplete dest">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo &&\n"> <"\tgit tag -f v1.0 &&\n"> <"\tgit push testrepo v1.0:tag &&\n"> <"\tcheck_push_result testrepo $the_commit tags/tag\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push sha1 with non-existent, incomplete dest">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo &&\n"> <"\ttest_must_fail git push testrepo $(git rev-parse master):foo\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push ref expression with non-existent, incomplete dest">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo &&\n"> <"\ttest_must_fail git push testrepo master^:branch\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with HEAD">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tgit checkout master &&\n"> <"\tgit push testrepo HEAD &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with HEAD nonexisting at remote">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tgit checkout -b local master &&\n"> <"\tgit push testrepo HEAD &&\n"> <"\tcheck_push_result testrepo $the_commit heads/local\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with +HEAD">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tgit checkout master &&\n"> <"\tgit branch -D local &&\n"> <"\tgit checkout -b local &&\n"> <"\tgit push testrepo master local &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master &&\n"> <"\tcheck_push_result testrepo $the_commit heads/local &&\n"> <"\n"> <"\t# Without force rewinding should fail\n"> <"\tgit reset --hard HEAD^ &&\n"> <"\ttest_must_fail git push testrepo HEAD &&\n"> <"\tcheck_push_result testrepo $the_commit heads/local &&\n"> <"\n"> <"\t# With force rewinding should succeed\n"> <"\tgit push testrepo +HEAD &&\n"> <"\tcheck_push_result testrepo $the_first_commit heads/local\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push HEAD with non-existent, incomplete dest">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo &&\n"> <"\tgit checkout master &&\n"> <"\tgit push testrepo HEAD:branch &&\n"> <"\tcheck_push_result testrepo $the_commit heads/branch\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with config remote.*.push = HEAD">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/local &&\n"> <"\tgit checkout master &&\n"> <"\tgit branch -f local $the_commit &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit checkout local &&\n"> <"\t\tgit reset --hard $the_first_commit\n"> <"\t) &&\n"> <"\ttest_config remote.there.url testrepo &&\n"> <"\ttest_config remote.there.push HEAD &&\n"> <"\ttest_config branch.master.remote there &&\n"> <"\tgit push &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master &&\n"> <"\tcheck_push_result testrepo $the_first_commit heads/local\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with remote.pushdefault">)} { (SQ <"\n"> <"\tmk_test up_repo heads/master &&\n"> <"\tmk_test down_repo heads/master &&\n"> <"\ttest_config remote.up.url up_repo &&\n"> <"\ttest_config remote.down.url down_repo &&\n"> <"\ttest_config branch.master.remote up &&\n"> <"\ttest_config remote.pushdefault down &&\n"> <"\ttest_config push.default matching &&\n"> <"\tgit push &&\n"> <"\tcheck_push_result up_repo $the_first_commit heads/master &&\n"> <"\tcheck_push_result down_repo $the_commit heads/master\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with config remote.*.pushurl">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tgit checkout master &&\n"> <"\ttest_config remote.there.url test2repo &&\n"> <"\ttest_config remote.there.pushurl testrepo &&\n"> <"\tgit push there : &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with config branch.*.pushremote">)} { (SQ <"\n"> <"\tmk_test up_repo heads/master &&\n"> <"\tmk_test side_repo heads/master &&\n"> <"\tmk_test down_repo heads/master &&\n"> <"\ttest_config remote.up.url up_repo &&\n"> <"\ttest_config remote.pushdefault side_repo &&\n"> <"\ttest_config remote.down.url down_repo &&\n"> <"\ttest_config branch.master.remote up &&\n"> <"\ttest_config branch.master.pushremote down &&\n"> <"\ttest_config push.default matching &&\n"> <"\tgit push &&\n"> <"\tcheck_push_result up_repo $the_first_commit heads/master &&\n"> <"\tcheck_push_result side_repo $the_first_commit heads/master &&\n"> <"\tcheck_push_result down_repo $the_commit heads/master\n"> ) } ) (C {(test_expect_success)} {(SQ <"branch.*.pushremote config order is irrelevant">)} { (SQ <"\n"> <"\tmk_test one_repo heads/master &&\n"> <"\tmk_test two_repo heads/master &&\n"> <"\ttest_config remote.one.url one_repo &&\n"> <"\ttest_config remote.two.url two_repo &&\n"> <"\ttest_config branch.master.pushremote two_repo &&\n"> <"\ttest_config remote.pushdefault one_repo &&\n"> <"\ttest_config push.default matching &&\n"> <"\tgit push &&\n"> <"\tcheck_push_result one_repo $the_first_commit heads/master &&\n"> <"\tcheck_push_result two_repo $the_commit heads/master\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with dry-run">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\told_commit=$(git show-ref -s --verify refs/heads/master)\n"> <"\t) &&\n"> <"\tgit push --dry-run testrepo : &&\n"> <"\tcheck_push_result testrepo $old_commit heads/master\n"> ) } ) (C {(test_expect_success)} {(SQ <"push updates local refs">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tmk_child testrepo child &&\n"> <"\t(\n"> <"\t\tcd child &&\n"> <"\t\tgit pull .. master &&\n"> <"\t\tgit push &&\n"> <"\t\ttest $(git rev-parse master) = \\\n"> <"\t\t\t$(git rev-parse remotes/origin/master)\n"> <"\t)\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push updates up-to-date local refs">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tmk_child testrepo child1 &&\n"> <"\tmk_child testrepo child2 &&\n"> <"\t(cd child1 && git pull .. master && git push) &&\n"> <"\t(\n"> <"\t\tcd child2 &&\n"> <"\t\tgit pull ../child1 master &&\n"> <"\t\tgit push &&\n"> <"\t\ttest $(git rev-parse master) = \\\n"> <"\t\t\t$(git rev-parse remotes/origin/master)\n"> <"\t)\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push preserves up-to-date packed refs">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tmk_child testrepo child &&\n"> <"\t(\n"> <"\t\tcd child &&\n"> <"\t\tgit push &&\n"> <"\t\t! test -f .git/refs/remotes/origin/master\n"> <"\t)\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push does not update local refs on failure">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tmk_child testrepo child &&\n"> <"\tmkdir testrepo/.git/hooks &&\n"> <"\techo \"#!/no/frobnication/today\" >testrepo/.git/hooks/pre-receive &&\n"> <"\tchmod +x testrepo/.git/hooks/pre-receive &&\n"> <"\t(\n"> <"\t\tcd child &&\n"> <"\t\tgit pull .. master\n"> <"\t\ttest_must_fail git push &&\n"> <"\t\ttest $(git rev-parse master) != \\\n"> <"\t\t\t$(git rev-parse remotes/origin/master)\n"> <"\t)\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"allow deleting an invalid remote ref">)} { (SQ <"\n"> <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\trm -f testrepo/.git/objects/??/* &&\n"> <"\tgit push testrepo :refs/heads/master &&\n"> <"\t(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"pushing valid refs triggers post-receive and post-update hooks">)} { (SQ <"\n"> <"\tmk_test_with_hooks testrepo heads/master heads/next &&\n"> <"\torgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&\n"> <"\tnewmaster=$(git show-ref -s --verify refs/heads/master) &&\n"> <"\torgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) &&\n"> <"\tnewnext=$_z40 &&\n"> <"\tgit push testrepo refs/heads/master:refs/heads/master :refs/heads/next &&\n"> <"\t(\n"> <"\t\tcd testrepo/.git &&\n"> <"\t\tcat >pre-receive.expect <<-EOF &&\n"> <"\t\t$orgmaster $newmaster refs/heads/master\n"> <"\t\t$orgnext $newnext refs/heads/next\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >update.expect <<-EOF &&\n"> <"\t\trefs/heads/master $orgmaster $newmaster\n"> <"\t\trefs/heads/next $orgnext $newnext\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >post-receive.expect <<-EOF &&\n"> <"\t\t$orgmaster $newmaster refs/heads/master\n"> <"\t\t$orgnext $newnext refs/heads/next\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >post-update.expect <<-EOF &&\n"> <"\t\trefs/heads/master\n"> <"\t\trefs/heads/next\n"> <"\t\tEOF\n"> <"\n"> <"\t\ttest_cmp pre-receive.expect pre-receive.actual &&\n"> <"\t\ttest_cmp update.expect update.actual &&\n"> <"\t\ttest_cmp post-receive.expect post-receive.actual &&\n"> <"\t\ttest_cmp post-update.expect post-update.actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"deleting dangling ref triggers hooks with correct args">)} { (SQ <"\n"> <"\tmk_test_with_hooks testrepo heads/master &&\n"> <"\trm -f testrepo/.git/objects/??/* &&\n"> <"\tgit push testrepo :refs/heads/master &&\n"> <"\t(\n"> <"\t\tcd testrepo/.git &&\n"> <"\t\tcat >pre-receive.expect <<-EOF &&\n"> <"\t\t$_z40 $_z40 refs/heads/master\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >update.expect <<-EOF &&\n"> <"\t\trefs/heads/master $_z40 $_z40\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >post-receive.expect <<-EOF &&\n"> <"\t\t$_z40 $_z40 refs/heads/master\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >post-update.expect <<-EOF &&\n"> <"\t\trefs/heads/master\n"> <"\t\tEOF\n"> <"\n"> <"\t\ttest_cmp pre-receive.expect pre-receive.actual &&\n"> <"\t\ttest_cmp update.expect update.actual &&\n"> <"\t\ttest_cmp post-receive.expect post-receive.actual &&\n"> <"\t\ttest_cmp post-update.expect post-update.actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"deletion of a non-existent ref is not fed to post-receive and post-update hooks">)} { (SQ <"\n"> <"\tmk_test_with_hooks testrepo heads/master &&\n"> <"\torgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&\n"> <"\tnewmaster=$(git show-ref -s --verify refs/heads/master) &&\n"> <"\tgit push testrepo master :refs/heads/nonexistent &&\n"> <"\t(\n"> <"\t\tcd testrepo/.git &&\n"> <"\t\tcat >pre-receive.expect <<-EOF &&\n"> <"\t\t$orgmaster $newmaster refs/heads/master\n"> <"\t\t$_z40 $_z40 refs/heads/nonexistent\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >update.expect <<-EOF &&\n"> <"\t\trefs/heads/master $orgmaster $newmaster\n"> <"\t\trefs/heads/nonexistent $_z40 $_z40\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >post-receive.expect <<-EOF &&\n"> <"\t\t$orgmaster $newmaster refs/heads/master\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >post-update.expect <<-EOF &&\n"> <"\t\trefs/heads/master\n"> <"\t\tEOF\n"> <"\n"> <"\t\ttest_cmp pre-receive.expect pre-receive.actual &&\n"> <"\t\ttest_cmp update.expect update.actual &&\n"> <"\t\ttest_cmp post-receive.expect post-receive.actual &&\n"> <"\t\ttest_cmp post-update.expect post-update.actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"deletion of a non-existent ref alone does trigger post-receive and post-update hooks">)} { (SQ <"\n"> <"\tmk_test_with_hooks testrepo heads/master &&\n"> <"\tgit push testrepo :refs/heads/nonexistent &&\n"> <"\t(\n"> <"\t\tcd testrepo/.git &&\n"> <"\t\tcat >pre-receive.expect <<-EOF &&\n"> <"\t\t$_z40 $_z40 refs/heads/nonexistent\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >update.expect <<-EOF &&\n"> <"\t\trefs/heads/nonexistent $_z40 $_z40\n"> <"\t\tEOF\n"> <"\n"> <"\t\ttest_cmp pre-receive.expect pre-receive.actual &&\n"> <"\t\ttest_cmp update.expect update.actual &&\n"> <"\t\ttest_path_is_missing post-receive.actual &&\n"> <"\t\ttest_path_is_missing post-update.actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"mixed ref updates, deletes, invalid deletes trigger hooks with correct input">)} { (SQ <"\n"> <"\tmk_test_with_hooks testrepo heads/master heads/next heads/pu &&\n"> <"\torgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&\n"> <"\tnewmaster=$(git show-ref -s --verify refs/heads/master) &&\n"> <"\torgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) &&\n"> <"\tnewnext=$_z40 &&\n"> <"\torgpu=$(cd testrepo && git show-ref -s --verify refs/heads/pu) &&\n"> <"\tnewpu=$(git show-ref -s --verify refs/heads/master) &&\n"> <"\tgit push testrepo refs/heads/master:refs/heads/master \\\n"> <"\t refs/heads/master:refs/heads/pu :refs/heads/next \\\n"> <"\t :refs/heads/nonexistent &&\n"> <"\t(\n"> <"\t\tcd testrepo/.git &&\n"> <"\t\tcat >pre-receive.expect <<-EOF &&\n"> <"\t\t$orgmaster $newmaster refs/heads/master\n"> <"\t\t$orgnext $newnext refs/heads/next\n"> <"\t\t$orgpu $newpu refs/heads/pu\n"> <"\t\t$_z40 $_z40 refs/heads/nonexistent\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >update.expect <<-EOF &&\n"> <"\t\trefs/heads/master $orgmaster $newmaster\n"> <"\t\trefs/heads/next $orgnext $newnext\n"> <"\t\trefs/heads/pu $orgpu $newpu\n"> <"\t\trefs/heads/nonexistent $_z40 $_z40\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >post-receive.expect <<-EOF &&\n"> <"\t\t$orgmaster $newmaster refs/heads/master\n"> <"\t\t$orgnext $newnext refs/heads/next\n"> <"\t\t$orgpu $newpu refs/heads/pu\n"> <"\t\tEOF\n"> <"\n"> <"\t\tcat >post-update.expect <<-EOF &&\n"> <"\t\trefs/heads/master\n"> <"\t\trefs/heads/next\n"> <"\t\trefs/heads/pu\n"> <"\t\tEOF\n"> <"\n"> <"\t\ttest_cmp pre-receive.expect pre-receive.actual &&\n"> <"\t\ttest_cmp update.expect update.actual &&\n"> <"\t\ttest_cmp post-receive.expect post-receive.actual &&\n"> <"\t\ttest_cmp post-update.expect post-update.actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"allow deleting a ref using --delete">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\t(cd testrepo && git config receive.denyDeleteCurrent warn) &&\n"> <"\tgit push testrepo --delete master &&\n"> <"\t(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)\n"> ) } ) (C {(test_expect_success)} {(SQ <"allow deleting a tag using --delete">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tgit tag -a -m dummy_message deltag heads/master &&\n"> <"\tgit push testrepo --tags &&\n"> <"\t(cd testrepo && git rev-parse --verify -q refs/tags/deltag) &&\n"> <"\tgit push testrepo --delete tag deltag &&\n"> <"\t(cd testrepo && test_must_fail git rev-parse --verify refs/tags/deltag)\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --delete without args aborts">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\ttest_must_fail git push testrepo --delete\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --delete refuses src:dest refspecs">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\ttest_must_fail git push testrepo --delete master:foo\n"> ) } ) (C {(test_expect_success)} {(SQ <"warn on push to HEAD of non-bare repository">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit checkout master &&\n"> <"\t\tgit config receive.denyCurrentBranch warn\n"> <"\t) &&\n"> <"\tgit push testrepo master 2>stderr &&\n"> <"\tgrep \"warning: updating the current branch\" stderr\n"> ) } ) (C {(test_expect_success)} {(SQ <"deny push to HEAD of non-bare repository">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit checkout master &&\n"> <"\t\tgit config receive.denyCurrentBranch true\n"> <"\t) &&\n"> <"\ttest_must_fail git push testrepo master\n"> ) } ) (C {(test_expect_success)} {(SQ <"allow push to HEAD of bare repository (bare)">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit checkout master &&\n"> <"\t\tgit config receive.denyCurrentBranch true &&\n"> <"\t\tgit config core.bare true\n"> <"\t) &&\n"> <"\tgit push testrepo master 2>stderr &&\n"> <"\t! grep \"warning: updating the current branch\" stderr\n"> ) } ) (C {(test_expect_success)} {(SQ <"allow push to HEAD of non-bare repository (config)">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit checkout master &&\n"> <"\t\tgit config receive.denyCurrentBranch false\n"> <"\t) &&\n"> <"\tgit push testrepo master 2>stderr &&\n"> <"\t! grep \"warning: updating the current branch\" stderr\n"> ) } ) (C {(test_expect_success)} {(SQ <"fetch with branches">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\tgit branch second $the_first_commit &&\n"> <"\tgit checkout second &&\n"> <"\techo \"..\" > testrepo/.git/branches/branch1 &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit fetch branch1 &&\n"> <"\t\techo \"$the_commit commit\trefs/heads/branch1\" >expect &&\n"> <"\t\tgit for-each-ref refs/heads >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t) &&\n"> <"\tgit checkout master\n"> ) } ) (C {(test_expect_success)} {(SQ <"fetch with branches containing #">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\techo \"..#second\" > testrepo/.git/branches/branch2 &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit fetch branch2 &&\n"> <"\t\techo \"$the_first_commit commit\trefs/heads/branch2\" >expect &&\n"> <"\t\tgit for-each-ref refs/heads >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t) &&\n"> <"\tgit checkout master\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with branches">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\tgit checkout second &&\n"> <"\techo \"testrepo\" > .git/branches/branch1 &&\n"> <"\tgit push branch1 &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\techo \"$the_first_commit commit\trefs/heads/master\" >expect &&\n"> <"\t\tgit for-each-ref refs/heads >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"push with branches containing #">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\techo \"testrepo#branch3\" > .git/branches/branch2 &&\n"> <"\tgit push branch2 &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\techo \"$the_first_commit commit\trefs/heads/branch3\" >expect &&\n"> <"\t\tgit for-each-ref refs/heads >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t) &&\n"> <"\tgit checkout master\n"> ) } ) (C {(test_expect_success)} {(SQ <"push into aliased refs (consistent)">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tmk_child testrepo child1 &&\n"> <"\tmk_child testrepo child2 &&\n"> <"\t(\n"> <"\t\tcd child1 &&\n"> <"\t\tgit branch foo &&\n"> <"\t\tgit symbolic-ref refs/heads/bar refs/heads/foo\n"> <"\t\tgit config receive.denyCurrentBranch false\n"> <"\t) &&\n"> <"\t(\n"> <"\t\tcd child2 &&\n"> <"\t\t>path2 &&\n"> <"\t\tgit add path2 &&\n"> <"\t\ttest_tick &&\n"> <"\t\tgit commit -a -m child2 &&\n"> <"\t\tgit branch foo &&\n"> <"\t\tgit branch bar &&\n"> <"\t\tgit push ../child1 foo bar\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"push into aliased refs (inconsistent)">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tmk_child testrepo child1 &&\n"> <"\tmk_child testrepo child2 &&\n"> <"\t(\n"> <"\t\tcd child1 &&\n"> <"\t\tgit branch foo &&\n"> <"\t\tgit symbolic-ref refs/heads/bar refs/heads/foo\n"> <"\t\tgit config receive.denyCurrentBranch false\n"> <"\t) &&\n"> <"\t(\n"> <"\t\tcd child2 &&\n"> <"\t\t>path2 &&\n"> <"\t\tgit add path2 &&\n"> <"\t\ttest_tick &&\n"> <"\t\tgit commit -a -m child2 &&\n"> <"\t\tgit branch foo &&\n"> <"\t\t>path3 &&\n"> <"\t\tgit add path3 &&\n"> <"\t\ttest_tick &&\n"> <"\t\tgit commit -a -m child2 &&\n"> <"\t\tgit branch bar &&\n"> <"\t\ttest_must_fail git push ../child1 foo bar 2>stderr &&\n"> <"\t\tgrep \"refusing inconsistent update\" stderr\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"push requires --force to update lightweight tag">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\tmk_child testrepo child1 &&\n"> <"\tmk_child testrepo child2 &&\n"> <"\t(\n"> <"\t\tcd child1 &&\n"> <"\t\tgit tag Tag &&\n"> <"\t\tgit push ../child2 Tag &&\n"> <"\t\tgit push ../child2 Tag &&\n"> <"\t\t>file1 &&\n"> <"\t\tgit add file1 &&\n"> <"\t\tgit commit -m \"file1\" &&\n"> <"\t\tgit tag -f Tag &&\n"> <"\t\ttest_must_fail git push ../child2 Tag &&\n"> <"\t\tgit push --force ../child2 Tag &&\n"> <"\t\tgit tag -f Tag &&\n"> <"\t\ttest_must_fail git push ../child2 Tag HEAD~ &&\n"> <"\t\tgit push --force ../child2 Tag\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --porcelain">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\techo >.git/foo \"To testrepo\" &&\n"> < "\techo >>.git/foo \"*\trefs/heads/master:refs/remotes/origin/master\t[new branch]\" &&\n" > <"\techo >>.git/foo \"Done\" &&\n"> < "\tgit push >.git/bar --porcelain testrepo refs/heads/master:refs/remotes/origin/master &&\n" > <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\techo \"$the_commit commit\trefs/remotes/origin/master\" >expect &&\n"> <"\t\tgit for-each-ref refs/remotes/origin >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t) &&\n"> <"\ttest_cmp .git/foo .git/bar\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --porcelain bad url">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> < "\ttest_must_fail git push >.git/bar --porcelain asdfasdfasd refs/heads/master:refs/remotes/origin/master &&\n" > <"\ttest_must_fail grep -q Done .git/bar\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --porcelain rejected">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\tgit push testrepo refs/heads/master:refs/remotes/origin/master &&\n"> <"\t(cd testrepo &&\n"> <"\t\tgit reset --hard origin/master^\n"> <"\t\tgit config receive.denyCurrentBranch true) &&\n"> <"\n"> <"\techo >.git/foo \"To testrepo\" &&\n"> < "\techo >>.git/foo \"!\trefs/heads/master:refs/heads/master\t[remote rejected] (branch is currently checked out)\" &&\n" > <"\n"> < "\ttest_must_fail git push >.git/bar --porcelain testrepo refs/heads/master:refs/heads/master &&\n" > <"\ttest_cmp .git/foo .git/bar\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --porcelain --dry-run rejected">)} { (SQ <"\n"> <"\tmk_empty testrepo &&\n"> <"\tgit push testrepo refs/heads/master:refs/remotes/origin/master &&\n"> <"\t(cd testrepo &&\n"> <"\t\tgit reset --hard origin/master\n"> <"\t\tgit config receive.denyCurrentBranch true) &&\n"> <"\n"> <"\techo >.git/foo \"To testrepo\" &&\n"> < "\techo >>.git/foo \"!\trefs/heads/master^:refs/heads/master\t[rejected] (non-fast-forward)\" &&\n" > <"\techo >>.git/foo \"Done\" &&\n"> <"\n"> < "\ttest_must_fail git push >.git/bar --porcelain --dry-run testrepo refs/heads/master^:refs/heads/master &&\n" > <"\ttest_cmp .git/foo .git/bar\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --prune">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master heads/second heads/foo heads/bar &&\n"> <"\tgit push --prune testrepo : &&\n"> <"\tcheck_push_result testrepo $the_commit heads/master &&\n"> <"\tcheck_push_result testrepo $the_first_commit heads/second &&\n"> <"\t! check_push_result testrepo $the_first_commit heads/foo heads/bar\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --prune refspec">)} { (SQ <"\n"> <"\tmk_test testrepo tmp/master tmp/second tmp/foo tmp/bar &&\n"> <"\tgit push --prune testrepo \"refs/heads/*:refs/tmp/*\" &&\n"> <"\tcheck_push_result testrepo $the_commit tmp/master &&\n"> <"\tcheck_push_result testrepo $the_first_commit tmp/second &&\n"> <"\t! check_push_result testrepo $the_first_commit tmp/foo tmp/bar\n"> ) } ) (ForEach iter_name: configsection iter_words: [{(transfer)} {(receive)}] do_arg_iter: False body: (DoGroup children: [ (C {(test_expect_success)} {(DQ ("push to update a ref hidden by ") ($ VSub_Name "$configsection") (.hiderefs))} { (SQ <"\n"> <"\t\tmk_test testrepo heads/master hidden/one hidden/two hidden/three &&\n"> <"\t\t(\n"> <"\t\t\tcd testrepo &&\n"> <"\t\t\tgit config $configsection.hiderefs refs/hidden\n"> <"\t\t) &&\n"> <"\n"> <"\t\t# push to unhidden ref succeeds normally\n"> <"\t\tgit push testrepo master:refs/heads/master &&\n"> <"\t\tcheck_push_result testrepo $the_commit heads/master &&\n"> <"\n"> <"\t\t# push to update a hidden ref should fail\n"> <"\t\ttest_must_fail git push testrepo master:refs/hidden/one &&\n"> <"\t\tcheck_push_result testrepo $the_first_commit hidden/one &&\n"> <"\n"> <"\t\t# push to delete a hidden ref should fail\n"> <"\t\ttest_must_fail git push testrepo :refs/hidden/two &&\n"> <"\t\tcheck_push_result testrepo $the_first_commit hidden/two &&\n"> <"\n"> <"\t\t# idempotent push to update a hidden ref should fail\n"> <"\t\ttest_must_fail git push testrepo $the_first_commit:refs/hidden/three &&\n"> <"\t\tcheck_push_result testrepo $the_first_commit hidden/three\n"> <"\t"> ) } ) ] spids: [2028 2065] ) spids: [2023 -1] ) (C {(test_expect_success)} {(SQ <"fetch exact SHA1">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master hidden/one &&\n"> <"\tgit push testrepo master:refs/hidden/one &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit config transfer.hiderefs refs/hidden\n"> <"\t) &&\n"> <"\tcheck_push_result testrepo $the_commit hidden/one &&\n"> <"\n"> <"\tmk_child testrepo child &&\n"> <"\t(\n"> <"\t\tcd child &&\n"> <"\n"> <"\t\t# make sure $the_commit does not exist here\n"> <"\t\tgit repack -a -d &&\n"> <"\t\tgit prune &&\n"> <"\t\ttest_must_fail git cat-file -t $the_commit &&\n"> <"\n"> <"\t\t# fetching the hidden object should fail by default\n"> <"\t\ttest_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&\n"> <"\t\ttest_must_fail git rev-parse --verify refs/heads/copy &&\n"> <"\n"> <"\t\t# the server side can allow it to succeed\n"> <"\t\t(\n"> <"\t\t\tcd ../testrepo &&\n"> <"\t\t\tgit config uploadpack.allowtipsha1inwant true\n"> <"\t\t) &&\n"> <"\n"> <"\t\tgit fetch -v ../testrepo $the_commit:refs/heads/copy master:refs/heads/extra &&\n"> <"\t\tcat >expect <<-EOF &&\n"> <"\t\t$the_commit\n"> <"\t\t$the_first_commit\n"> <"\t\tEOF\n"> <"\t\t{\n"> <"\t\t\tgit rev-parse --verify refs/heads/copy &&\n"> <"\t\t\tgit rev-parse --verify refs/heads/extra\n"> <"\t\t} >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (ForEach iter_name: configallowtipsha1inwant iter_words: [{(true)} {(false)}] do_arg_iter: False body: (DoGroup children: [ (C {(test_expect_success)} { (DQ ("shallow fetch reachable SHA1 (but not a ref), allowtipsha1inwant=") ($ VSub_Name "$configallowtipsha1inwant") ) } { (SQ <"\n"> <"\t\tmk_empty testrepo &&\n"> <"\t\t(\n"> <"\t\t\tcd testrepo &&\n"> <"\t\t\tgit config uploadpack.allowtipsha1inwant $configallowtipsha1inwant &&\n"> <"\t\t\tgit commit --allow-empty -m foo &&\n"> <"\t\t\tgit commit --allow-empty -m bar\n"> <"\t\t) &&\n"> <"\t\tSHA1=$(git --git-dir=testrepo/.git rev-parse HEAD^) &&\n"> <"\t\tmk_empty shallow &&\n"> <"\t\t(\n"> <"\t\t\tcd shallow &&\n"> <"\t\t\ttest_must_fail git fetch --depth=1 ../testrepo/.git $SHA1 &&\n"> < "\t\t\tgit --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true &&\n" > <"\t\t\tgit fetch --depth=1 ../testrepo/.git $SHA1 &&\n"> <"\t\t\tgit cat-file commit $SHA1\n"> <"\t\t)\n"> <"\t"> ) } ) (C {(test_expect_success)} { (DQ ("deny fetch unreachable SHA1, allowtipsha1inwant=") ($ VSub_Name "$configallowtipsha1inwant") ) } { (SQ <"\n"> <"\t\tmk_empty testrepo &&\n"> <"\t\t(\n"> <"\t\t\tcd testrepo &&\n"> <"\t\t\tgit config uploadpack.allowtipsha1inwant $configallowtipsha1inwant &&\n"> <"\t\t\tgit commit --allow-empty -m foo &&\n"> <"\t\t\tgit commit --allow-empty -m bar &&\n"> <"\t\t\tgit commit --allow-empty -m xyz\n"> <"\t\t) &&\n"> <"\t\tSHA1_1=$(git --git-dir=testrepo/.git rev-parse HEAD^^) &&\n"> <"\t\tSHA1_2=$(git --git-dir=testrepo/.git rev-parse HEAD^) &&\n"> <"\t\tSHA1_3=$(git --git-dir=testrepo/.git rev-parse HEAD) &&\n"> <"\t\t(\n"> <"\t\t\tcd testrepo &&\n"> <"\t\t\tgit reset --hard $SHA1_2 &&\n"> <"\t\t\tgit cat-file commit $SHA1_1 &&\n"> <"\t\t\tgit cat-file commit $SHA1_3\n"> <"\t\t) &&\n"> <"\t\tmk_empty shallow &&\n"> <"\t\t(\n"> <"\t\t\tcd shallow &&\n"> <"\t\t\ttest_must_fail ok=sigpipe git fetch ../testrepo/.git $SHA1_3 &&\n"> <"\t\t\ttest_must_fail ok=sigpipe git fetch ../testrepo/.git $SHA1_1 &&\n"> < "\t\t\tgit --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true &&\n" > <"\t\t\tgit fetch ../testrepo/.git $SHA1_1 &&\n"> <"\t\t\tgit cat-file commit $SHA1_1 &&\n"> <"\t\t\ttest_must_fail git cat-file commit $SHA1_2 &&\n"> <"\t\t\tgit fetch ../testrepo/.git $SHA1_2 &&\n"> <"\t\t\tgit cat-file commit $SHA1_2 &&\n"> <"\t\t\ttest_must_fail ok=sigpipe git fetch ../testrepo/.git $SHA1_3\n"> <"\t\t)\n"> <"\t"> ) } ) ] spids: [2127 2202] ) spids: [2122 -1] ) (C {(test_expect_success)} {(SQ <"fetch follows tags by default">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\trm -fr src dst &&\n"> <"\tgit init src &&\n"> <"\t(\n"> <"\t\tcd src &&\n"> <"\t\tgit pull ../testrepo master &&\n"> <"\t\tgit tag -m \"annotated\" tag &&\n"> <"\t\tgit for-each-ref >tmp1 &&\n"> <"\t\t(\n"> <"\t\t\tcat tmp1\n"> <"\t\t\tsed -n \"s|refs/heads/master$|refs/remotes/origin/master|p\" tmp1\n"> <"\t\t) |\n"> <"\t\tsort -k 3 >../expect\n"> <"\t) &&\n"> <"\tgit init dst &&\n"> <"\t(\n"> <"\t\tcd dst &&\n"> <"\t\tgit remote add origin ../src &&\n"> <"\t\tgit config branch.master.remote origin &&\n"> <"\t\tgit config branch.master.merge refs/heads/master &&\n"> <"\t\tgit pull &&\n"> <"\t\tgit for-each-ref >../actual\n"> <"\t) &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"pushing a specific ref applies remote.$name.push as refmap">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\trm -fr src dst &&\n"> <"\tgit init src &&\n"> <"\tgit init --bare dst &&\n"> <"\t(\n"> <"\t\tcd src &&\n"> <"\t\tgit pull ../testrepo master &&\n"> <"\t\tgit branch next &&\n"> <"\t\tgit config remote.dst.url ../dst &&\n"> <"\t\tgit config remote.dst.push \"+refs/heads/*:refs/remotes/src/*\" &&\n"> <"\t\tgit push dst master &&\n"> <"\t\tgit show-ref refs/heads/master |\n"> <"\t\tsed -e \"s|refs/heads/|refs/remotes/src/|\" >../dst/expect\n"> <"\t) &&\n"> <"\t(\n"> <"\t\tcd dst &&\n"> <"\t\ttest_must_fail git show-ref refs/heads/next &&\n"> <"\t\ttest_must_fail git show-ref refs/heads/master &&\n"> <"\t\tgit show-ref refs/remotes/src/master >actual\n"> <"\t) &&\n"> <"\ttest_cmp dst/expect dst/actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"with no remote.$name.push, it is not used as refmap">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\trm -fr src dst &&\n"> <"\tgit init src &&\n"> <"\tgit init --bare dst &&\n"> <"\t(\n"> <"\t\tcd src &&\n"> <"\t\tgit pull ../testrepo master &&\n"> <"\t\tgit branch next &&\n"> <"\t\tgit config remote.dst.url ../dst &&\n"> <"\t\tgit config push.default matching &&\n"> <"\t\tgit push dst master &&\n"> <"\t\tgit show-ref refs/heads/master >../dst/expect\n"> <"\t) &&\n"> <"\t(\n"> <"\t\tcd dst &&\n"> <"\t\ttest_must_fail git show-ref refs/heads/next &&\n"> <"\t\tgit show-ref refs/heads/master >actual\n"> <"\t) &&\n"> <"\ttest_cmp dst/expect dst/actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"with no remote.$name.push, upstream mapping is used">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\trm -fr src dst &&\n"> <"\tgit init src &&\n"> <"\tgit init --bare dst &&\n"> <"\t(\n"> <"\t\tcd src &&\n"> <"\t\tgit pull ../testrepo master &&\n"> <"\t\tgit branch next &&\n"> <"\t\tgit config remote.dst.url ../dst &&\n"> <"\t\tgit config remote.dst.fetch \"+refs/heads/*:refs/remotes/dst/*\" &&\n"> <"\t\tgit config push.default upstream &&\n"> <"\n"> <"\t\tgit config branch.master.merge refs/heads/trunk &&\n"> <"\t\tgit config branch.master.remote dst &&\n"> <"\n"> <"\t\tgit push dst master &&\n"> <"\t\tgit show-ref refs/heads/master |\n"> <"\t\tsed -e \"s|refs/heads/master|refs/heads/trunk|\" >../dst/expect\n"> <"\t) &&\n"> <"\t(\n"> <"\t\tcd dst &&\n"> <"\t\ttest_must_fail git show-ref refs/heads/master &&\n"> <"\t\ttest_must_fail git show-ref refs/heads/next &&\n"> <"\t\tgit show-ref refs/heads/trunk >actual\n"> <"\t) &&\n"> <"\ttest_cmp dst/expect dst/actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"push does not follow tags by default">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\trm -fr src dst &&\n"> <"\tgit init src &&\n"> <"\tgit init --bare dst &&\n"> <"\t(\n"> <"\t\tcd src &&\n"> <"\t\tgit pull ../testrepo master &&\n"> <"\t\tgit tag -m \"annotated\" tag &&\n"> <"\t\tgit checkout -b another &&\n"> <"\t\tgit commit --allow-empty -m \"future commit\" &&\n"> <"\t\tgit tag -m \"future\" future &&\n"> <"\t\tgit checkout master &&\n"> <"\t\tgit for-each-ref refs/heads/master >../expect &&\n"> <"\t\tgit push ../dst master\n"> <"\t) &&\n"> <"\t(\n"> <"\t\tcd dst &&\n"> <"\t\tgit for-each-ref >../actual\n"> <"\t) &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --follow-tag only pushes relevant tags">)} { (SQ <"\n"> <"\tmk_test testrepo heads/master &&\n"> <"\trm -fr src dst &&\n"> <"\tgit init src &&\n"> <"\tgit init --bare dst &&\n"> <"\t(\n"> <"\t\tcd src &&\n"> <"\t\tgit pull ../testrepo master &&\n"> <"\t\tgit tag -m \"annotated\" tag &&\n"> <"\t\tgit checkout -b another &&\n"> <"\t\tgit commit --allow-empty -m \"future commit\" &&\n"> <"\t\tgit tag -m \"future\" future &&\n"> <"\t\tgit checkout master &&\n"> <"\t\tgit for-each-ref refs/heads/master refs/tags/tag >../expect\n"> <"\t\tgit push --follow-tag ../dst master\n"> <"\t) &&\n"> <"\t(\n"> <"\t\tcd dst &&\n"> <"\t\tgit for-each-ref >../actual\n"> <"\t) &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --no-thin must produce non-thin pack">)} { (SQ <"\n"> <"\tcat >>path1 <<\\EOF &&\n"> <"keep base version of path1 big enough, compared to the new changes\n"> <"later, in order to pass size heuristics in\n"> <"builtin/pack-objects.c:try_delta()\n"> <"EOF\n"> <"\tgit commit -am initial &&\n"> <"\tgit init no-thin &&\n"> <"\tgit --git-dir=no-thin/.git config receive.unpacklimit 0 &&\n"> <"\tgit push no-thin/.git refs/heads/master:refs/heads/foo &&\n"> <"\techo modified >> path1 &&\n"> <"\tgit commit -am modified &&\n"> <"\tgit repack -adf &&\n"> <"\trcvpck=\"git receive-pack --reject-thin-pack-for-testing\" &&\n"> <"\tgit push --no-thin --receive-pack=\"$rcvpck\" no-thin/.git refs/heads/master:refs/heads/foo\n"> ) } ) (C {(test_expect_success)} {(SQ <"pushing a tag pushes the tagged object">)} { (SQ <"\n"> <"\trm -rf dst.git &&\n"> <"\tblob=$(echo unreferenced | git hash-object -w --stdin) &&\n"> <"\tgit tag -m foo tag-of-blob $blob &&\n"> <"\tgit init --bare dst.git &&\n"> <"\tgit push dst.git tag-of-blob &&\n"> <"\t# the receiving index-pack should have noticed\n"> <"\t# any problems, but we double check\n"> <"\techo unreferenced >expect &&\n"> <"\tgit --git-dir=dst.git cat-file blob tag-of-blob >actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"push into bare respects core.logallrefupdates">)} { (SQ <"\n"> <"\trm -rf dst.git &&\n"> <"\tgit init --bare dst.git &&\n"> <"\tgit -C dst.git config core.logallrefupdates true &&\n"> <"\n"> <"\t# double push to test both with and without\n"> <"\t# the actual pack transfer\n"> <"\tgit push dst.git master:one &&\n"> <"\techo \"one@{0} push\" >expect &&\n"> <"\tgit -C dst.git log -g --format=\"%gd %gs\" one >actual &&\n"> <"\ttest_cmp expect actual &&\n"> <"\n"> <"\tgit push dst.git master:two &&\n"> <"\techo \"two@{0} push\" >expect &&\n"> <"\tgit -C dst.git log -g --format=\"%gd %gs\" two >actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"fetch into bare respects core.logallrefupdates">)} { (SQ <"\n"> <"\trm -rf dst.git &&\n"> <"\tgit init --bare dst.git &&\n"> <"\t(\n"> <"\t\tcd dst.git &&\n"> <"\t\tgit config core.logallrefupdates true &&\n"> <"\n"> <"\t\t# as above, we double-fetch to test both\n"> <"\t\t# with and without pack transfer\n"> <"\t\tgit fetch .. master:one &&\n"> <"\t\techo \"one@{0} fetch .. master:one: storing head\" >expect &&\n"> <"\t\tgit log -g --format=\"%gd %gs\" one >actual &&\n"> <"\t\ttest_cmp expect actual &&\n"> <"\n"> <"\t\tgit fetch .. master:two &&\n"> <"\t\techo \"two@{0} fetch .. master:two: storing head\" >expect &&\n"> <"\t\tgit log -g --format=\"%gd %gs\" two >actual &&\n"> <"\t\ttest_cmp expect actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"receive.denyCurrentBranch = updateInstead">)} { (SQ <"\n"> <"\tgit push testrepo master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\tgit config receive.denyCurrentBranch updateInstead\n"> <"\t) &&\n"> <"\ttest_commit third path2 &&\n"> <"\n"> <"\t# Try pushing into a repository with pristine working tree\n"> <"\tgit push testrepo master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit update-index -q --refresh &&\n"> <"\t\tgit diff-files --quiet -- &&\n"> <"\t\tgit diff-index --quiet --cached HEAD -- &&\n"> <"\t\ttest third = \"$(cat path2)\" &&\n"> <"\t\ttest $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)\n"> <"\t) &&\n"> <"\n"> <"\t# Try pushing into a repository with working tree needing a refresh\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit reset --hard HEAD^ &&\n"> <"\t\ttest $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&\n"> <"\t\ttest-chmtime +100 path1\n"> <"\t) &&\n"> <"\tgit push testrepo master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit update-index -q --refresh &&\n"> <"\t\tgit diff-files --quiet -- &&\n"> <"\t\tgit diff-index --quiet --cached HEAD -- &&\n"> <"\t\ttest_cmp ../path1 path1 &&\n"> <"\t\ttest third = \"$(cat path2)\" &&\n"> <"\t\ttest $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)\n"> <"\t) &&\n"> <"\n"> <"\t# Update what is to be pushed\n"> <"\ttest_commit fourth path2 &&\n"> <"\n"> <"\t# Try pushing into a repository with a dirty working tree\n"> <"\t# (1) the working tree updated\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\techo changed >path1\n"> <"\t) &&\n"> <"\ttest_must_fail git push testrepo master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\ttest $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&\n"> <"\t\tgit diff --quiet --cached &&\n"> <"\t\ttest changed = \"$(cat path1)\"\n"> <"\t) &&\n"> <"\n"> <"\t# (2) the index updated\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\techo changed >path1 &&\n"> <"\t\tgit add path1\n"> <"\t) &&\n"> <"\ttest_must_fail git push testrepo master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\ttest $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&\n"> <"\t\tgit diff --quiet &&\n"> <"\t\ttest changed = \"$(cat path1)\"\n"> <"\t) &&\n"> <"\n"> <"\t# Introduce a new file in the update\n"> <"\ttest_commit fifth path3 &&\n"> <"\n"> <"\t# (3) the working tree has an untracked file that would interfere\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\techo changed >path3\n"> <"\t) &&\n"> <"\ttest_must_fail git push testrepo master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\ttest $(git -C .. rev-parse HEAD^^) = $(git rev-parse HEAD) &&\n"> <"\t\tgit diff --quiet &&\n"> <"\t\tgit diff --quiet --cached &&\n"> <"\t\ttest changed = \"$(cat path3)\"\n"> <"\t) &&\n"> <"\n"> <"\t# (4) the target changes to what gets pushed but it still is a change\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit reset --hard &&\n"> <"\t\techo fifth >path3 &&\n"> <"\t\tgit add path3\n"> <"\t) &&\n"> <"\ttest_must_fail git push testrepo master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\ttest $(git -C .. rev-parse HEAD^^) = $(git rev-parse HEAD) &&\n"> <"\t\tgit diff --quiet &&\n"> <"\t\ttest fifth = \"$(cat path3)\"\n"> <"\t) &&\n"> <"\n"> <"\t# (5) push into void\n"> <"\trm -fr void &&\n"> <"\tgit init void &&\n"> <"\t(\n"> <"\t\tcd void &&\n"> <"\t\tgit config receive.denyCurrentBranch updateInstead\n"> <"\t) &&\n"> <"\tgit push void master &&\n"> <"\t(\n"> <"\t\tcd void &&\n"> <"\t\ttest $(git -C .. rev-parse master) = $(git rev-parse HEAD) &&\n"> <"\t\tgit diff --quiet &&\n"> <"\t\tgit diff --cached --quiet\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"updateInstead with push-to-checkout hook">)} { (SQ <"\n"> <"\trm -fr testrepo &&\n"> <"\tgit init testrepo &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit pull .. master &&\n"> <"\t\tgit reset --hard HEAD^^ &&\n"> <"\t\tgit tag initial &&\n"> <"\t\tgit config receive.denyCurrentBranch updateInstead &&\n"> <"\t\twrite_script .git/hooks/push-to-checkout <<-\\EOF\n"> <"\t\techo >&2 updating from $(git rev-parse HEAD)\n"> <"\t\techo >&2 updating to \"$1\"\n"> <"\n"> <"\t\tgit update-index -q --refresh &&\n"> <"\t\tgit read-tree -u -m HEAD \"$1\" || {\n"> <"\t\t\tstatus=$?\n"> <"\t\t\techo >&2 read-tree failed\n"> <"\t\t\texit $status\n"> <"\t\t}\n"> <"\t\tEOF\n"> <"\t) &&\n"> <"\n"> <"\t# Try pushing into a pristine\n"> <"\tgit push testrepo master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit diff --quiet &&\n"> <"\t\tgit diff HEAD --quiet &&\n"> <"\t\ttest $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)\n"> <"\t) &&\n"> <"\n"> <"\t# Try pushing into a repository with conflicting change\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit reset --hard initial &&\n"> <"\t\techo conflicting >path2\n"> <"\t) &&\n"> <"\ttest_must_fail git push testrepo master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\ttest $(git rev-parse initial) = $(git rev-parse HEAD) &&\n"> <"\t\ttest conflicting = \"$(cat path2)\" &&\n"> <"\t\tgit diff-index --quiet --cached HEAD\n"> <"\t) &&\n"> <"\n"> <"\t# Try pushing into a repository with unrelated change\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\tgit reset --hard initial &&\n"> <"\t\techo unrelated >path1 &&\n"> <"\t\techo irrelevant >path5 &&\n"> <"\t\tgit add path5\n"> <"\t) &&\n"> <"\tgit push testrepo master &&\n"> <"\t(\n"> <"\t\tcd testrepo &&\n"> <"\t\ttest \"$(cat path1)\" = unrelated &&\n"> <"\t\ttest \"$(cat path5)\" = irrelevant &&\n"> <"\t\ttest \"$(git diff --name-only --cached HEAD)\" = path5 &&\n"> <"\t\ttest $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)\n"> <"\t) &&\n"> <"\n"> <"\t# push into void\n"> <"\trm -fr void &&\n"> <"\tgit init void &&\n"> <"\t(\n"> <"\t\tcd void &&\n"> <"\t\tgit config receive.denyCurrentBranch updateInstead &&\n"> <"\t\twrite_script .git/hooks/push-to-checkout <<-\\EOF\n"> <"\t\tif git rev-parse --quiet --verify HEAD\n"> <"\t\tthen\n"> <"\t\t\thas_head=yes\n"> <"\t\t\techo >&2 updating from $(git rev-parse HEAD)\n"> <"\t\telse\n"> <"\t\t\thas_head=no\n"> <"\t\t\techo >&2 pushing into void\n"> <"\t\tfi\n"> <"\t\techo >&2 updating to \"$1\"\n"> <"\n"> <"\t\tgit update-index -q --refresh &&\n"> <"\t\tcase \"$has_head\" in\n"> <"\t\tyes)\n"> <"\t\t\tgit read-tree -u -m HEAD \"$1\" ;;\n"> <"\t\tno)\n"> <"\t\t\tgit read-tree -u -m \"$1\" ;;\n"> <"\t\tesac || {\n"> <"\t\t\tstatus=$?\n"> <"\t\t\techo >&2 read-tree failed\n"> <"\t\t\texit $status\n"> <"\t\t}\n"> <"\t\tEOF\n"> <"\t) &&\n"> <"\n"> <"\tgit push void master &&\n"> <"\t(\n"> <"\t\tcd void &&\n"> <"\t\tgit diff --quiet &&\n"> <"\t\tgit diff --cached --quiet &&\n"> <"\t\ttest $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)\n"> <"\t)\n"> ) } ) (C {(test_done)}) ] )