#!/bin/sh global test_description := ''check various push.default settings'' source ./test-lib.sh test_expect_success 'setup bare remotes' ' git init --bare repo1 && git remote add parent1 repo1 && git init --bare repo2 && git remote add parent2 repo2 && test_commit one && git push parent1 HEAD && git push parent2 HEAD ' # $1 = local revision # $2 = remote revision (tested to be equal to the local one) # $3 = [optional] repo to check for actual output (repo1 by default) proc check_pushed_commit { git log -1 --format='%h %s' $1 >expect && git --git-dir="$(3:-repo1)" log -1 --format='%h %s' $2 >actual && test_cmp expect actual } # $1 = push.default value # $2 = expected target branch for the push # $3 = [optional] repo to check for actual output (repo1 by default) proc test_push_success { git $(1:+-c) $(1:+push.default="$1") push && check_pushed_commit HEAD $2 $3 } # $1 = push.default value # check that push fails and does not modify any remote branch proc test_push_failure { git --git-dir=repo1 log --no-walk --format='%h %s' --all >expect && test_must_fail git $(1:+-c) $(1:+push.default="$1") push && git --git-dir=repo1 log --no-walk --format='%h %s' --all >actual && test_cmp expect actual } # $1 = success or failure # $2 = push.default value # $3 = branch to check for actual output (master or foo) # $4 = [optional] switch to triangular workflow proc test_pushdefault_workflow { global workflow := 'central' global pushdefault := 'parent1' if test -n $(4-) { global workflow := 'triangular' global pushdefault := 'parent2' } test_expect_success "push.default = $2 $1 in $workflow workflows" " test_config branch.master.remote parent1 && test_config branch.master.merge refs/heads/foo && test_config remote.pushdefault $pushdefault && test_commit commit-for-$2$(4+-triangular) && test_push_$1 $2 $3 $(4+repo2) " } test_expect_success '"upstream" pushes to configured upstream' ' git checkout master && test_config branch.master.remote parent1 && test_config branch.master.merge refs/heads/foo && test_commit two && test_push_success upstream foo ' test_expect_success '"upstream" does not push on unconfigured remote' ' git checkout master && test_unconfig branch.master.remote && test_commit three && test_push_failure upstream ' test_expect_success '"upstream" does not push on unconfigured branch' ' git checkout master && test_config branch.master.remote parent1 && test_unconfig branch.master.merge && test_commit four && test_push_failure upstream ' test_expect_success '"upstream" does not push when remotes do not match' ' git checkout master && test_config branch.master.remote parent1 && test_config branch.master.merge refs/heads/foo && test_config push.default upstream && test_commit five && test_must_fail git push parent2 ' test_expect_success 'push from/to new branch with upstream, matching and simple' ' git checkout -b new-branch && test_push_failure simple && test_push_failure matching && test_push_failure upstream ' test_expect_success 'push from/to new branch with current creates remote branch' ' test_config branch.new-branch.remote repo1 && git checkout new-branch && test_push_success current new-branch ' test_expect_success 'push to existing branch, with no upstream configured' ' test_config branch.master.remote repo1 && git checkout master && test_push_failure simple && test_push_failure upstream ' test_expect_success 'push to existing branch, upstream configured with same name' ' test_config branch.master.remote repo1 && test_config branch.master.merge refs/heads/master && git checkout master && test_commit six && test_push_success upstream master && test_commit seven && test_push_success simple master ' test_expect_success 'push to existing branch, upstream configured with different name' ' test_config branch.master.remote repo1 && test_config branch.master.merge refs/heads/other-name && git checkout master && test_commit eight && test_push_success upstream other-name && test_commit nine && test_push_failure simple && git --git-dir=repo1 log -1 --format="%h %s" "other-name" >expect-other-name && test_push_success current master && git --git-dir=repo1 log -1 --format="%h %s" "other-name" >actual-other-name && test_cmp expect-other-name actual-other-name ' # We are on 'master', which integrates with 'foo' from parent1 # remote (set in test_pushdefault_workflow helper). Push to # parent1 in centralized, and push to parent2 in triangular workflow. # The parent1 repository has 'master' and 'foo' branches, while # the parent2 repository has only 'master' branch. # # test_pushdefault_workflow() arguments: # $1 = success or failure # $2 = push.default value # $3 = branch to check for actual output (master or foo) # $4 = [optional] switch to triangular workflow # update parent1's master (which is not our upstream) test_pushdefault_workflow success current master # update parent1's foo (which is our upstream) test_pushdefault_workflow success upstream foo # upsream is foo which is not the name of the current branch test_pushdefault_workflow failure simple master # master and foo are updated test_pushdefault_workflow success matching master # master is updated test_pushdefault_workflow success current master triangular # upstream mode cannot be used in triangular test_pushdefault_workflow failure upstream foo triangular # in triangular, 'simple' works as 'current' and update the branch # with the same name. test_pushdefault_workflow success simple master triangular # master is updated (parent2 does not have foo) test_pushdefault_workflow success matching master triangular # default tests, when no push-default is specified. This # should behave the same as "simple" in non-triangular # settings, and as "current" otherwise. test_expect_success 'default behavior allows "simple" push' ' test_config branch.master.remote parent1 && test_config branch.master.merge refs/heads/master && test_config remote.pushdefault parent1 && test_commit default-master-master && test_push_success "" master ' test_expect_success 'default behavior rejects non-simple push' ' test_config branch.master.remote parent1 && test_config branch.master.merge refs/heads/foo && test_config remote.pushdefault parent1 && test_commit default-master-foo && test_push_failure "" ' test_expect_success 'default triangular behavior acts like "current"' ' test_config branch.master.remote parent1 && test_config branch.master.merge refs/heads/foo && test_config remote.pushdefault parent2 && test_commit default-triangular && test_push_success "" master repo2 ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"check various push.default settings">)} spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (C {(test_expect_success)} {(SQ <"setup bare remotes">)} { (SQ <"\n"> <"\tgit init --bare repo1 &&\n"> <"\tgit remote add parent1 repo1 &&\n"> <"\tgit init --bare repo2 &&\n"> <"\tgit remote add parent2 repo2 &&\n"> <"\ttest_commit one &&\n"> <"\tgit push parent1 HEAD &&\n"> <"\tgit push parent2 HEAD\n"> ) } ) (FuncDef name: check_pushed_commit body: (BraceGroup children: [ (AndOr children: [ (SimpleCommand words: [ {(git)} {(log)} {(-1)} {(--format) (Lit_Other "=") (SQ <"%h %s">)} {(DQ ($ VSub_Number "$1"))} ] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(expect)} spids:[65])] ) (AndOr children: [ (SimpleCommand words: [ {(git)} {(--git-dir) (Lit_Other "=") (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(repo1)}) spids: [76 80] ) ) } {(log)} {(-1)} {(--format) (Lit_Other "=") (SQ <"%h %s">)} {(DQ ($ VSub_Number "$2"))} ] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(actual)} spids:[97])] ) (C {(test_cmp)} {(expect)} {(actual)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [46] ) spids: [41 45] ) (FuncDef name: test_push_success body: (BraceGroup children: [ (AndOr children: [ (C {(git)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonPlus arg_word:{(-c)}) spids: [131 135] ) } { (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonPlus arg_word: {("push.default=") (DQ ($ VSub_Number "$1"))} ) spids: [137 144] ) } {(push)} ) (C {(check_pushed_commit)} {(HEAD)} {(DQ ($ VSub_Number "$2"))} {(DQ ($ VSub_Number "$3"))} ) ] op_id: Op_DAmp ) ] spids: [126] ) spids: [121 125] ) (FuncDef name: test_push_failure body: (BraceGroup children: [ (AndOr children: [ (SimpleCommand words: [ {(git)} {(--git-dir) (Lit_Other "=") (repo1)} {(log)} {(--no-walk)} {(--format) (Lit_Other "=") (SQ <"%h %s">)} {(--all)} ] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(expect)} spids:[198])] ) (AndOr children: [ (C {(test_must_fail)} {(git)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonPlus arg_word:{(-c)}) spids: [208 212] ) } { (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonPlus arg_word: {("push.default=") (DQ ($ VSub_Number "$1"))} ) spids: [214 221] ) } {(push)} ) (AndOr children: [ (SimpleCommand words: [ {(git)} {(--git-dir) (Lit_Other "=") (repo1)} {(log)} {(--no-walk)} {(--format) (Lit_Other "=") (SQ <"%h %s">)} {(--all)} ] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(actual)} spids:[246])] ) (C {(test_cmp)} {(expect)} {(actual)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [177] ) spids: [172 176] ) (FuncDef name: test_pushdefault_workflow body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:workflow) op:Equal rhs:{(central)} spids:[281])] spids: [281] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:pushdefault) op: Equal rhs: {(parent1)} spids: [285] ) ] spids: [285] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(test)} {(-n)} { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_Hyphen arg_word:{(SQ )}) spids: [296 299] ) ) } ) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:workflow) op: Equal rhs: {(triangular)} spids: [306] ) ] spids: [306] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:pushdefault) op: Equal rhs: {(parent2)} spids: [310] ) ] spids: [310] ) ] spids: [-1 303] ) ] spids: [-1 314] ) (C {(test_expect_success)} { (DQ ("push.default = ") ($ VSub_Number "$2") (" ") ($ VSub_Number "$1") (" in ") ($ VSub_Name "$workflow") (" workflows") ) } { (DQ ("\n") ("\t\ttest_config branch.master.remote parent1 &&\n") ("\t\ttest_config branch.master.merge refs/heads/foo &&\n") ("\t\ttest_config remote.pushdefault ") ($ VSub_Name "$pushdefault") (" &&\n") ("\t\ttest_commit commit-for-") ($ VSub_Number "$2") (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_Plus arg_word:{(-triangular)}) spids: [338 342] ) (" &&\n") ("\t\ttest_push_") ($ VSub_Number "$1") (" ") ($ VSub_Number "$2") (" ") ($ VSub_Number "$3") (" ") (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_Plus arg_word:{(repo2)}) spids: [351 355] ) ("\n") ("\t") ) } ) ] spids: [278] ) spids: [273 277] ) (C {(test_expect_success)} {(SQ <"\"upstream\" pushes to configured upstream">)} { (SQ <"\n"> <"\tgit checkout master &&\n"> <"\ttest_config branch.master.remote parent1 &&\n"> <"\ttest_config branch.master.merge refs/heads/foo &&\n"> <"\ttest_commit two &&\n"> <"\ttest_push_success upstream foo\n"> ) } ) (C {(test_expect_success)} {(SQ <"\"upstream\" does not push on unconfigured remote">)} { (SQ <"\n"> <"\tgit checkout master &&\n"> <"\ttest_unconfig branch.master.remote &&\n"> <"\ttest_commit three &&\n"> <"\ttest_push_failure upstream\n"> ) } ) (C {(test_expect_success)} {(SQ <"\"upstream\" does not push on unconfigured branch">)} { (SQ <"\n"> <"\tgit checkout master &&\n"> <"\ttest_config branch.master.remote parent1 &&\n"> <"\ttest_unconfig branch.master.merge &&\n"> <"\ttest_commit four &&\n"> <"\ttest_push_failure upstream\n"> ) } ) (C {(test_expect_success)} {(SQ <"\"upstream\" does not push when remotes do not match">)} { (SQ <"\n"> <"\tgit checkout master &&\n"> <"\ttest_config branch.master.remote parent1 &&\n"> <"\ttest_config branch.master.merge refs/heads/foo &&\n"> <"\ttest_config push.default upstream &&\n"> <"\ttest_commit five &&\n"> <"\ttest_must_fail git push parent2\n"> ) } ) (C {(test_expect_success)} {(SQ <"push from/to new branch with upstream, matching and simple">)} { (SQ <"\n"> <"\tgit checkout -b new-branch &&\n"> <"\ttest_push_failure simple &&\n"> <"\ttest_push_failure matching &&\n"> <"\ttest_push_failure upstream\n"> ) } ) (C {(test_expect_success)} {(SQ <"push from/to new branch with current creates remote branch">)} { (SQ <"\n"> <"\ttest_config branch.new-branch.remote repo1 &&\n"> <"\tgit checkout new-branch &&\n"> <"\ttest_push_success current new-branch\n"> ) } ) (C {(test_expect_success)} {(SQ <"push to existing branch, with no upstream configured">)} { (SQ <"\n"> <"\ttest_config branch.master.remote repo1 &&\n"> <"\tgit checkout master &&\n"> <"\ttest_push_failure simple &&\n"> <"\ttest_push_failure upstream\n"> ) } ) (C {(test_expect_success)} {(SQ <"push to existing branch, upstream configured with same name">)} { (SQ <"\n"> <"\ttest_config branch.master.remote repo1 &&\n"> <"\ttest_config branch.master.merge refs/heads/master &&\n"> <"\tgit checkout master &&\n"> <"\ttest_commit six &&\n"> <"\ttest_push_success upstream master &&\n"> <"\ttest_commit seven &&\n"> <"\ttest_push_success simple master\n"> ) } ) (C {(test_expect_success)} {(SQ <"push to existing branch, upstream configured with different name">)} { (SQ <"\n"> <"\ttest_config branch.master.remote repo1 &&\n"> <"\ttest_config branch.master.merge refs/heads/other-name &&\n"> <"\tgit checkout master &&\n"> <"\ttest_commit eight &&\n"> <"\ttest_push_success upstream other-name &&\n"> <"\ttest_commit nine &&\n"> <"\ttest_push_failure simple &&\n"> < "\tgit --git-dir=repo1 log -1 --format=\"%h %s\" \"other-name\" >expect-other-name &&\n" > <"\ttest_push_success current master &&\n"> < "\tgit --git-dir=repo1 log -1 --format=\"%h %s\" \"other-name\" >actual-other-name &&\n" > <"\ttest_cmp expect-other-name actual-other-name\n"> ) } ) (C {(test_pushdefault_workflow)} {(success)} {(current)} {(master)}) (C {(test_pushdefault_workflow)} {(success)} {(upstream)} {(foo)}) (C {(test_pushdefault_workflow)} {(failure)} {(simple)} {(master)}) (C {(test_pushdefault_workflow)} {(success)} {(matching)} {(master)}) (C {(test_pushdefault_workflow)} {(success)} {(current)} {(master)} {(triangular)}) (C {(test_pushdefault_workflow)} {(failure)} {(upstream)} {(foo)} {(triangular)}) (C {(test_pushdefault_workflow)} {(success)} {(simple)} {(master)} {(triangular)}) (C {(test_pushdefault_workflow)} {(success)} {(matching)} {(master)} {(triangular)}) (C {(test_expect_success)} {(SQ <"default behavior allows \"simple\" push">)} { (SQ <"\n"> <"\ttest_config branch.master.remote parent1 &&\n"> <"\ttest_config branch.master.merge refs/heads/master &&\n"> <"\ttest_config remote.pushdefault parent1 &&\n"> <"\ttest_commit default-master-master &&\n"> <"\ttest_push_success \"\" master\n"> ) } ) (C {(test_expect_success)} {(SQ <"default behavior rejects non-simple push">)} { (SQ <"\n"> <"\ttest_config branch.master.remote parent1 &&\n"> <"\ttest_config branch.master.merge refs/heads/foo &&\n"> <"\ttest_config remote.pushdefault parent1 &&\n"> <"\ttest_commit default-master-foo &&\n"> <"\ttest_push_failure \"\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"default triangular behavior acts like \"current\"">)} { (SQ <"\n"> <"\ttest_config branch.master.remote parent1 &&\n"> <"\ttest_config branch.master.merge refs/heads/foo &&\n"> <"\ttest_config remote.pushdefault parent2 &&\n"> <"\ttest_commit default-triangular &&\n"> <"\ttest_push_success \"\" master repo2\n"> ) } ) (C {(test_done)}) ] )