#!/bin/sh # # Copyright (c) 2005 Junio C Hamano # global test_description := ''See why rewinding head breaks send-pack '' source ./test-lib.sh global cnt := '64' test_expect_success setup ' test_tick && mkdir mozart mozart/is && echo "Commit #0" >mozart/is/pink && git update-index --add mozart/is/pink && tree=$(git write-tree) && commit=$(echo "Commit #0" | git commit-tree $tree) && zero=$commit && parent=$zero && i=0 && while test $i -le $cnt do i=$(($i+1)) && test_tick && echo "Commit #$i" >mozart/is/pink && git update-index --add mozart/is/pink && tree=$(git write-tree) && commit=$(echo "Commit #$i" | git commit-tree $tree -p $parent) && git update-ref refs/tags/commit$i $commit && parent=$commit || return 1 done && git update-ref HEAD "$commit" && git clone ./. victim && ( cd victim && git config receive.denyCurrentBranch warn && git log ) && git update-ref HEAD "$zero" && parent=$zero && i=0 && while test $i -le $cnt do i=$(($i+1)) && test_tick && echo "Rebase #$i" >mozart/is/pink && git update-index --add mozart/is/pink && tree=$(git write-tree) && commit=$(echo "Rebase #$i" | git commit-tree $tree -p $parent) && git update-ref refs/tags/rebase$i $commit && parent=$commit || return 1 done && git update-ref HEAD "$commit" && echo Rebase && git log' test_expect_success 'pack the source repository' ' git repack -a -d && git prune ' test_expect_success 'pack the destination repository' ' ( cd victim && git repack -a -d && git prune ) ' test_expect_success 'refuse pushing rewound head without --force' ' pushed_head=$(git rev-parse --verify master) && victim_orig=$(cd victim && git rev-parse --verify master) && test_must_fail git send-pack ./victim master && victim_head=$(cd victim && git rev-parse --verify master) && test "$victim_head" = "$victim_orig" && # this should update git send-pack --force ./victim master && victim_head=$(cd victim && git rev-parse --verify master) && test "$victim_head" = "$pushed_head" ' test_expect_success 'push can be used to delete a ref' ' ( cd victim && git branch extra master ) && git send-pack ./victim :extra master && ( cd victim && test_must_fail git rev-parse --verify extra ) ' test_expect_success 'refuse deleting push with denyDeletes' ' ( cd victim && ( git branch -D extra || : ) && git config receive.denyDeletes true && git branch extra master ) && test_must_fail git send-pack ./victim :extra master ' test_expect_success 'cannot override denyDeletes with git -c send-pack' ' ( cd victim && test_might_fail git branch -D extra && git config receive.denyDeletes true && git branch extra master ) && test_must_fail git -c receive.denyDeletes=false \ send-pack ./victim :extra master ' test_expect_success 'override denyDeletes with git -c receive-pack' ' ( cd victim && test_might_fail git branch -D extra && git config receive.denyDeletes true && git branch extra master ) && git send-pack \ --receive-pack="git -c receive.denyDeletes=false receive-pack" \ ./victim :extra master ' test_expect_success 'denyNonFastforwards trumps --force' ' ( cd victim && ( git branch -D extra || : ) && git config receive.denyNonFastforwards true ) && victim_orig=$(cd victim && git rev-parse --verify master) && test_must_fail git send-pack --force ./victim master^:master && victim_head=$(cd victim && git rev-parse --verify master) && test "$victim_orig" = "$victim_head" ' test_expect_success 'send-pack --all sends all branches' ' # make sure we have at least 2 branches with different # values, just to be thorough git branch other-branch HEAD^ && git init --bare all.git && git send-pack --all all.git && git for-each-ref refs/heads >expect && git -C all.git for-each-ref refs/heads >actual && test_cmp expect actual ' test_expect_success 'push --all excludes remote-tracking hierarchy' ' mkdir parent && ( cd parent && git init && : >file && git add file && git commit -m add ) && git clone parent child && ( cd child && git push --all ) && ( cd parent && test -z "$(git for-each-ref refs/remotes/origin)" ) ' test_expect_success 'receive-pack runs auto-gc in remote repo' ' rm -rf parent child && git init parent && ( # Setup a repo with 2 packs cd parent && echo "Some text" >file.txt && git add . && git commit -m "Initial commit" && git repack -adl && echo "Some more text" >>file.txt && git commit -a -m "Second commit" && git repack ) && cp -R parent child && ( # Set the child to auto-pack if more than one pack exists cd child && git config gc.autopacklimit 1 && git config gc.autodetach false && git branch test_auto_gc && # And create a file that follows the temporary object naming # convention for the auto-gc to remove : >.git/objects/tmp_test_object && test-chmtime =-1209601 .git/objects/tmp_test_object ) && ( cd parent && echo "Even more text" >>file.txt && git commit -a -m "Third commit" && git send-pack ../child HEAD:refs/heads/test_auto_gc ) && test ! -e child/.git/objects/tmp_test_object ' proc rewound_push_setup { rm -rf parent child && mkdir parent && shell { cd parent && git init && echo one >file && git add file && git commit -m one && git config receive.denyCurrentBranch warn && echo two >file && git commit -a -m two } && git clone parent child && shell { cd child && git reset --hard HEAD^ } } test_expect_success 'pushing explicit refspecs respects forcing' ' rewound_push_setup && parent_orig=$(cd parent && git rev-parse --verify master) && ( cd child && test_must_fail git send-pack ../parent \ refs/heads/master:refs/heads/master ) && parent_head=$(cd parent && git rev-parse --verify master) && test "$parent_orig" = "$parent_head" && ( cd child && git send-pack ../parent \ +refs/heads/master:refs/heads/master ) && parent_head=$(cd parent && git rev-parse --verify master) && child_head=$(cd child && git rev-parse --verify master) && test "$parent_head" = "$child_head" ' test_expect_success 'pushing wildcard refspecs respects forcing' ' rewound_push_setup && parent_orig=$(cd parent && git rev-parse --verify master) && ( cd child && test_must_fail git send-pack ../parent \ "refs/heads/*:refs/heads/*" ) && parent_head=$(cd parent && git rev-parse --verify master) && test "$parent_orig" = "$parent_head" && ( cd child && git send-pack ../parent \ "+refs/heads/*:refs/heads/*" ) && parent_head=$(cd parent && git rev-parse --verify master) && child_head=$(cd child && git rev-parse --verify master) && test "$parent_head" = "$child_head" ' test_expect_success 'deny pushing to delete current branch' ' rewound_push_setup && ( cd child && test_must_fail git send-pack ../parent :refs/heads/master 2>errs ) ' test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"See why rewinding head breaks send-pack\n"> <"\n">)} spids: [13] ) ] spids: [13] ) (C {(.)} {(./test-lib.sh)}) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:cnt) op:Equal rhs:{(64)} spids:[24])] spids: [24] ) (C {(test_expect_success)} {(setup)} { (SQ <"\n"> <"\ttest_tick &&\n"> <"\tmkdir mozart mozart/is &&\n"> <"\techo \"Commit #0\" >mozart/is/pink &&\n"> <"\tgit update-index --add mozart/is/pink &&\n"> <"\ttree=$(git write-tree) &&\n"> <"\tcommit=$(echo \"Commit #0\" | git commit-tree $tree) &&\n"> <"\tzero=$commit &&\n"> <"\tparent=$zero &&\n"> <"\ti=0 &&\n"> <"\twhile test $i -le $cnt\n"> <"\tdo\n"> <"\t i=$(($i+1)) &&\n"> <"\t test_tick &&\n"> <"\t echo \"Commit #$i\" >mozart/is/pink &&\n"> <"\t git update-index --add mozart/is/pink &&\n"> <"\t tree=$(git write-tree) &&\n"> <"\t commit=$(echo \"Commit #$i\" | git commit-tree $tree -p $parent) &&\n"> <"\t git update-ref refs/tags/commit$i $commit &&\n"> <"\t parent=$commit || return 1\n"> <"\tdone &&\n"> <"\tgit update-ref HEAD \"$commit\" &&\n"> <"\tgit clone ./. victim &&\n"> <"\t( cd victim && git config receive.denyCurrentBranch warn && git log ) &&\n"> <"\tgit update-ref HEAD \"$zero\" &&\n"> <"\tparent=$zero &&\n"> <"\ti=0 &&\n"> <"\twhile test $i -le $cnt\n"> <"\tdo\n"> <"\t i=$(($i+1)) &&\n"> <"\t test_tick &&\n"> <"\t echo \"Rebase #$i\" >mozart/is/pink &&\n"> <"\t git update-index --add mozart/is/pink &&\n"> <"\t tree=$(git write-tree) &&\n"> <"\t commit=$(echo \"Rebase #$i\" | git commit-tree $tree -p $parent) &&\n"> <"\t git update-ref refs/tags/rebase$i $commit &&\n"> <"\t parent=$commit || return 1\n"> <"\tdone &&\n"> <"\tgit update-ref HEAD \"$commit\" &&\n"> <"\techo Rebase &&\n"> <"\tgit log"> ) } ) (C {(test_expect_success)} {(SQ <"pack the source repository">)} {(SQ <"\n"> <"\tgit repack -a -d &&\n"> <"\tgit prune\n">)} ) (C {(test_expect_success)} {(SQ <"pack the destination repository">)} { (SQ <"\n"> <" (\n"> <"\tcd victim &&\n"> <"\tgit repack -a -d &&\n"> <"\tgit prune\n"> <" )\n"> ) } ) (C {(test_expect_success)} {(SQ <"refuse pushing rewound head without --force">)} { (SQ <"\n"> <"\tpushed_head=$(git rev-parse --verify master) &&\n"> <"\tvictim_orig=$(cd victim && git rev-parse --verify master) &&\n"> <"\ttest_must_fail git send-pack ./victim master &&\n"> <"\tvictim_head=$(cd victim && git rev-parse --verify master) &&\n"> <"\ttest \"$victim_head\" = \"$victim_orig\" &&\n"> <"\t# this should update\n"> <"\tgit send-pack --force ./victim master &&\n"> <"\tvictim_head=$(cd victim && git rev-parse --verify master) &&\n"> <"\ttest \"$victim_head\" = \"$pushed_head\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"push can be used to delete a ref">)} { (SQ <"\n"> <"\t( cd victim && git branch extra master ) &&\n"> <"\tgit send-pack ./victim :extra master &&\n"> <"\t( cd victim &&\n"> <"\t test_must_fail git rev-parse --verify extra )\n"> ) } ) (C {(test_expect_success)} {(SQ <"refuse deleting push with denyDeletes">)} { (SQ <"\n"> <"\t(\n"> <"\t cd victim &&\n"> <"\t ( git branch -D extra || : ) &&\n"> <"\t git config receive.denyDeletes true &&\n"> <"\t git branch extra master\n"> <"\t) &&\n"> <"\ttest_must_fail git send-pack ./victim :extra master\n"> ) } ) (C {(test_expect_success)} {(SQ <"cannot override denyDeletes with git -c send-pack">)} { (SQ <"\n"> <"\t(\n"> <"\t\tcd victim &&\n"> <"\t\ttest_might_fail git branch -D extra &&\n"> <"\t\tgit config receive.denyDeletes true &&\n"> <"\t\tgit branch extra master\n"> <"\t) &&\n"> <"\ttest_must_fail git -c receive.denyDeletes=false \\\n"> <"\t\t\t\t\tsend-pack ./victim :extra master\n"> ) } ) (C {(test_expect_success)} {(SQ <"override denyDeletes with git -c receive-pack">)} { (SQ <"\n"> <"\t(\n"> <"\t\tcd victim &&\n"> <"\t\ttest_might_fail git branch -D extra &&\n"> <"\t\tgit config receive.denyDeletes true &&\n"> <"\t\tgit branch extra master\n"> <"\t) &&\n"> <"\tgit send-pack \\\n"> <"\t\t--receive-pack=\"git -c receive.denyDeletes=false receive-pack\" \\\n"> <"\t\t./victim :extra master\n"> ) } ) (C {(test_expect_success)} {(SQ <"denyNonFastforwards trumps --force">)} { (SQ <"\n"> <"\t(\n"> <"\t cd victim &&\n"> <"\t ( git branch -D extra || : ) &&\n"> <"\t git config receive.denyNonFastforwards true\n"> <"\t) &&\n"> <"\tvictim_orig=$(cd victim && git rev-parse --verify master) &&\n"> <"\ttest_must_fail git send-pack --force ./victim master^:master &&\n"> <"\tvictim_head=$(cd victim && git rev-parse --verify master) &&\n"> <"\ttest \"$victim_orig\" = \"$victim_head\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"send-pack --all sends all branches">)} { (SQ <"\n"> <"\t# make sure we have at least 2 branches with different\n"> <"\t# values, just to be thorough\n"> <"\tgit branch other-branch HEAD^ &&\n"> <"\n"> <"\tgit init --bare all.git &&\n"> <"\tgit send-pack --all all.git &&\n"> <"\tgit for-each-ref refs/heads >expect &&\n"> <"\tgit -C all.git for-each-ref refs/heads >actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"push --all excludes remote-tracking hierarchy">)} { (SQ <"\n"> <"\tmkdir parent &&\n"> <"\t(\n"> <"\t cd parent &&\n"> <"\t git init && : >file && git add file && git commit -m add\n"> <"\t) &&\n"> <"\tgit clone parent child &&\n"> <"\t(\n"> <"\t cd child && git push --all\n"> <"\t) &&\n"> <"\t(\n"> <"\t cd parent &&\n"> <"\t test -z \"$(git for-each-ref refs/remotes/origin)\"\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"receive-pack runs auto-gc in remote repo">)} { (SQ <"\n"> <"\trm -rf parent child &&\n"> <"\tgit init parent &&\n"> <"\t(\n"> <"\t # Setup a repo with 2 packs\n"> <"\t cd parent &&\n"> <"\t echo \"Some text\" >file.txt &&\n"> <"\t git add . &&\n"> <"\t git commit -m \"Initial commit\" &&\n"> <"\t git repack -adl &&\n"> <"\t echo \"Some more text\" >>file.txt &&\n"> <"\t git commit -a -m \"Second commit\" &&\n"> <"\t git repack\n"> <"\t) &&\n"> <"\tcp -R parent child &&\n"> <"\t(\n"> <"\t # Set the child to auto-pack if more than one pack exists\n"> <"\t cd child &&\n"> <"\t git config gc.autopacklimit 1 &&\n"> <"\t git config gc.autodetach false &&\n"> <"\t git branch test_auto_gc &&\n"> <"\t # And create a file that follows the temporary object naming\n"> <"\t # convention for the auto-gc to remove\n"> <"\t : >.git/objects/tmp_test_object &&\n"> <"\t test-chmtime =-1209601 .git/objects/tmp_test_object\n"> <"\t) &&\n"> <"\t(\n"> <"\t cd parent &&\n"> <"\t echo \"Even more text\" >>file.txt &&\n"> <"\t git commit -a -m \"Third commit\" &&\n"> <"\t git send-pack ../child HEAD:refs/heads/test_auto_gc\n"> <"\t) &&\n"> <"\ttest ! -e child/.git/objects/tmp_test_object\n"> ) } ) (FuncDef name: rewound_push_setup body: (BraceGroup children: [ (AndOr children: [ (C {(rm)} {(-rf)} {(parent)} {(child)}) (AndOr children: [ (C {(mkdir)} {(parent)}) (AndOr children: [ (Subshell child: (AndOr children: [ (C {(cd)} {(parent)}) (AndOr children: [ (C {(git)} {(init)}) (AndOr children: [ (SimpleCommand words: [{(echo)} {(one)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(file)} spids: [350] ) ] ) (AndOr children: [ (C {(git)} {(add)} {(file)}) (AndOr children: [ (C {(git)} {(commit)} {(-m)} {(one)}) (AndOr children: [ (C {(git)} {(config)} {(receive.denyCurrentBranch)} {(warn)} ) (AndOr children: [ (SimpleCommand words: [{(echo)} {(two)}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(file)} spids: [389] ) ] ) (C {(git)} {(commit)} {(-a)} {(-m)} {(two)}) ] 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: [329 405] ) (AndOr children: [ (C {(git)} {(clone)} {(parent)} {(child)}) (Subshell child: (AndOr children: [ (C {(cd)} {(child)}) (C {(git)} {(reset)} {(--hard)} {(HEAD) (Lit_Other "^")}) ] op_id: Op_DAmp ) spids: [421 440] ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [308] ) spids: [304 307] ) (C {(test_expect_success)} {(SQ <"pushing explicit refspecs respects forcing">)} { (SQ <"\n"> <"\trewound_push_setup &&\n"> <"\tparent_orig=$(cd parent && git rev-parse --verify master) &&\n"> <"\t(\n"> <"\t cd child &&\n"> <"\t test_must_fail git send-pack ../parent \\\n"> <"\t\trefs/heads/master:refs/heads/master\n"> <"\t) &&\n"> <"\tparent_head=$(cd parent && git rev-parse --verify master) &&\n"> <"\ttest \"$parent_orig\" = \"$parent_head\" &&\n"> <"\t(\n"> <"\t cd child &&\n"> <"\t git send-pack ../parent \\\n"> <"\t +refs/heads/master:refs/heads/master\n"> <"\t) &&\n"> <"\tparent_head=$(cd parent && git rev-parse --verify master) &&\n"> <"\tchild_head=$(cd child && git rev-parse --verify master) &&\n"> <"\ttest \"$parent_head\" = \"$child_head\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"pushing wildcard refspecs respects forcing">)} { (SQ <"\n"> <"\trewound_push_setup &&\n"> <"\tparent_orig=$(cd parent && git rev-parse --verify master) &&\n"> <"\t(\n"> <"\t cd child &&\n"> <"\t test_must_fail git send-pack ../parent \\\n"> <"\t \"refs/heads/*:refs/heads/*\"\n"> <"\t) &&\n"> <"\tparent_head=$(cd parent && git rev-parse --verify master) &&\n"> <"\ttest \"$parent_orig\" = \"$parent_head\" &&\n"> <"\t(\n"> <"\t cd child &&\n"> <"\t git send-pack ../parent \\\n"> <"\t \"+refs/heads/*:refs/heads/*\"\n"> <"\t) &&\n"> <"\tparent_head=$(cd parent && git rev-parse --verify master) &&\n"> <"\tchild_head=$(cd child && git rev-parse --verify master) &&\n"> <"\ttest \"$parent_head\" = \"$child_head\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"deny pushing to delete current branch">)} { (SQ <"\n"> <"\trewound_push_setup &&\n"> <"\t(\n"> <"\t cd child &&\n"> <"\t test_must_fail git send-pack ../parent :refs/heads/master 2>errs\n"> <"\t)\n"> ) } ) (C {(test_done)}) ] )