1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
|
#!/bin/sh
test_description='migration of ref storage backends'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_migration () {
git -C "$1" for-each-ref --include-root-refs \
--format='%(refname) %(objectname) %(symref)' >expect &&
git -C "$1" refs migrate --ref-format="$2" &&
git -C "$1" for-each-ref --include-root-refs \
--format='%(refname) %(objectname) %(symref)' >actual &&
test_cmp expect actual &&
git -C "$1" rev-parse --show-ref-format >actual &&
echo "$2" >expect &&
test_cmp expect actual
}
test_expect_success 'setup' '
rm -rf .git &&
# The migration does not yet support reflogs.
git config --global core.logAllRefUpdates false
'
test_expect_success "superfluous arguments" '
test_when_finished "rm -rf repo" &&
git init repo &&
test_must_fail git -C repo refs migrate foo 2>err &&
cat >expect <<-EOF &&
usage: too many arguments
EOF
test_cmp expect err
'
test_expect_success "missing ref storage format" '
test_when_finished "rm -rf repo" &&
git init repo &&
test_must_fail git -C repo refs migrate 2>err &&
cat >expect <<-EOF &&
usage: missing --ref-format=<format>
EOF
test_cmp expect err
'
test_expect_success "unknown ref storage format" '
test_when_finished "rm -rf repo" &&
git init repo &&
test_must_fail git -C repo refs migrate \
--ref-format=unknown 2>err &&
cat >expect <<-EOF &&
error: unknown ref storage format ${SQ}unknown${SQ}
EOF
test_cmp expect err
'
ref_formats="files reftable"
for from_format in $ref_formats
do
for to_format in $ref_formats
do
if test "$from_format" = "$to_format"
then
continue
fi
test_expect_success "$from_format: migration to same format fails" '
test_when_finished "rm -rf repo" &&
git init --ref-format=$from_format repo &&
test_must_fail git -C repo refs migrate \
--ref-format=$from_format 2>err &&
cat >expect <<-EOF &&
error: repository already uses ${SQ}$from_format${SQ} format
EOF
test_cmp expect err
'
test_expect_success "$from_format -> $to_format: migration with reflog fails" '
test_when_finished "rm -rf repo" &&
git init --ref-format=$from_format repo &&
test_config -C repo core.logAllRefUpdates true &&
test_commit -C repo logged &&
test_must_fail git -C repo refs migrate \
--ref-format=$to_format 2>err &&
cat >expect <<-EOF &&
error: migrating reflogs is not supported yet
EOF
test_cmp expect err
'
test_expect_success "$from_format -> $to_format: migration with worktree fails" '
test_when_finished "rm -rf repo" &&
git init --ref-format=$from_format repo &&
git -C repo worktree add wt &&
test_must_fail git -C repo refs migrate \
--ref-format=$to_format 2>err &&
cat >expect <<-EOF &&
error: migrating repositories with worktrees is not supported yet
EOF
test_cmp expect err
'
test_expect_success "$from_format -> $to_format: unborn HEAD" '
test_when_finished "rm -rf repo" &&
git init --ref-format=$from_format repo &&
test_migration repo "$to_format"
'
test_expect_success "$from_format -> $to_format: single ref" '
test_when_finished "rm -rf repo" &&
git init --ref-format=$from_format repo &&
test_commit -C repo initial &&
test_migration repo "$to_format"
'
test_expect_success "$from_format -> $to_format: bare repository" '
test_when_finished "rm -rf repo repo.git" &&
git init --ref-format=$from_format repo &&
test_commit -C repo initial &&
git clone --ref-format=$from_format --mirror repo repo.git &&
test_migration repo.git "$to_format"
'
test_expect_success "$from_format -> $to_format: dangling symref" '
test_when_finished "rm -rf repo" &&
git init --ref-format=$from_format repo &&
test_commit -C repo initial &&
git -C repo symbolic-ref BROKEN_HEAD refs/heads/nonexistent &&
test_migration repo "$to_format" &&
echo refs/heads/nonexistent >expect &&
git -C repo symbolic-ref BROKEN_HEAD >actual &&
test_cmp expect actual
'
test_expect_success "$from_format -> $to_format: broken ref" '
test_when_finished "rm -rf repo" &&
git init --ref-format=$from_format repo &&
test_commit -C repo initial &&
test-tool -C repo ref-store main update-ref "" refs/heads/broken \
"$(test_oid 001)" "$ZERO_OID" REF_SKIP_CREATE_REFLOG,REF_SKIP_OID_VERIFICATION &&
test_migration repo "$to_format" &&
test_oid 001 >expect &&
git -C repo rev-parse refs/heads/broken >actual &&
test_cmp expect actual
'
test_expect_success "$from_format -> $to_format: pseudo-refs" '
test_when_finished "rm -rf repo" &&
git init --ref-format=$from_format repo &&
test_commit -C repo initial &&
git -C repo update-ref FOO_HEAD HEAD &&
test_migration repo "$to_format"
'
test_expect_success "$from_format -> $to_format: special refs are left alone" '
test_when_finished "rm -rf repo" &&
git init --ref-format=$from_format repo &&
test_commit -C repo initial &&
git -C repo rev-parse HEAD >repo/.git/MERGE_HEAD &&
git -C repo rev-parse MERGE_HEAD &&
test_migration repo "$to_format" &&
test_path_is_file repo/.git/MERGE_HEAD
'
test_expect_success "$from_format -> $to_format: a bunch of refs" '
test_when_finished "rm -rf repo" &&
git init --ref-format=$from_format repo &&
test_commit -C repo initial &&
cat >input <<-EOF &&
create FOO_HEAD HEAD
create refs/heads/branch-1 HEAD
create refs/heads/branch-2 HEAD
create refs/heads/branch-3 HEAD
create refs/heads/branch-4 HEAD
create refs/tags/tag-1 HEAD
create refs/tags/tag-2 HEAD
EOF
git -C repo update-ref --stdin <input &&
test_migration repo "$to_format"
'
test_expect_success "$from_format -> $to_format: dry-run migration does not modify repository" '
test_when_finished "rm -rf repo" &&
git init --ref-format=$from_format repo &&
test_commit -C repo initial &&
git -C repo refs migrate --dry-run \
--ref-format=$to_format >output &&
grep "Finished dry-run migration of refs" output &&
test_path_is_dir repo/.git/ref_migration.* &&
echo $from_format >expect &&
git -C repo rev-parse --show-ref-format >actual &&
test_cmp expect actual
'
done
done
test_expect_success 'migrating from files format deletes backend files' '
test_when_finished "rm -rf repo" &&
git init --ref-format=files repo &&
test_commit -C repo first &&
git -C repo pack-refs --all &&
test_commit -C repo second &&
git -C repo update-ref ORIG_HEAD HEAD &&
git -C repo rev-parse HEAD >repo/.git/FETCH_HEAD &&
test_path_is_file repo/.git/HEAD &&
test_path_is_file repo/.git/ORIG_HEAD &&
test_path_is_file repo/.git/refs/heads/main &&
test_path_is_file repo/.git/packed-refs &&
test_migration repo reftable &&
echo "ref: refs/heads/.invalid" >expect &&
test_cmp expect repo/.git/HEAD &&
echo "this repository uses the reftable format" >expect &&
test_cmp expect repo/.git/refs/heads &&
test_path_is_file repo/.git/FETCH_HEAD &&
test_path_is_missing repo/.git/ORIG_HEAD &&
test_path_is_missing repo/.git/refs/heads/main &&
test_path_is_missing repo/.git/logs &&
test_path_is_missing repo/.git/packed-refs
'
test_expect_success 'migrating from reftable format deletes backend files' '
test_when_finished "rm -rf repo" &&
git init --ref-format=reftable repo &&
test_commit -C repo first &&
test_path_is_dir repo/.git/reftable &&
test_migration repo files &&
test_path_is_missing repo/.git/reftable &&
echo "ref: refs/heads/main" >expect &&
test_cmp expect repo/.git/HEAD &&
test_path_is_file repo/.git/refs/heads/main
'
test_done
|