You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
7.9 KiB
299 lines
7.9 KiB
#!/bin/sh |
|
# |
|
# Copyright (c) 2005 Junio C Hamano |
|
# |
|
|
|
test_description='See why rewinding head breaks send-pack |
|
|
|
' |
|
. ./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 '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 && |
|
test_might_fail 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 && |
|
test_might_fail 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-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 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 |
|
) |
|
' |
|
|
|
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 '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/master |
|
$local refs/remotes/origin/HEAD |
|
$local refs/remotes/origin/master |
|
$shared .have |
|
EOF |
|
|
|
GIT_TRACE_PACKET=$(pwd)/trace \ |
|
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
|
|
|