| 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='git partial clone' |
| 4 | |
| 5 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main |
| 6 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
| 7 | |
| 8 | . ./test-lib.sh |
| 9 | |
| 10 | # create a normal "src" repo where we can later create new commits. |
| 11 | # expect_1.oids will contain a list of the OIDs of all blobs. |
| 12 | test_expect_success 'setup normal src repo' ' |
| 13 | echo "{print \$1}" >print_1.awk && |
| 14 | echo "{print \$2}" >print_2.awk && |
| 15 | |
| 16 | git init src && |
| 17 | for n in 1 2 3 4 |
| 18 | do |
| 19 | echo "This is file: $n" > src/file.$n.txt && |
| 20 | git -C src add file.$n.txt && |
| 21 | git -C src commit -m "file $n" && |
| 22 | git -C src ls-files -s file.$n.txt >>temp || return 1 |
| 23 | done && |
| 24 | awk -f print_2.awk <temp | sort >expect_1.oids && |
| 25 | test_line_count = 4 expect_1.oids |
| 26 | ' |
| 27 | |
| 28 | # bare clone "src" giving "srv.bare" for use as our server. |
| 29 | test_expect_success 'setup bare clone for server' ' |
| 30 | git clone --bare "file://$(pwd)/src" srv.bare && |
| 31 | git -C srv.bare config --local uploadpack.allowfilter 1 && |
| 32 | git -C srv.bare config --local uploadpack.allowanysha1inwant 1 |
| 33 | ' |
| 34 | |
| 35 | # do basic partial clone from "srv.bare" |
| 36 | # confirm we are missing all of the known blobs. |
| 37 | # confirm partial clone was registered in the local config. |
| 38 | test_expect_success 'do partial clone 1' ' |
| 39 | git clone --no-checkout --filter=blob:none "file://$(pwd)/srv.bare" pc1 && |
| 40 | |
| 41 | git -C pc1 rev-list --quiet --objects --missing=print HEAD >revs && |
| 42 | awk -f print_1.awk revs | |
| 43 | sed "s/?//" | |
| 44 | sort >observed.oids && |
| 45 | |
| 46 | test_cmp expect_1.oids observed.oids && |
| 47 | test "$(git -C pc1 config --local core.repositoryformatversion)" = "1" && |
| 48 | test "$(git -C pc1 config --local remote.origin.promisor)" = "true" && |
| 49 | test "$(git -C pc1 config --local remote.origin.partialclonefilter)" = "blob:none" |
| 50 | ' |
| 51 | |
| 52 | test_expect_success 'rev-list --missing=allow-promisor on partial clone' ' |
| 53 | git -C pc1 rev-list --objects --missing=allow-promisor HEAD >actual && |
| 54 | git -C pc1 rev-list --objects --missing=print HEAD >expect.raw && |
| 55 | grep -v "^?" expect.raw >expect && |
| 56 | test_cmp expect actual |
| 57 | ' |
| 58 | |
| 59 | test_expect_success 'verify that .promisor file contains refs fetched' ' |
| 60 | ls pc1/.git/objects/pack/pack-*.promisor >promisorlist && |
| 61 | test_line_count = 1 promisorlist && |
| 62 | git -C srv.bare rev-parse --verify HEAD >headhash && |
| 63 | test_grep "$(cat headhash) HEAD" $(cat promisorlist) && |
| 64 | test_grep "$(cat headhash) refs/heads/main" $(cat promisorlist) |
| 65 | ' |
| 66 | |
| 67 | # checkout main to force dynamic object fetch of blobs at HEAD. |
| 68 | test_expect_success 'verify checkout with dynamic object fetch' ' |
| 69 | git -C pc1 rev-list --quiet --objects --missing=print HEAD >observed && |
| 70 | test_line_count = 4 observed && |
| 71 | git -C pc1 checkout main && |
| 72 | git -C pc1 rev-list --quiet --objects --missing=print HEAD >observed && |
| 73 | test_line_count = 0 observed |
| 74 | ' |
| 75 | |
| 76 | # create new commits in "src" repo to establish a blame history on file.1.txt |
| 77 | # and push to "srv.bare". |
| 78 | test_expect_success 'push new commits to server' ' |
| 79 | git -C src remote add srv "file://$(pwd)/srv.bare" && |
| 80 | for x in a b c d e |
| 81 | do |
| 82 | echo "Mod file.1.txt $x" >>src/file.1.txt && |
| 83 | git -C src add file.1.txt && |
| 84 | git -C src commit -m "mod $x" || return 1 |
| 85 | done && |
| 86 | git -C src blame main -- file.1.txt >expect.blame && |
| 87 | git -C src push -u srv main |
| 88 | ' |
| 89 | |
| 90 | # (partial) fetch in the partial clone repo from the promisor remote. |
| 91 | # verify that fetch inherited the filter-spec from the config and DOES NOT |
| 92 | # have the new blobs. |
| 93 | test_expect_success 'partial fetch inherits filter settings' ' |
| 94 | git -C pc1 fetch origin && |
| 95 | git -C pc1 rev-list --quiet --objects --missing=print \ |
| 96 | main..origin/main >observed && |
| 97 | test_line_count = 5 observed |
| 98 | ' |
| 99 | |
| 100 | test_expect_success 'partial fetch does not spawn rev-list connectivity check' ' |
| 101 | test_when_finished "rm -rf connectivity-remote connectivity-client" && |
| 102 | git init connectivity-remote && |
| 103 | test_commit -C connectivity-remote one && |
| 104 | git -C connectivity-remote config uploadpack.allowfilter 1 && |
| 105 | git -C connectivity-remote config uploadpack.allowanysha1inwant 1 && |
| 106 | |
| 107 | git clone --no-checkout --filter=blob:none \ |
| 108 | "file://$(pwd)/connectivity-remote" connectivity-client && |
| 109 | |
| 110 | # When doing a partial fetch where all tips are part of a promisor pack |
| 111 | # we want to skip the connectivity check, as these objects are allowed |
| 112 | # to not be fully connected. |
| 113 | test_commit -C connectivity-remote two && |
| 114 | GIT_TRACE2_EVENT="$(pwd)/partial.trace" git -C connectivity-client fetch origin && |
| 115 | test_subcommand_flex ! git rev-list --objects --stdin <partial.trace && |
| 116 | |
| 117 | # Otherwise, when doing a fetch where any of the tips is not part of a |
| 118 | # promisor pack, then we must run the connectivity check. |
| 119 | test_commit -C connectivity-remote three && |
| 120 | GIT_TRACE2_EVENT="$(pwd)/full.trace" git -C connectivity-client fetch --no-filter origin && |
| 121 | test_subcommand_flex git rev-list --objects --stdin <full.trace |
| 122 | ' |
| 123 | |
| 124 | # force dynamic object fetch using diff. |
| 125 | # we should only get 1 new blob (for the file in origin/main). |
| 126 | test_expect_success 'verify diff causes dynamic object fetch' ' |
| 127 | git -C pc1 diff main..origin/main -- file.1.txt && |
| 128 | git -C pc1 rev-list --quiet --objects --missing=print \ |
| 129 | main..origin/main >observed && |
| 130 | test_line_count = 4 observed |
| 131 | ' |
| 132 | |
| 133 | # force full dynamic object fetch of the file's history using blame. |
| 134 | # we should get the intermediate blobs for the file. |
| 135 | test_expect_success 'verify blame causes dynamic object fetch' ' |
| 136 | git -C pc1 blame origin/main -- file.1.txt >observed.blame && |
| 137 | test_cmp expect.blame observed.blame && |
| 138 | git -C pc1 rev-list --quiet --objects --missing=print \ |
| 139 | main..origin/main >observed && |
| 140 | test_line_count = 0 observed |
| 141 | ' |
| 142 | |
| 143 | # create new commits in "src" repo to establish a history on file.2.txt |
| 144 | # and push to "srv.bare". |
| 145 | test_expect_success 'push new commits to server for file.2.txt' ' |
| 146 | for x in a b c d e f |
| 147 | do |
| 148 | echo "Mod file.2.txt $x" >>src/file.2.txt && |
| 149 | git -C src add file.2.txt && |
| 150 | git -C src commit -m "mod $x" || return 1 |
| 151 | done && |
| 152 | git -C src push -u srv main |
| 153 | ' |
| 154 | |
| 155 | # Do FULL fetch by disabling inherited filter-spec using --no-filter. |
| 156 | # Verify we have all the new blobs. |
| 157 | test_expect_success 'override inherited filter-spec using --no-filter' ' |
| 158 | git -C pc1 fetch --no-filter origin && |
| 159 | git -C pc1 rev-list --quiet --objects --missing=print \ |
| 160 | main..origin/main >observed && |
| 161 | test_line_count = 0 observed |
| 162 | ' |
| 163 | |
| 164 | # create new commits in "src" repo to establish a history on file.3.txt |
| 165 | # and push to "srv.bare". |
| 166 | test_expect_success 'push new commits to server for file.3.txt' ' |
| 167 | for x in a b c d e f |
| 168 | do |
| 169 | echo "Mod file.3.txt $x" >>src/file.3.txt && |
| 170 | git -C src add file.3.txt && |
| 171 | git -C src commit -m "mod $x" || return 1 |
| 172 | done && |
| 173 | git -C src push -u srv main |
| 174 | ' |
| 175 | |
| 176 | # Do a partial fetch and then try to manually fetch the missing objects. |
| 177 | # This can be used as the basis of a pre-command hook to bulk fetch objects |
| 178 | # perhaps combined with a command in dry-run mode. |
| 179 | test_expect_success 'manual prefetch of missing objects' ' |
| 180 | git -C pc1 fetch --filter=blob:none origin && |
| 181 | |
| 182 | git -C pc1 rev-list --quiet --objects --missing=print \ |
| 183 | main..origin/main >revs && |
| 184 | awk -f print_1.awk revs | |
| 185 | sed "s/?//" | |
| 186 | sort >observed.oids && |
| 187 | |
| 188 | test_line_count = 6 observed.oids && |
| 189 | git -C pc1 fetch-pack --stdin "file://$(pwd)/srv.bare" <observed.oids && |
| 190 | |
| 191 | git -C pc1 rev-list --quiet --objects --missing=print \ |
| 192 | main..origin/main >revs && |
| 193 | awk -f print_1.awk revs | |
| 194 | sed "s/?//" | |
| 195 | sort >observed.oids && |
| 196 | |
| 197 | test_line_count = 0 observed.oids |
| 198 | ' |
| 199 | |
| 200 | # create new commits in "src" repo to establish a history on file.4.txt |
| 201 | # and push to "srv.bare". |
| 202 | test_expect_success 'push new commits to server for file.4.txt' ' |
| 203 | for x in a b c d e f |
| 204 | do |
| 205 | echo "Mod file.4.txt $x" >src/file.4.txt && |
| 206 | if list_contains "a,b" "$x"; then |
| 207 | printf "%10000s" X >>src/file.4.txt |
| 208 | fi && |
| 209 | if list_contains "c,d" "$x"; then |
| 210 | printf "%20000s" X >>src/file.4.txt |
| 211 | fi && |
| 212 | git -C src add file.4.txt && |
| 213 | git -C src commit -m "mod $x" || return 1 |
| 214 | done && |
| 215 | git -C src push -u srv main |
| 216 | ' |
| 217 | |
| 218 | # Do partial fetch to fetch smaller files; then verify that without --refetch |
| 219 | # applying a new filter does not refetch missing large objects. Then use |
| 220 | # --refetch to apply the new filter on existing commits. Test it under both |
| 221 | # protocol v2 & v0. |
| 222 | test_expect_success 'apply a different filter using --refetch' ' |
| 223 | git -C pc1 fetch --filter=blob:limit=999 origin && |
| 224 | git -C pc1 rev-list --quiet --objects --missing=print \ |
| 225 | main..origin/main >observed && |
| 226 | test_line_count = 4 observed && |
| 227 | |
| 228 | git -C pc1 fetch --filter=blob:limit=19999 --refetch origin && |
| 229 | git -C pc1 rev-list --quiet --objects --missing=print \ |
| 230 | main..origin/main >observed && |
| 231 | test_line_count = 2 observed && |
| 232 | |
| 233 | git -c protocol.version=0 -C pc1 fetch --filter=blob:limit=29999 \ |
| 234 | --refetch origin && |
| 235 | git -C pc1 rev-list --quiet --objects --missing=print \ |
| 236 | main..origin/main >observed && |
| 237 | test_line_count = 0 observed |
| 238 | ' |
| 239 | |
| 240 | test_expect_success 'fetch --refetch works with a shallow clone' ' |
| 241 | git clone --no-checkout --depth=1 --filter=blob:none "file://$(pwd)/srv.bare" pc1s && |
| 242 | git -C pc1s rev-list --objects --missing=print HEAD >observed && |
| 243 | test_line_count = 6 observed && |
| 244 | |
| 245 | GIT_TRACE=1 git -C pc1s fetch --filter=blob:limit=999 --refetch origin && |
| 246 | git -C pc1s rev-list --objects --missing=print HEAD >observed && |
| 247 | test_line_count = 6 observed |
| 248 | ' |
| 249 | |
| 250 | test_expect_success 'fetch --refetch triggers repacking' ' |
| 251 | GIT_TRACE2_CONFIG_PARAMS=gc.autoPackLimit,maintenance.incremental-repack.auto && |
| 252 | export GIT_TRACE2_CONFIG_PARAMS && |
| 253 | |
| 254 | GIT_TRACE2_EVENT="$PWD/trace1.event" \ |
| 255 | git -C pc1 fetch --refetch origin && |
| 256 | test_subcommand git maintenance run --auto --no-quiet --no-detach <trace1.event && |
| 257 | test_grep \"param\":\"gc.autopacklimit\",\"value\":\"1\" trace1.event && |
| 258 | test_grep \"param\":\"maintenance.incremental-repack.auto\",\"value\":\"-1\" trace1.event && |
| 259 | |
| 260 | GIT_TRACE2_EVENT="$PWD/trace2.event" \ |
| 261 | git -c protocol.version=0 \ |
| 262 | -c gc.autoPackLimit=0 \ |
| 263 | -c maintenance.incremental-repack.auto=1234 \ |
| 264 | -C pc1 fetch --refetch origin && |
| 265 | test_subcommand git maintenance run --auto --no-quiet --no-detach <trace2.event && |
| 266 | test_grep \"param\":\"gc.autopacklimit\",\"value\":\"0\" trace2.event && |
| 267 | test_grep \"param\":\"maintenance.incremental-repack.auto\",\"value\":\"-1\" trace2.event && |
| 268 | |
| 269 | GIT_TRACE2_EVENT="$PWD/trace3.event" \ |
| 270 | git -c protocol.version=0 \ |
| 271 | -c gc.autoPackLimit=1234 \ |
| 272 | -c maintenance.incremental-repack.auto=0 \ |
| 273 | -C pc1 fetch --refetch origin && |
| 274 | test_subcommand git maintenance run --auto --no-quiet --no-detach <trace3.event && |
| 275 | test_grep \"param\":\"gc.autopacklimit\",\"value\":\"1\" trace3.event && |
| 276 | test_grep \"param\":\"maintenance.incremental-repack.auto\",\"value\":\"0\" trace3.event |
| 277 | ' |
| 278 | |
| 279 | test_expect_success 'partial clone with transfer.fsckobjects=1 works with submodules' ' |
| 280 | test_create_repo submodule && |
| 281 | test_commit -C submodule mycommit && |
| 282 | |
| 283 | test_create_repo src_with_sub && |
| 284 | git -C src_with_sub config uploadpack.allowfilter 1 && |
| 285 | git -C src_with_sub config uploadpack.allowanysha1inwant 1 && |
| 286 | |
| 287 | test_config_global protocol.file.allow always && |
| 288 | |
| 289 | git -C src_with_sub submodule add "file://$(pwd)/submodule" mysub && |
| 290 | git -C src_with_sub commit -m "commit with submodule" && |
| 291 | |
| 292 | git -c transfer.fsckobjects=1 \ |
| 293 | clone --filter="blob:none" "file://$(pwd)/src_with_sub" dst && |
| 294 | test_when_finished rm -rf dst |
| 295 | ' |
| 296 | |
| 297 | test_expect_success 'lazily fetched .gitmodules works' ' |
| 298 | git clone --filter="blob:none" --no-checkout "file://$(pwd)/src_with_sub" dst && |
| 299 | git -C dst fetch && |
| 300 | test_when_finished rm -rf dst |
| 301 | ' |
| 302 | |
| 303 | test_expect_success 'partial clone with transfer.fsckobjects=1 uses index-pack --fsck-objects' ' |
| 304 | git init src && |
| 305 | test_commit -C src x && |
| 306 | test_config -C src uploadpack.allowfilter 1 && |
| 307 | test_config -C src uploadpack.allowanysha1inwant 1 && |
| 308 | |
| 309 | GIT_TRACE="$(pwd)/trace" git -c transfer.fsckobjects=1 \ |
| 310 | clone --filter="blob:none" "file://$(pwd)/src" dst && |
| 311 | test_grep "git index-pack.*--fsck-objects" trace |
| 312 | ' |
| 313 | |
| 314 | test_expect_success 'use fsck before and after manually fetching a missing subtree' ' |
| 315 | # push new commit so server has a subtree |
| 316 | mkdir src/dir && |
| 317 | echo "in dir" >src/dir/file.txt && |
| 318 | git -C src add dir/file.txt && |
| 319 | git -C src commit -m "file in dir" && |
| 320 | git -C src push -u srv main && |
| 321 | SUBTREE=$(git -C src rev-parse HEAD:dir) && |
| 322 | |
| 323 | rm -rf dst && |
| 324 | git clone --no-checkout --filter=tree:0 "file://$(pwd)/srv.bare" dst && |
| 325 | git -C dst fsck && |
| 326 | |
| 327 | # Make sure we only have commits, and all trees and blobs are missing. |
| 328 | git -C dst rev-list --missing=allow-any --objects main \ |
| 329 | >fetched_objects && |
| 330 | awk -f print_1.awk fetched_objects | |
| 331 | xargs -n1 git -C dst cat-file -t >fetched_types && |
| 332 | |
| 333 | sort -u fetched_types >unique_types.observed && |
| 334 | echo commit >unique_types.expected && |
| 335 | test_cmp unique_types.expected unique_types.observed && |
| 336 | |
| 337 | # Auto-fetch a tree with cat-file. |
| 338 | git -C dst cat-file -p $SUBTREE >tree_contents && |
| 339 | test_grep file.txt tree_contents && |
| 340 | |
| 341 | # fsck still works after an auto-fetch of a tree. |
| 342 | git -C dst fsck && |
| 343 | |
| 344 | # Auto-fetch all remaining trees and blobs with --missing=error |
| 345 | git -C dst rev-list --missing=error --objects main >fetched_objects && |
| 346 | test_line_count = 88 fetched_objects && |
| 347 | |
| 348 | awk -f print_1.awk fetched_objects | |
| 349 | xargs -n1 git -C dst cat-file -t >fetched_types && |
| 350 | |
| 351 | sort -u fetched_types >unique_types.observed && |
| 352 | test_write_lines blob commit tree >unique_types.expected && |
| 353 | test_cmp unique_types.expected unique_types.observed |
| 354 | ' |
| 355 | |
| 356 | test_expect_success 'implicitly construct combine: filter with repeated flags' ' |
| 357 | GIT_TRACE=$(pwd)/trace git clone --bare \ |
| 358 | --filter=blob:none --filter=tree:1 \ |
| 359 | "file://$(pwd)/srv.bare" pc2 && |
| 360 | test_grep "trace:.* git pack-objects .*--filter=combine:blob:none+tree:1" \ |
| 361 | trace && |
| 362 | git -C pc2 rev-list --objects --missing=allow-any HEAD >objects && |
| 363 | |
| 364 | # We should have gotten some root trees. |
| 365 | test_grep " $" objects && |
| 366 | # Should not have gotten any non-root trees or blobs. |
| 367 | test_grep ! " ." objects && |
| 368 | |
| 369 | xargs -n 1 git -C pc2 cat-file -t <objects >types && |
| 370 | sort -u types >unique_types.actual && |
| 371 | test_write_lines commit tree >unique_types.expected && |
| 372 | test_cmp unique_types.expected unique_types.actual |
| 373 | ' |
| 374 | |
| 375 | test_expect_success 'upload-pack complains of bogus filter config' ' |
| 376 | printf 0000 | |
| 377 | test_must_fail git \ |
| 378 | -c uploadpackfilter.tree.maxdepth \ |
| 379 | upload-pack . >/dev/null 2>err && |
| 380 | test_grep "unable to parse.*tree.maxdepth" err |
| 381 | ' |
| 382 | |
| 383 | test_expect_success 'upload-pack fails banned object filters' ' |
| 384 | test_config -C srv.bare uploadpackfilter.blob:none.allow false && |
| 385 | test_must_fail ok=sigpipe git clone --no-checkout --filter=blob:none \ |
| 386 | "file://$(pwd)/srv.bare" pc3 2>err && |
| 387 | test_grep "filter '\''blob:none'\'' not supported" err |
| 388 | ' |
| 389 | |
| 390 | test_expect_success 'upload-pack fails banned combine object filters' ' |
| 391 | test_config -C srv.bare uploadpackfilter.allow false && |
| 392 | test_config -C srv.bare uploadpackfilter.combine.allow true && |
| 393 | test_config -C srv.bare uploadpackfilter.tree.allow true && |
| 394 | test_config -C srv.bare uploadpackfilter.blob:none.allow false && |
| 395 | test_must_fail ok=sigpipe git clone --no-checkout --filter=tree:1 \ |
| 396 | --filter=blob:none "file://$(pwd)/srv.bare" pc3 2>err && |
| 397 | test_grep "filter '\''blob:none'\'' not supported" err |
| 398 | ' |
| 399 | |
| 400 | test_expect_success 'upload-pack fails banned object filters with fallback' ' |
| 401 | test_config -C srv.bare uploadpackfilter.allow false && |
| 402 | test_must_fail ok=sigpipe git clone --no-checkout --filter=blob:none \ |
| 403 | "file://$(pwd)/srv.bare" pc3 2>err && |
| 404 | test_grep "filter '\''blob:none'\'' not supported" err |
| 405 | ' |
| 406 | |
| 407 | test_expect_success 'upload-pack limits tree depth filters' ' |
| 408 | test_config -C srv.bare uploadpackfilter.allow false && |
| 409 | test_config -C srv.bare uploadpackfilter.tree.allow true && |
| 410 | test_config -C srv.bare uploadpackfilter.tree.maxDepth 0 && |
| 411 | test_must_fail ok=sigpipe git clone --no-checkout --filter=tree:1 \ |
| 412 | "file://$(pwd)/srv.bare" pc3 2>err && |
| 413 | test_grep "tree filter allows max depth 0, but got 1" err && |
| 414 | |
| 415 | git clone --no-checkout --filter=tree:0 "file://$(pwd)/srv.bare" pc4 && |
| 416 | |
| 417 | test_config -C srv.bare uploadpackfilter.tree.maxDepth 5 && |
| 418 | git clone --no-checkout --filter=tree:5 "file://$(pwd)/srv.bare" pc5 && |
| 419 | test_must_fail ok=sigpipe git clone --no-checkout --filter=tree:6 \ |
| 420 | "file://$(pwd)/srv.bare" pc6 2>err && |
| 421 | test_grep "tree filter allows max depth 5, but got 6" err |
| 422 | ' |
| 423 | |
| 424 | test_expect_success 'partial clone fetches blobs pointed to by refs even if normally filtered out' ' |
| 425 | rm -rf src dst && |
| 426 | git init src && |
| 427 | test_commit -C src x && |
| 428 | test_config -C src uploadpack.allowfilter 1 && |
| 429 | test_config -C src uploadpack.allowanysha1inwant 1 && |
| 430 | |
| 431 | # Create a tag pointing to a blob. |
| 432 | BLOB=$(echo blob-contents | git -C src hash-object --stdin -w) && |
| 433 | git -C src tag myblob "$BLOB" && |
| 434 | |
| 435 | git clone --filter="blob:none" "file://$(pwd)/src" dst 2>err && |
| 436 | test_grep ! "does not point to a valid object" err && |
| 437 | git -C dst fsck |
| 438 | ' |
| 439 | |
| 440 | test_expect_success 'fetch what is specified on CLI even if already promised' ' |
| 441 | rm -rf src dst.git && |
| 442 | git init src && |
| 443 | test_commit -C src foo && |
| 444 | test_config -C src uploadpack.allowfilter 1 && |
| 445 | test_config -C src uploadpack.allowanysha1inwant 1 && |
| 446 | |
| 447 | git hash-object --stdin <src/foo.t >blob && |
| 448 | |
| 449 | git clone --bare --filter=blob:none "file://$(pwd)/src" dst.git && |
| 450 | git -C dst.git rev-list --objects --quiet --missing=print HEAD >missing_before && |
| 451 | test_grep "?$(cat blob)" missing_before && |
| 452 | git -C dst.git fetch origin $(cat blob) && |
| 453 | git -C dst.git rev-list --objects --quiet --missing=print HEAD >missing_after && |
| 454 | test_grep ! "?$(cat blob)" missing_after |
| 455 | ' |
| 456 | |
| 457 | test_expect_success 'setup src repo for sparse filter' ' |
| 458 | git init sparse-src && |
| 459 | git -C sparse-src config --local uploadpack.allowfilter 1 && |
| 460 | git -C sparse-src config --local uploadpack.allowanysha1inwant 1 && |
| 461 | test_commit -C sparse-src one && |
| 462 | test_commit -C sparse-src two && |
| 463 | echo /one.t >sparse-src/only-one && |
| 464 | git -C sparse-src add . && |
| 465 | git -C sparse-src commit -m "add sparse checkout files" |
| 466 | ' |
| 467 | |
| 468 | test_expect_success 'partial clone with sparse filter succeeds' ' |
| 469 | rm -rf dst.git && |
| 470 | git clone --no-local --bare \ |
| 471 | --filter=sparse:oid=main:only-one \ |
| 472 | sparse-src dst.git && |
| 473 | ( |
| 474 | cd dst.git && |
| 475 | git rev-list --objects --missing=print HEAD >out && |
| 476 | test_grep "^$(git rev-parse HEAD:one.t)" out && |
| 477 | test_grep "^?$(git rev-parse HEAD:two.t)" out |
| 478 | ) |
| 479 | ' |
| 480 | |
| 481 | test_expect_success 'partial clone with unresolvable sparse filter fails cleanly' ' |
| 482 | rm -rf dst.git && |
| 483 | test_must_fail git clone --no-local --bare \ |
| 484 | --filter=sparse:oid=main:no-such-name \ |
| 485 | sparse-src dst.git 2>err && |
| 486 | test_grep "unable to access sparse blob in .main:no-such-name" err && |
| 487 | test_must_fail git clone --no-local --bare \ |
| 488 | --filter=sparse:oid=main \ |
| 489 | sparse-src dst.git 2>err && |
| 490 | test_grep "unable to parse sparse filter data in" err |
| 491 | ' |
| 492 | |
| 493 | setup_triangle () { |
| 494 | rm -rf big-blob.txt server client promisor-remote && |
| 495 | |
| 496 | printf "line %d\n" $(test_seq 1 100) >big-blob.txt && |
| 497 | |
| 498 | # Create a server with 2 commits: a commit with a big tree and a child |
| 499 | # commit with an incremental change. Also, create a partial clone |
| 500 | # client that only contains the first commit. |
| 501 | git init server && |
| 502 | git -C server config --local uploadpack.allowfilter 1 && |
| 503 | for i in $(test_seq 1 100) |
| 504 | do |
| 505 | echo "make the tree big" >server/file$i && |
| 506 | git -C server add file$i || return 1 |
| 507 | done && |
| 508 | git -C server commit -m "initial" && |
| 509 | git clone --bare --filter=tree:0 "file://$(pwd)/server" client && |
| 510 | echo another line >>server/file1 && |
| 511 | git -C server commit -am "incremental change" && |
| 512 | |
| 513 | # Create a promisor remote that only contains the tree and blob from |
| 514 | # the first commit. |
| 515 | git init promisor-remote && |
| 516 | git -C server config --local uploadpack.allowanysha1inwant 1 && |
| 517 | TREE_HASH=$(git -C server rev-parse HEAD~1^{tree}) && |
| 518 | git -C promisor-remote fetch --keep "file://$(pwd)/server" "$TREE_HASH" && |
| 519 | git -C promisor-remote count-objects -v >object-count && |
| 520 | test_grep "count: 0" object-count && |
| 521 | test_grep "in-pack: 2" object-count && |
| 522 | |
| 523 | # Set it as the promisor remote of client. Thus, whenever |
| 524 | # the client lazy fetches, the lazy fetch will succeed only if it is |
| 525 | # for this tree or blob. |
| 526 | test_commit -C promisor-remote one && # so that ref advertisement is not empty |
| 527 | git -C promisor-remote config --local uploadpack.allowanysha1inwant 1 && |
| 528 | git -C client remote set-url origin "file://$(pwd)/promisor-remote" |
| 529 | } |
| 530 | |
| 531 | # NEEDSWORK: The tests beginning with "fetch lazy-fetches" below only |
| 532 | # test that "fetch" avoid fetching trees and blobs, but not commits or |
| 533 | # tags. Revisit this if Git is ever taught to support partial clones |
| 534 | # with commits and/or tags filtered out. |
| 535 | |
| 536 | test_expect_success 'fetch lazy-fetches only to resolve deltas' ' |
| 537 | setup_triangle && |
| 538 | |
| 539 | # Exercise to make sure it works. Git will not fetch anything from the |
| 540 | # promisor remote other than for the big tree (because it needs to |
| 541 | # resolve the delta). |
| 542 | GIT_TRACE_PACKET="$(pwd)/trace" git -C client \ |
| 543 | fetch "file://$(pwd)/server" main && |
| 544 | |
| 545 | # Verify the assumption that the client needed to fetch the delta base |
| 546 | # to resolve the delta. |
| 547 | git -C server rev-parse HEAD~1^{tree} >hash && |
| 548 | test_grep "want $(cat hash)" trace |
| 549 | ' |
| 550 | |
| 551 | test_expect_success 'fetch lazy-fetches only to resolve deltas, protocol v2' ' |
| 552 | setup_triangle && |
| 553 | |
| 554 | git -C server config --local protocol.version 2 && |
| 555 | git -C client config --local protocol.version 2 && |
| 556 | git -C promisor-remote config --local protocol.version 2 && |
| 557 | |
| 558 | # Exercise to make sure it works. Git will not fetch anything from the |
| 559 | # promisor remote other than for the big blob (because it needs to |
| 560 | # resolve the delta). |
| 561 | GIT_TRACE_PACKET="$(pwd)/trace" git -C client \ |
| 562 | fetch "file://$(pwd)/server" main && |
| 563 | |
| 564 | # Verify that protocol version 2 was used. |
| 565 | test_grep "fetch< version 2" trace && |
| 566 | |
| 567 | # Verify the assumption that the client needed to fetch the delta base |
| 568 | # to resolve the delta. |
| 569 | git -C server rev-parse HEAD~1^{tree} >hash && |
| 570 | test_grep "want $(cat hash)" trace |
| 571 | ' |
| 572 | |
| 573 | test_expect_success 'fetch does not lazy-fetch missing targets of its refs' ' |
| 574 | rm -rf server client trace && |
| 575 | |
| 576 | test_create_repo server && |
| 577 | test_config -C server uploadpack.allowfilter 1 && |
| 578 | test_config -C server uploadpack.allowanysha1inwant 1 && |
| 579 | test_commit -C server foo && |
| 580 | |
| 581 | git clone --filter=blob:none "file://$(pwd)/server" client && |
| 582 | # Make all refs point to nothing by deleting all objects. |
| 583 | rm client/.git/objects/pack/* && |
| 584 | |
| 585 | test_commit -C server bar && |
| 586 | GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \ |
| 587 | --no-tags --recurse-submodules=no \ |
| 588 | origin refs/tags/bar && |
| 589 | FOO_HASH=$(git -C server rev-parse foo) && |
| 590 | test_grep ! "want $FOO_HASH" trace |
| 591 | ' |
| 592 | |
| 593 | # The following two tests must be in this order. It is important that |
| 594 | # the srv.bare repository did not have tags during clone, but has tags |
| 595 | # in the fetch. |
| 596 | |
| 597 | test_expect_success 'verify fetch succeeds when asking for new tags' ' |
| 598 | git clone --filter=blob:none "file://$(pwd)/srv.bare" tag-test && |
| 599 | for i in I J K |
| 600 | do |
| 601 | test_commit -C src $i && |
| 602 | git -C src branch $i || return 1 |
| 603 | done && |
| 604 | git -C srv.bare fetch --tags origin +refs/heads/*:refs/heads/* && |
| 605 | git -C tag-test -c protocol.version=2 fetch --tags origin |
| 606 | ' |
| 607 | |
| 608 | test_expect_success 'verify fetch downloads only one pack when updating refs' ' |
| 609 | git clone --filter=blob:none "file://$(pwd)/srv.bare" pack-test && |
| 610 | ls pack-test/.git/objects/pack/*pack >pack-list && |
| 611 | test_line_count = 2 pack-list && |
| 612 | test_config -C pack-test maintenance.auto false && |
| 613 | for i in A B C |
| 614 | do |
| 615 | test_commit -C src $i && |
| 616 | git -C src branch $i || return 1 |
| 617 | done && |
| 618 | git -C srv.bare fetch origin +refs/heads/*:refs/heads/* && |
| 619 | git -C pack-test fetch origin && |
| 620 | ls pack-test/.git/objects/pack/*pack >pack-list && |
| 621 | test_line_count = 3 pack-list |
| 622 | ' |
| 623 | |
| 624 | test_expect_success 'single-branch tag following respects partial clone' ' |
| 625 | git clone --single-branch -b B --filter=blob:none \ |
| 626 | "file://$(pwd)/srv.bare" single && |
| 627 | git -C single rev-parse --verify refs/tags/B && |
| 628 | git -C single rev-parse --verify refs/tags/A && |
| 629 | test_must_fail git -C single rev-parse --verify refs/tags/C |
| 630 | ' |
| 631 | |
| 632 | test_expect_success 'fetch from a partial clone, protocol v0' ' |
| 633 | rm -rf server client trace && |
| 634 | |
| 635 | # Pretend that the server is a partial clone |
| 636 | git init server && |
| 637 | git -C server remote add a_remote "file://$(pwd)/" && |
| 638 | test_config -C server core.repositoryformatversion 1 && |
| 639 | test_config -C server extensions.partialclone a_remote && |
| 640 | test_config -C server protocol.version 0 && |
| 641 | test_commit -C server foo && |
| 642 | |
| 643 | # Fetch from the server |
| 644 | git init client && |
| 645 | test_config -C client protocol.version 0 && |
| 646 | test_commit -C client bar && |
| 647 | GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch "file://$(pwd)/server" && |
| 648 | test_grep ! "version 2" trace |
| 649 | ' |
| 650 | |
| 651 | test_expect_success 'fetch from a partial clone, protocol v2' ' |
| 652 | rm -rf server client trace && |
| 653 | |
| 654 | # Pretend that the server is a partial clone |
| 655 | git init server && |
| 656 | git -C server remote add a_remote "file://$(pwd)/" && |
| 657 | test_config -C server core.repositoryformatversion 1 && |
| 658 | test_config -C server extensions.partialclone a_remote && |
| 659 | test_config -C server protocol.version 2 && |
| 660 | test_commit -C server foo && |
| 661 | |
| 662 | # Fetch from the server |
| 663 | git init client && |
| 664 | test_config -C client protocol.version 2 && |
| 665 | test_commit -C client bar && |
| 666 | GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch "file://$(pwd)/server" && |
| 667 | test_grep "version 2" trace |
| 668 | ' |
| 669 | |
| 670 | test_expect_success 'repack does not loosen promisor objects' ' |
| 671 | rm -rf client trace && |
| 672 | git clone --bare --filter=blob:none "file://$(pwd)/srv.bare" client && |
| 673 | test_when_finished "rm -rf client trace" && |
| 674 | GIT_TRACE2_PERF="$(pwd)/trace" git -C client repack -A -d && |
| 675 | test_grep "loosen_unused_packed_objects/loosened:0" trace |
| 676 | ' |
| 677 | |
| 678 | test_expect_success 'lazy-fetch in submodule succeeds' ' |
| 679 | # setup |
| 680 | test_config_global protocol.file.allow always && |
| 681 | |
| 682 | test_when_finished "rm -rf src-sub" && |
| 683 | git init src-sub && |
| 684 | git -C src-sub config uploadpack.allowfilter 1 && |
| 685 | git -C src-sub config uploadpack.allowanysha1inwant 1 && |
| 686 | |
| 687 | # This blob must be missing in the subsequent commit. |
| 688 | echo foo >src-sub/file && |
| 689 | git -C src-sub add file && |
| 690 | git -C src-sub commit -m "submodule one" && |
| 691 | SUB_ONE=$(git -C src-sub rev-parse HEAD) && |
| 692 | |
| 693 | echo bar >src-sub/file && |
| 694 | git -C src-sub add file && |
| 695 | git -C src-sub commit -m "submodule two" && |
| 696 | SUB_TWO=$(git -C src-sub rev-parse HEAD) && |
| 697 | |
| 698 | test_when_finished "rm -rf src-super" && |
| 699 | git init src-super && |
| 700 | git -C src-super config uploadpack.allowfilter 1 && |
| 701 | git -C src-super config uploadpack.allowanysha1inwant 1 && |
| 702 | git -C src-super submodule add ../src-sub src-sub && |
| 703 | |
| 704 | git -C src-super/src-sub checkout $SUB_ONE && |
| 705 | git -C src-super add src-sub && |
| 706 | git -C src-super commit -m "superproject one" && |
| 707 | |
| 708 | git -C src-super/src-sub checkout $SUB_TWO && |
| 709 | git -C src-super add src-sub && |
| 710 | git -C src-super commit -m "superproject two" && |
| 711 | |
| 712 | # the fetch |
| 713 | test_when_finished "rm -rf client" && |
| 714 | git clone --filter=blob:none --also-filter-submodules \ |
| 715 | --recurse-submodules "file://$(pwd)/src-super" client && |
| 716 | |
| 717 | # Trigger lazy-fetch from the superproject |
| 718 | git -C client restore --recurse-submodules --source=HEAD^ :/ |
| 719 | ' |
| 720 | |
| 721 | test_expect_success 'after fetching descendants of non-promisor commits, gc works' ' |
| 722 | # Setup |
| 723 | git init full && |
| 724 | git -C full config uploadpack.allowfilter 1 && |
| 725 | git -C full config uploadpack.allowanysha1inwant 1 && |
| 726 | touch full/foo && |
| 727 | git -C full add foo && |
| 728 | git -C full commit -m "commit 1" && |
| 729 | git -C full checkout --detach && |
| 730 | |
| 731 | # Partial clone and push commit to remote |
| 732 | git clone "file://$(pwd)/full" --filter=blob:none partial && |
| 733 | echo "hello" > partial/foo && |
| 734 | git -C partial commit -a -m "commit 2" && |
| 735 | git -C partial push && |
| 736 | |
| 737 | # gc in partial repo |
| 738 | git -C partial gc --prune=now && |
| 739 | |
| 740 | # Create another commit in normal repo |
| 741 | git -C full checkout main && |
| 742 | echo " world" >> full/foo && |
| 743 | git -C full commit -a -m "commit 3" && |
| 744 | |
| 745 | # Pull from remote in partial repo, and run gc again |
| 746 | git -C partial pull && |
| 747 | git -C partial gc --prune=now |
| 748 | ' |
| 749 | |
| 750 | |
| 751 | . "$TEST_DIRECTORY"/lib-httpd.sh |
| 752 | start_httpd |
| 753 | |
| 754 | # Converts bytes into their hexadecimal representation. For example, |
| 755 | # "printf 'ab\r\n' | hex_unpack" results in '61620d0a'. |
| 756 | hex_unpack () { |
| 757 | perl -e '$/ = undef; $input = <>; print unpack("H2" x length($input), $input)' |
| 758 | } |
| 759 | |
| 760 | # Inserts $1 at the start of the string and every 2 characters thereafter. |
| 761 | intersperse () { |
| 762 | sed 's/\(..\)/'$1'\1/g' |
| 763 | } |
| 764 | |
| 765 | # Create a one-time-script command to replace the existing packfile with $1. |
| 766 | replace_packfile () { |
| 767 | cp "$1" one-time-pack && |
| 768 | write_script "$HTTPD_ROOT_PATH/one-time-script" <<-EOF |
| 769 | if grep packfile "\$1" >/dev/null |
| 770 | then |
| 771 | sed '/packfile/q' "\$1" && |
| 772 | # The protocol requires that the packfile be sent in sideband |
| 773 | # 1, hence the extra \001 byte at the beginning. |
| 774 | printf "%04x\001" \$((\$(wc -c <"$PWD/one-time-pack") + 5)) && |
| 775 | cat "$PWD/one-time-pack" && |
| 776 | printf "0000" |
| 777 | else |
| 778 | cat "\$1" |
| 779 | fi |
| 780 | EOF |
| 781 | } |
| 782 | |
| 783 | test_expect_success 'upon cloning, check that all refs point to objects' ' |
| 784 | SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" && |
| 785 | rm -rf "$SERVER" repo && |
| 786 | test_create_repo "$SERVER" && |
| 787 | test_commit -C "$SERVER" foo && |
| 788 | test_config -C "$SERVER" uploadpack.allowfilter 1 && |
| 789 | test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 && |
| 790 | |
| 791 | # Create a tag pointing to a blob. |
| 792 | BLOB=$(echo blob-contents | git -C "$SERVER" hash-object --stdin -w) && |
| 793 | git -C "$SERVER" tag myblob "$BLOB" && |
| 794 | |
| 795 | # Craft a packfile not including that blob. |
| 796 | git -C "$SERVER" rev-parse HEAD | |
| 797 | git -C "$SERVER" pack-objects --stdout >incomplete.pack && |
| 798 | |
| 799 | # Replace the existing packfile with the crafted one. The protocol |
| 800 | # requires that the packfile be sent in sideband 1, hence the extra |
| 801 | # \x01 byte at the beginning. |
| 802 | replace_packfile incomplete.pack && |
| 803 | |
| 804 | # Use protocol v2 because the perl command looks for the "packfile" |
| 805 | # section header. |
| 806 | test_config -C "$SERVER" protocol.version 2 && |
| 807 | test_must_fail git -c protocol.version=2 clone \ |
| 808 | --filter=blob:none $HTTPD_URL/one_time_script/server repo 2>err && |
| 809 | |
| 810 | test_grep "did not send all necessary objects" err && |
| 811 | |
| 812 | # Ensure that the one-time-script script was used. |
| 813 | ! test -e "$HTTPD_ROOT_PATH/one-time-script" |
| 814 | ' |
| 815 | |
| 816 | test_expect_success 'when partial cloning, tolerate server not sending target of tag' ' |
| 817 | SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" && |
| 818 | rm -rf "$SERVER" repo && |
| 819 | test_create_repo "$SERVER" && |
| 820 | test_commit -C "$SERVER" foo && |
| 821 | test_config -C "$SERVER" uploadpack.allowfilter 1 && |
| 822 | test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 && |
| 823 | |
| 824 | # Create an annotated tag pointing to a blob. |
| 825 | BLOB=$(echo blob-contents | git -C "$SERVER" hash-object --stdin -w) && |
| 826 | git -C "$SERVER" tag -m message -a myblob "$BLOB" && |
| 827 | |
| 828 | # Craft a packfile including the tag, but not the blob it points to. |
| 829 | # Also, omit objects referenced from HEAD in order to force a second |
| 830 | # fetch (to fetch missing objects) upon the automatic checkout that |
| 831 | # happens after a clone. |
| 832 | printf "%s\n%s\n--not\n%s\n%s\n" \ |
| 833 | $(git -C "$SERVER" rev-parse HEAD) \ |
| 834 | $(git -C "$SERVER" rev-parse myblob) \ |
| 835 | $(git -C "$SERVER" rev-parse HEAD^{tree}) \ |
| 836 | $(git -C "$SERVER" rev-parse myblob^{blob}) | |
| 837 | git -C "$SERVER" pack-objects --thin --stdout >incomplete.pack && |
| 838 | |
| 839 | # Replace the existing packfile with the crafted one. The protocol |
| 840 | # requires that the packfile be sent in sideband 1, hence the extra |
| 841 | # \x01 byte at the beginning. |
| 842 | replace_packfile incomplete.pack && |
| 843 | |
| 844 | # Use protocol v2 because the perl command looks for the "packfile" |
| 845 | # section header. |
| 846 | test_config -C "$SERVER" protocol.version 2 && |
| 847 | |
| 848 | # Exercise to make sure it works. |
| 849 | git -c protocol.version=2 clone \ |
| 850 | --filter=blob:none $HTTPD_URL/one_time_script/server repo 2> err && |
| 851 | test_grep ! "missing object referenced by" err && |
| 852 | |
| 853 | # Ensure that the one-time-script script was used. |
| 854 | ! test -e "$HTTPD_ROOT_PATH/one-time-script" |
| 855 | ' |
| 856 | |
| 857 | test_expect_success PERL_TEST_HELPERS 'tolerate server sending REF_DELTA against missing promisor objects' ' |
| 858 | SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" && |
| 859 | rm -rf "$SERVER" repo && |
| 860 | test_create_repo "$SERVER" && |
| 861 | test_config -C "$SERVER" uploadpack.allowfilter 1 && |
| 862 | test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 && |
| 863 | |
| 864 | # Create a commit with 2 blobs to be used as delta bases. |
| 865 | for i in $(test_seq 10) |
| 866 | do |
| 867 | echo "this is a line" >>"$SERVER/foo.txt" && |
| 868 | echo "this is another line" >>"$SERVER/have.txt" || return 1 |
| 869 | done && |
| 870 | git -C "$SERVER" add foo.txt have.txt && |
| 871 | git -C "$SERVER" commit -m bar && |
| 872 | git -C "$SERVER" rev-parse HEAD:foo.txt >deltabase_missing && |
| 873 | git -C "$SERVER" rev-parse HEAD:have.txt >deltabase_have && |
| 874 | |
| 875 | # Clone. The client has deltabase_have but not deltabase_missing. |
| 876 | git -c protocol.version=2 clone --no-checkout \ |
| 877 | --filter=blob:none $HTTPD_URL/one_time_script/server repo && |
| 878 | git -C repo hash-object -w -- "$SERVER/have.txt" && |
| 879 | |
| 880 | # Sanity check to ensure that the client does not have |
| 881 | # deltabase_missing. |
| 882 | git -C repo rev-list --objects --ignore-missing \ |
| 883 | -- $(cat deltabase_missing) >objlist && |
| 884 | test_line_count = 0 objlist && |
| 885 | |
| 886 | # Another commit. This commit will be fetched by the client. |
| 887 | echo "abcdefghijklmnopqrstuvwxyz" >>"$SERVER/foo.txt" && |
| 888 | echo "abcdefghijklmnopqrstuvwxyz" >>"$SERVER/have.txt" && |
| 889 | git -C "$SERVER" add foo.txt have.txt && |
| 890 | git -C "$SERVER" commit -m baz && |
| 891 | |
| 892 | # Pack a thin pack containing, among other things, HEAD:foo.txt |
| 893 | # delta-ed against HEAD^:foo.txt and HEAD:have.txt delta-ed against |
| 894 | # HEAD^:have.txt. |
| 895 | printf "%s\n--not\n%s\n" \ |
| 896 | $(git -C "$SERVER" rev-parse HEAD) \ |
| 897 | $(git -C "$SERVER" rev-parse HEAD^) | |
| 898 | git -C "$SERVER" pack-objects --thin --stdout >thin.pack && |
| 899 | |
| 900 | # Ensure that the pack contains one delta against HEAD^:foo.txt. Since |
| 901 | # the delta contains at least 26 novel characters, the size cannot be |
| 902 | # contained in 4 bits, so the object header will take up 2 bytes. The |
| 903 | # most significant nybble of the first byte is 0b1111 (0b1 to indicate |
| 904 | # that the header continues, and 0b111 to indicate REF_DELTA), followed |
| 905 | # by any 3 nybbles, then the OID of the delta base. |
| 906 | printf "f.,..%s" $(intersperse "," <deltabase_missing) >want && |
| 907 | hex_unpack <thin.pack | intersperse "," >have && |
| 908 | test_grep $(cat want) have && |
| 909 | |
| 910 | # Ensure that the pack contains one delta against HEAD^:have.txt, |
| 911 | # similar to the above. |
| 912 | printf "f.,..%s" $(intersperse "," <deltabase_have) >want && |
| 913 | hex_unpack <thin.pack | intersperse "," >have && |
| 914 | test_grep $(cat want) have && |
| 915 | |
| 916 | replace_packfile thin.pack && |
| 917 | |
| 918 | # Use protocol v2 because the perl command looks for the "packfile" |
| 919 | # section header. |
| 920 | test_config -C "$SERVER" protocol.version 2 && |
| 921 | |
| 922 | # Fetch the thin pack and ensure that index-pack is able to handle the |
| 923 | # REF_DELTA object with a missing promisor delta base. |
| 924 | GIT_TRACE_PACKET="$(pwd)/trace" git -C repo -c protocol.version=2 fetch && |
| 925 | |
| 926 | # Ensure that the missing delta base was directly fetched, but not the |
| 927 | # one that the client has. |
| 928 | test_grep "want $(cat deltabase_missing)" trace && |
| 929 | test_grep ! "want $(cat deltabase_have)" trace && |
| 930 | |
| 931 | # Ensure that the one-time-script script was used. |
| 932 | ! test -e "$HTTPD_ROOT_PATH/one-time-script" |
| 933 | ' |
| 934 | |
| 935 | # DO NOT add non-httpd-specific tests here, because the last part of this |
| 936 | # test script is only executed when httpd is available and enabled. |
| 937 | |
| 938 | test_done |