Git fork
at reftables-rust 328 lines 10 kB view raw
1#!/bin/sh 2 3test_description='migration of ref storage backends' 4 5GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main 6export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 7 8. ./test-lib.sh 9 10print_all_reflog_entries () { 11 repo=$1 && 12 test-tool -C "$repo" ref-store main for-each-reflog >reflogs && 13 while read reflog 14 do 15 echo "REFLOG: $reflog" && 16 test-tool -C "$repo" ref-store main for-each-reflog-ent "$reflog" || 17 return 1 18 done <reflogs 19} 20 21# Migrate the provided repository from one format to the other and 22# verify that the references and logs are migrated over correctly. 23# Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]] 24# <repo> is the relative path to the repo to be migrated. 25# <format> is the ref format to be migrated to. 26# <skip_reflog_verify> (default: false) whether to skip reflog verification. 27# <options...> are other options be passed directly to 'git refs migrate'. 28test_migration () { 29 repo=$1 && 30 format=$2 && 31 shift 2 && 32 skip_reflog_verify=false && 33 if test $# -ge 1 34 then 35 skip_reflog_verify=$1 36 shift 37 fi && 38 git -C "$repo" for-each-ref --include-root-refs \ 39 --format='%(refname) %(objectname) %(symref)' >expect && 40 if ! $skip_reflog_verify 41 then 42 print_all_reflog_entries "$repo" >expect_logs 43 fi && 44 45 git -C "$repo" refs migrate --ref-format="$format" "$@" && 46 47 git -C "$repo" for-each-ref --include-root-refs \ 48 --format='%(refname) %(objectname) %(symref)' >actual && 49 test_cmp expect actual && 50 if ! $skip_reflog_verify 51 then 52 print_all_reflog_entries "$repo" >actual_logs && 53 test_cmp expect_logs actual_logs 54 fi && 55 56 git -C "$repo" rev-parse --show-ref-format >actual && 57 echo "$format" >expect && 58 test_cmp expect actual 59} 60 61test_expect_success 'setup' ' 62 rm -rf .git 63' 64 65test_expect_success "superfluous arguments" ' 66 test_when_finished "rm -rf repo" && 67 git init repo && 68 test_must_fail git -C repo refs migrate foo 2>err && 69 cat >expect <<-EOF && 70 usage: too many arguments 71 EOF 72 test_cmp expect err 73' 74 75test_expect_success "missing ref storage format" ' 76 test_when_finished "rm -rf repo" && 77 git init repo && 78 test_must_fail git -C repo refs migrate 2>err && 79 cat >expect <<-EOF && 80 usage: missing --ref-format=<format> 81 EOF 82 test_cmp expect err 83' 84 85test_expect_success "unknown ref storage format" ' 86 test_when_finished "rm -rf repo" && 87 git init repo && 88 test_must_fail git -C repo refs migrate \ 89 --ref-format=unknown 2>err && 90 cat >expect <<-EOF && 91 error: unknown ref storage format ${SQ}unknown${SQ} 92 EOF 93 test_cmp expect err 94' 95 96ref_formats="files reftable" 97for from_format in $ref_formats 98do 99 for to_format in $ref_formats 100 do 101 if test "$from_format" = "$to_format" 102 then 103 continue 104 fi 105 106 test_expect_success "$from_format: migration to same format fails" ' 107 test_when_finished "rm -rf repo" && 108 git init --ref-format=$from_format repo && 109 test_must_fail git -C repo refs migrate \ 110 --ref-format=$from_format 2>err && 111 cat >expect <<-EOF && 112 error: repository already uses ${SQ}$from_format${SQ} format 113 EOF 114 test_cmp expect err 115 ' 116 117 test_expect_success "$from_format -> $to_format: migration with worktree fails" ' 118 test_when_finished "rm -rf repo" && 119 git init --ref-format=$from_format repo && 120 git -C repo worktree add wt && 121 test_must_fail git -C repo refs migrate \ 122 --ref-format=$to_format 2>err && 123 cat >expect <<-EOF && 124 error: migrating repositories with worktrees is not supported yet 125 EOF 126 test_cmp expect err 127 ' 128 129 test_expect_success "$from_format -> $to_format: unborn HEAD" ' 130 test_when_finished "rm -rf repo" && 131 git init --ref-format=$from_format repo && 132 test_migration repo "$to_format" 133 ' 134 135 test_expect_success "$from_format -> $to_format: single ref" ' 136 test_when_finished "rm -rf repo" && 137 git init --ref-format=$from_format repo && 138 test_commit -C repo initial && 139 test_migration repo "$to_format" 140 ' 141 142 test_expect_success "$from_format -> $to_format: bare repository" ' 143 test_when_finished "rm -rf repo repo.git" && 144 git init --ref-format=$from_format repo && 145 test_commit -C repo initial && 146 git clone --ref-format=$from_format --mirror repo repo.git && 147 test_migration repo.git "$to_format" 148 ' 149 150 test_expect_success "$from_format -> $to_format: dangling symref" ' 151 test_when_finished "rm -rf repo" && 152 git init --ref-format=$from_format repo && 153 test_commit -C repo initial && 154 git -C repo symbolic-ref BROKEN_HEAD refs/heads/nonexistent && 155 test_migration repo "$to_format" && 156 echo refs/heads/nonexistent >expect && 157 git -C repo symbolic-ref BROKEN_HEAD >actual && 158 test_cmp expect actual 159 ' 160 161 test_expect_success "$from_format -> $to_format: broken ref" ' 162 test_when_finished "rm -rf repo" && 163 git init --ref-format=$from_format repo && 164 test_commit -C repo initial && 165 test-tool -C repo ref-store main update-ref "" refs/heads/broken \ 166 "$(test_oid 001)" "$ZERO_OID" REF_SKIP_CREATE_REFLOG,REF_SKIP_OID_VERIFICATION && 167 test_migration repo "$to_format" true && 168 test_oid 001 >expect && 169 git -C repo rev-parse refs/heads/broken >actual && 170 test_cmp expect actual 171 ' 172 173 test_expect_success "$from_format -> $to_format: pseudo-refs" ' 174 test_when_finished "rm -rf repo" && 175 git init --ref-format=$from_format repo && 176 test_commit -C repo initial && 177 git -C repo update-ref FOO_HEAD HEAD && 178 test_migration repo "$to_format" 179 ' 180 181 test_expect_success "$from_format -> $to_format: special refs are left alone" ' 182 test_when_finished "rm -rf repo" && 183 git init --ref-format=$from_format repo && 184 test_commit -C repo initial && 185 git -C repo rev-parse HEAD >repo/.git/MERGE_HEAD && 186 git -C repo rev-parse MERGE_HEAD && 187 test_migration repo "$to_format" && 188 test_path_is_file repo/.git/MERGE_HEAD 189 ' 190 191 test_expect_success "$from_format -> $to_format: a bunch of refs" ' 192 test_when_finished "rm -rf repo" && 193 git init --ref-format=$from_format repo && 194 195 test_commit -C repo initial && 196 cat >input <<-EOF && 197 create FOO_HEAD HEAD 198 create refs/heads/branch-1 HEAD 199 create refs/heads/branch-2 HEAD 200 create refs/heads/branch-3 HEAD 201 create refs/heads/branch-4 HEAD 202 create refs/tags/tag-1 HEAD 203 create refs/tags/tag-2 HEAD 204 EOF 205 git -C repo update-ref --stdin <input && 206 test_migration repo "$to_format" 207 ' 208 209 test_expect_success "$from_format -> $to_format: dry-run migration does not modify repository" ' 210 test_when_finished "rm -rf repo" && 211 git init --ref-format=$from_format repo && 212 test_commit -C repo initial && 213 git -C repo refs migrate --dry-run \ 214 --ref-format=$to_format >output && 215 grep "Finished dry-run migration of refs" output && 216 test_path_is_dir repo/.git/ref_migration.* && 217 echo $from_format >expect && 218 git -C repo rev-parse --show-ref-format >actual && 219 test_cmp expect actual 220 ' 221 222 test_expect_success "$from_format -> $to_format: reflogs of symrefs with target deleted" ' 223 test_when_finished "rm -rf repo" && 224 git init --ref-format=$from_format repo && 225 test_commit -C repo initial && 226 git -C repo branch branch-1 HEAD && 227 git -C repo symbolic-ref refs/heads/symref refs/heads/branch-1 && 228 cat >input <<-EOF && 229 delete refs/heads/branch-1 230 EOF 231 git -C repo update-ref --stdin <input && 232 test_migration repo "$to_format" 233 ' 234 235 test_expect_success "$from_format -> $to_format: reflogs order is retained" ' 236 test_when_finished "rm -rf repo" && 237 git init --ref-format=$from_format repo && 238 test_commit --date "100005000 +0700" --no-tag -C repo initial && 239 test_commit --date "100003000 +0700" --no-tag -C repo second && 240 test_migration repo "$to_format" 241 ' 242 243 test_expect_success "$from_format -> $to_format: stash is retained" ' 244 test_when_finished "rm -rf repo" && 245 git init --ref-format=$from_format repo && 246 ( 247 cd repo && 248 test_commit initial A && 249 echo foo >A && 250 git stash push && 251 echo bar >A && 252 git stash push && 253 git stash list >expect.reflog && 254 test_migration . "$to_format" && 255 git stash list >actual.reflog && 256 test_cmp expect.reflog actual.reflog 257 ) 258 ' 259 260 test_expect_success "$from_format -> $to_format: skip reflog with --skip-reflog" ' 261 test_when_finished "rm -rf repo" && 262 git init --ref-format=$from_format repo && 263 test_commit -C repo initial && 264 # we see that the repository contains reflogs. 265 git -C repo reflog --all >reflogs && 266 test_line_count = 2 reflogs && 267 test_migration repo "$to_format" true --no-reflog && 268 # there should be no reflogs post migration. 269 git -C repo reflog --all >reflogs && 270 test_must_be_empty reflogs 271 ' 272 done 273done 274 275test_expect_success 'multiple reftable blocks with multiple entries' ' 276 test_when_finished "rm -rf repo" && 277 git init --ref-format=files repo && 278 test_commit -C repo first && 279 printf "create refs/heads/ref-%d HEAD\n" $(test_seq 5000) >stdin && 280 git -C repo update-ref --stdin <stdin && 281 test_commit -C repo second && 282 printf "update refs/heads/ref-%d HEAD\n" $(test_seq 3000) >stdin && 283 git -C repo update-ref --stdin <stdin && 284 test_migration repo reftable true 285' 286 287test_expect_success 'migrating from files format deletes backend files' ' 288 test_when_finished "rm -rf repo" && 289 git init --ref-format=files repo && 290 test_commit -C repo first && 291 git -C repo pack-refs --all && 292 test_commit -C repo second && 293 git -C repo update-ref ORIG_HEAD HEAD && 294 git -C repo rev-parse HEAD >repo/.git/FETCH_HEAD && 295 296 test_path_is_file repo/.git/HEAD && 297 test_path_is_file repo/.git/ORIG_HEAD && 298 test_path_is_file repo/.git/refs/heads/main && 299 test_path_is_file repo/.git/packed-refs && 300 301 test_migration repo reftable && 302 303 echo "ref: refs/heads/.invalid" >expect && 304 test_cmp expect repo/.git/HEAD && 305 echo "this repository uses the reftable format" >expect && 306 test_cmp expect repo/.git/refs/heads && 307 test_path_is_file repo/.git/FETCH_HEAD && 308 test_path_is_missing repo/.git/ORIG_HEAD && 309 test_path_is_missing repo/.git/refs/heads/main && 310 test_path_is_missing repo/.git/logs && 311 test_path_is_missing repo/.git/packed-refs 312' 313 314test_expect_success 'migrating from reftable format deletes backend files' ' 315 test_when_finished "rm -rf repo" && 316 git init --ref-format=reftable repo && 317 test_commit -C repo first && 318 319 test_path_is_dir repo/.git/reftable && 320 test_migration repo files && 321 322 test_path_is_missing repo/.git/reftable && 323 echo "ref: refs/heads/main" >expect && 324 test_cmp expect repo/.git/HEAD && 325 test_path_is_file repo/.git/packed-refs 326' 327 328test_done