1#!/bin/sh 2# 3# Copyright (c) 2005 Junio C Hamano 4# 5 6test_description='See why rewinding head breaks send-pack 7 8' 9GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 10export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 11 12. ./test-lib.sh 13 14cnt=64 15test_expect_success setup ' 16 test_tick && 17 mkdir mozart mozart/is && 18 echo "Commit #0" >mozart/is/pink && 19 git update-index --add mozart/is/pink && 20 tree=$(git write-tree) && 21 commit=$(echo "Commit #0" | git commit-tree $tree) && 22 zero=$commit && 23 parent=$zero && 24 i=0 && 25 while test $i -le $cnt 26 do 27 i=$(($i+1)) && 28 test_tick && 29 echo "Commit #$i" >mozart/is/pink && 30 git update-index --add mozart/is/pink && 31 tree=$(git write-tree) && 32 commit=$(echo "Commit #$i" | 33 git commit-tree $tree -p $parent) && 34 git update-ref refs/tags/commit$i $commit && 35 parent=$commit || return 1 36 done && 37 git update-ref HEAD "$commit" && 38 git clone ./. victim && 39 ( cd victim && git config receive.denyCurrentBranch warn && git log ) && 40 git update-ref HEAD "$zero" && 41 parent=$zero && 42 i=0 && 43 while test $i -le $cnt 44 do 45 i=$(($i+1)) && 46 test_tick && 47 echo "Rebase #$i" >mozart/is/pink && 48 git update-index --add mozart/is/pink && 49 tree=$(git write-tree) && 50 commit=$(echo "Rebase #$i" | git commit-tree $tree -p $parent) && 51 git update-ref refs/tags/rebase$i $commit && 52 parent=$commit || return 1 53 done && 54 git update-ref HEAD "$commit" && 55 echo Rebase && 56 git log' 57 58test_expect_success 'pack the source repository' ' 59 git repack -a -d && 60 git prune 61' 62 63test_expect_success 'pack the destination repository' ' 64 ( 65 cd victim && 66 git repack -a -d && 67 git prune 68 ) 69' 70 71test_expect_success 'refuse pushing rewound head without --force' ' 72 pushed_head=$(git rev-parse --verify main) && 73 victim_orig=$(cd victim && git rev-parse --verify main) && 74 test_must_fail git send-pack ./victim main && 75 victim_head=$(cd victim && git rev-parse --verify main) && 76 test "$victim_head" = "$victim_orig" && 77 # this should update 78 git send-pack --force ./victim main && 79 victim_head=$(cd victim && git rev-parse --verify main) && 80 test "$victim_head" = "$pushed_head" 81' 82 83test_expect_success 'push can be used to delete a ref' ' 84 ( cd victim && git branch extra main ) && 85 git send-pack ./victim :extra main && 86 ( cd victim && 87 test_must_fail git rev-parse --verify extra ) 88' 89 90test_expect_success 'refuse deleting push with denyDeletes' ' 91 ( 92 cd victim && 93 test_might_fail git branch -D extra && 94 git config receive.denyDeletes true && 95 git branch extra main 96 ) && 97 test_must_fail git send-pack ./victim :extra main 98' 99 100test_expect_success 'cannot override denyDeletes with git -c send-pack' ' 101 ( 102 cd victim && 103 test_might_fail git branch -D extra && 104 git config receive.denyDeletes true && 105 git branch extra main 106 ) && 107 test_must_fail git -c receive.denyDeletes=false \ 108 send-pack ./victim :extra main 109' 110 111test_expect_success 'override denyDeletes with git -c receive-pack' ' 112 ( 113 cd victim && 114 test_might_fail git branch -D extra && 115 git config receive.denyDeletes true && 116 git branch extra main 117 ) && 118 git send-pack \ 119 --receive-pack="git -c receive.denyDeletes=false receive-pack" \ 120 ./victim :extra main 121' 122 123test_expect_success 'denyNonFastforwards trumps --force' ' 124 ( 125 cd victim && 126 test_might_fail git branch -D extra && 127 git config receive.denyNonFastforwards true 128 ) && 129 victim_orig=$(cd victim && git rev-parse --verify main) && 130 test_must_fail git send-pack --force ./victim main^:main && 131 victim_head=$(cd victim && git rev-parse --verify main) && 132 test "$victim_orig" = "$victim_head" 133' 134 135test_expect_success 'send-pack --all sends all branches' ' 136 # make sure we have at least 2 branches with different 137 # values, just to be thorough 138 git branch other-branch HEAD^ && 139 140 git init --bare all.git && 141 git send-pack --all all.git && 142 git for-each-ref refs/heads >expect && 143 git -C all.git for-each-ref refs/heads >actual && 144 test_cmp expect actual 145' 146 147test_expect_success 'push --all excludes remote-tracking hierarchy' ' 148 mkdir parent && 149 ( 150 cd parent && 151 git init && : >file && git add file && git commit -m add 152 ) && 153 git clone parent child && 154 ( 155 cd child && git push --all 156 ) && 157 ( 158 cd parent && 159 test -z "$(git for-each-ref refs/remotes/origin)" 160 ) 161' 162 163test_expect_success 'receive-pack runs auto-gc in remote repo' ' 164 rm -rf parent child && 165 git init parent && 166 ( 167 # Setup a repo with 2 packs 168 cd parent && 169 echo "Some text" >file.txt && 170 git add . && 171 git commit -m "Initial commit" && 172 git repack -adl && 173 echo "Some more text" >>file.txt && 174 git commit -a -m "Second commit" && 175 git repack 176 ) && 177 cp -R parent child && 178 ( 179 # Set the child to auto-pack if more than one pack exists 180 cd child && 181 git config gc.autopacklimit 1 && 182 git config gc.autodetach false && 183 git branch test_auto_gc && 184 # And create a file that follows the temporary object naming 185 # convention for the auto-gc to remove 186 : >.git/objects/tmp_test_object && 187 test-tool chmtime =-1209601 .git/objects/tmp_test_object 188 ) && 189 ( 190 cd parent && 191 echo "Even more text" >>file.txt && 192 git commit -a -m "Third commit" && 193 git send-pack ../child HEAD:refs/heads/test_auto_gc 194 ) && 195 test ! -e child/.git/objects/tmp_test_object 196' 197 198rewound_push_setup() { 199 rm -rf parent child && 200 mkdir parent && 201 ( 202 cd parent && 203 git init && 204 echo one >file && git add file && git commit -m one && 205 git config receive.denyCurrentBranch warn && 206 echo two >file && git commit -a -m two 207 ) && 208 git clone parent child && 209 ( 210 cd child && git reset --hard HEAD^ 211 ) 212} 213 214test_expect_success 'pushing explicit refspecs respects forcing' ' 215 rewound_push_setup && 216 parent_orig=$(cd parent && git rev-parse --verify main) && 217 ( 218 cd child && 219 test_must_fail git send-pack ../parent \ 220 refs/heads/main:refs/heads/main 221 ) && 222 parent_head=$(cd parent && git rev-parse --verify main) && 223 test "$parent_orig" = "$parent_head" && 224 ( 225 cd child && 226 git send-pack ../parent \ 227 +refs/heads/main:refs/heads/main 228 ) && 229 parent_head=$(cd parent && git rev-parse --verify main) && 230 child_head=$(cd child && git rev-parse --verify main) && 231 test "$parent_head" = "$child_head" 232' 233 234test_expect_success 'pushing wildcard refspecs respects forcing' ' 235 rewound_push_setup && 236 parent_orig=$(cd parent && git rev-parse --verify main) && 237 ( 238 cd child && 239 test_must_fail git send-pack ../parent \ 240 "refs/heads/*:refs/heads/*" 241 ) && 242 parent_head=$(cd parent && git rev-parse --verify main) && 243 test "$parent_orig" = "$parent_head" && 244 ( 245 cd child && 246 git send-pack ../parent \ 247 "+refs/heads/*:refs/heads/*" 248 ) && 249 parent_head=$(cd parent && git rev-parse --verify main) && 250 child_head=$(cd child && git rev-parse --verify main) && 251 test "$parent_head" = "$child_head" 252' 253 254test_expect_success 'deny pushing to delete current branch' ' 255 rewound_push_setup && 256 ( 257 cd child && 258 test_must_fail git send-pack ../parent :refs/heads/main 2>errs 259 ) 260' 261 262extract_ref_advertisement () { 263 perl -lne ' 264 # \\ is there to skip capabilities after \0 265 /push< ([^\\]+)/ or next; 266 exit 0 if $1 eq "0000"; 267 print $1; 268 ' 269} 270 271test_expect_success 'receive-pack de-dupes .have lines' ' 272 git init shared && 273 git -C shared commit --allow-empty -m both && 274 git clone -s shared fork && 275 ( 276 cd shared && 277 git checkout -b only-shared && 278 git commit --allow-empty -m only-shared && 279 git update-ref refs/heads/foo HEAD 280 ) && 281 282 # Notable things in this expectation: 283 # - local refs are not de-duped 284 # - .have does not duplicate locals 285 # - .have does not duplicate itself 286 local=$(git -C fork rev-parse HEAD) && 287 shared=$(git -C shared rev-parse only-shared) && 288 cat >expect <<-EOF && 289 $local refs/heads/main 290 $local refs/remotes/origin/HEAD 291 $local refs/remotes/origin/main 292 $shared .have 293 EOF 294 295 GIT_TRACE_PACKET=$(pwd)/trace GIT_TEST_PROTOCOL_VERSION=0 \ 296 git push \ 297 --receive-pack="unset GIT_TRACE_PACKET; git-receive-pack" \ 298 fork HEAD:foo && 299 extract_ref_advertisement <trace >refs && 300 test_cmp expect refs 301' 302 303test_done 304