| #!/bin/sh | |
| # | |
| # Copyright (c) 2005 Junio C Hamano | |
| # | |
| test_description='See why rewinding head breaks send-pack | |
| ' | |
| GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main | |
| export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME | |
| . ./test-lib.sh | |
| 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 'send-pack does not crash with -h' ' | |
| git send-pack -h >usage && | |
| test_grep "[Uu]sage: git send-pack " usage && | |
| nongit git send-pack -h >usage && | |
| test_grep "[Uu]sage: git send-pack " usage | |
| ' | |
| 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 main) && | |
| victim_orig=$(cd victim && git rev-parse --verify main) && | |
| test_must_fail git send-pack ./victim main && | |
| victim_head=$(cd victim && git rev-parse --verify main) && | |
| test "$victim_head" = "$victim_orig" && | |
| # this should update | |
| git send-pack --force ./victim main && | |
| victim_head=$(cd victim && git rev-parse --verify main) && | |
| test "$victim_head" = "$pushed_head" | |
| ' | |
| test_expect_success 'push can be used to delete a ref' ' | |
| ( cd victim && git branch extra main ) && | |
| git send-pack ./victim :extra main && | |
| ( cd victim && | |
| test_must_fail git rev-parse --verify extra ) | |
| ' | |
| test_expect_success 'refuse deleting push with denyDeletes' ' | |
| ( | |
| cd victim && | |
| test_might_fail git branch -D extra && | |
| git config receive.denyDeletes true && | |
| git branch extra main | |
| ) && | |
| test_must_fail git send-pack ./victim :extra main | |
| ' | |
| 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 main | |
| ) && | |
| test_must_fail git -c receive.denyDeletes=false \ | |
| send-pack ./victim :extra main | |
| ' | |
| 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 main | |
| ) && | |
| git send-pack \ | |
| --receive-pack="git -c receive.denyDeletes=false receive-pack" \ | |
| ./victim :extra main | |
| ' | |
| test_expect_success 'denyNonFastforwards trumps --force' ' | |
| ( | |
| cd victim && | |
| test_might_fail git branch -D extra && | |
| git config receive.denyNonFastforwards true | |
| ) && | |
| victim_orig=$(cd victim && git rev-parse --verify main) && | |
| test_must_fail git send-pack --force ./victim main^:main && | |
| victim_head=$(cd victim && git rev-parse --verify main) && | |
| 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 config maintenance.strategy gc && | |
| 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-tool 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 | |
| ' | |
| rewound_push_setup() { | |
| rm -rf parent child && | |
| mkdir parent && | |
| ( | |
| 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 && | |
| ( | |
| 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 main) && | |
| ( | |
| cd child && | |
| test_must_fail git send-pack ../parent \ | |
| refs/heads/main:refs/heads/main | |
| ) && | |
| parent_head=$(cd parent && git rev-parse --verify main) && | |
| test "$parent_orig" = "$parent_head" && | |
| ( | |
| cd child && | |
| git send-pack ../parent \ | |
| +refs/heads/main:refs/heads/main | |
| ) && | |
| parent_head=$(cd parent && git rev-parse --verify main) && | |
| child_head=$(cd child && git rev-parse --verify main) && | |
| test "$parent_head" = "$child_head" | |
| ' | |
| test_expect_success 'pushing wildcard refspecs respects forcing' ' | |
| rewound_push_setup && | |
| parent_orig=$(cd parent && git rev-parse --verify main) && | |
| ( | |
| cd child && | |
| test_must_fail git send-pack ../parent \ | |
| "refs/heads/*:refs/heads/*" | |
| ) && | |
| parent_head=$(cd parent && git rev-parse --verify main) && | |
| test "$parent_orig" = "$parent_head" && | |
| ( | |
| cd child && | |
| git send-pack ../parent \ | |
| "+refs/heads/*:refs/heads/*" | |
| ) && | |
| parent_head=$(cd parent && git rev-parse --verify main) && | |
| child_head=$(cd child && git rev-parse --verify main) && | |
| 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/main 2>errs | |
| ) | |
| ' | |
| extract_ref_advertisement () { | |
| perl -lne ' | |
| # \\ is there to skip capabilities after \0 | |
| /push< ([^\\]+)/ or next; | |
| exit 0 if $1 eq "0000"; | |
| print $1; | |
| ' | |
| } | |
| test_expect_success PERL_TEST_HELPERS 'receive-pack de-dupes .have lines' ' | |
| git init shared && | |
| git -C shared commit --allow-empty -m both && | |
| git clone -s shared fork && | |
| ( | |
| cd shared && | |
| git checkout -b only-shared && | |
| git commit --allow-empty -m only-shared && | |
| git update-ref refs/heads/foo HEAD | |
| ) && | |
| # Notable things in this expectation: | |
| # - local refs are not de-duped | |
| # - .have does not duplicate locals | |
| # - .have does not duplicate itself | |
| local=$(git -C fork rev-parse HEAD) && | |
| shared=$(git -C shared rev-parse only-shared) && | |
| cat >expect <<-EOF && | |
| $local refs/heads/main | |
| $local refs/remotes/origin/HEAD | |
| $local refs/remotes/origin/main | |
| $shared .have | |
| EOF | |
| GIT_TRACE_PACKET=$(pwd)/trace GIT_TEST_PROTOCOL_VERSION=0 \ | |
| git push \ | |
| --receive-pack="unset GIT_TRACE_PACKET; git-receive-pack" \ | |
| fork HEAD:foo && | |
| extract_ref_advertisement <trace >refs && | |
| test_cmp expect refs | |
| ' | |
| test_done |