25bccb4b79
When fetch.bundleURI is set, 'git fetch' downloads bundles from the given bundle URI before fetching from the specified remote. However, when using non-file remotes, 'git fetch --all' will launch 'git fetch' subprocesses which then read fetch.bundleURI and fetch the bundle list again. We do not expect the bundle list to have new information during these multiple runs, so avoid these extra calls by un-setting fetch.bundleURI in the subprocess arguments. Be careful to skip fetching bundles for the empty bundle string. Fetching bundles from the empty list presents some interesting test failures. Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1059 lines
26 KiB
Bash
Executable File
1059 lines
26 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='test fetching bundles with --bundle-uri'
|
|
|
|
. ./test-lib.sh
|
|
|
|
test_expect_success 'fail to clone from non-existent file' '
|
|
test_when_finished rm -rf test &&
|
|
git clone --bundle-uri="$(pwd)/does-not-exist" . test 2>err &&
|
|
grep "failed to download bundle from URI" err
|
|
'
|
|
|
|
test_expect_success 'fail to clone from non-bundle file' '
|
|
test_when_finished rm -rf test &&
|
|
echo bogus >bogus &&
|
|
git clone --bundle-uri="$(pwd)/bogus" . test 2>err &&
|
|
grep "is not a bundle" err
|
|
'
|
|
|
|
test_expect_success 'create bundle' '
|
|
git init clone-from &&
|
|
git -C clone-from checkout -b topic &&
|
|
test_commit -C clone-from A &&
|
|
test_commit -C clone-from B &&
|
|
git -C clone-from bundle create B.bundle topic
|
|
'
|
|
|
|
test_expect_success 'clone with path bundle' '
|
|
git clone --bundle-uri="clone-from/B.bundle" \
|
|
clone-from clone-path &&
|
|
git -C clone-path rev-parse refs/bundles/topic >actual &&
|
|
git -C clone-from rev-parse topic >expect &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'clone with file:// bundle' '
|
|
git clone --bundle-uri="file://$(pwd)/clone-from/B.bundle" \
|
|
clone-from clone-file &&
|
|
git -C clone-file rev-parse refs/bundles/topic >actual &&
|
|
git -C clone-from rev-parse topic >expect &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
# To get interesting tests for bundle lists, we need to construct a
|
|
# somewhat-interesting commit history.
|
|
#
|
|
# ---------------- bundle-4
|
|
#
|
|
# 4
|
|
# / \
|
|
# ----|---|------- bundle-3
|
|
# | |
|
|
# | 3
|
|
# | |
|
|
# ----|---|------- bundle-2
|
|
# | |
|
|
# 2 |
|
|
# | |
|
|
# ----|---|------- bundle-1
|
|
# \ /
|
|
# 1
|
|
# |
|
|
# (previous commits)
|
|
test_expect_success 'construct incremental bundle list' '
|
|
(
|
|
cd clone-from &&
|
|
git checkout -b base &&
|
|
test_commit 1 &&
|
|
git checkout -b left &&
|
|
test_commit 2 &&
|
|
git checkout -b right base &&
|
|
test_commit 3 &&
|
|
git checkout -b merge left &&
|
|
git merge right -m "4" &&
|
|
|
|
git bundle create bundle-1.bundle base &&
|
|
git bundle create bundle-2.bundle base..left &&
|
|
git bundle create bundle-3.bundle base..right &&
|
|
git bundle create bundle-4.bundle merge --not left right
|
|
)
|
|
'
|
|
|
|
test_expect_success 'clone bundle list (file, no heuristic)' '
|
|
cat >bundle-list <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
|
|
[bundle "bundle-1"]
|
|
uri = file://$(pwd)/clone-from/bundle-1.bundle
|
|
|
|
[bundle "bundle-2"]
|
|
uri = file://$(pwd)/clone-from/bundle-2.bundle
|
|
|
|
[bundle "bundle-3"]
|
|
uri = file://$(pwd)/clone-from/bundle-3.bundle
|
|
|
|
[bundle "bundle-4"]
|
|
uri = file://$(pwd)/clone-from/bundle-4.bundle
|
|
EOF
|
|
|
|
git clone --bundle-uri="file://$(pwd)/bundle-list" \
|
|
clone-from clone-list-file 2>err &&
|
|
! grep "Repository lacks these prerequisite commits" err &&
|
|
|
|
git -C clone-from for-each-ref --format="%(objectname)" >oids &&
|
|
git -C clone-list-file cat-file --batch-check <oids &&
|
|
|
|
git -C clone-list-file for-each-ref --format="%(refname)" >refs &&
|
|
grep "refs/bundles/" refs >actual &&
|
|
cat >expect <<-\EOF &&
|
|
refs/bundles/base
|
|
refs/bundles/left
|
|
refs/bundles/merge
|
|
refs/bundles/right
|
|
EOF
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'clone bundle list (file, all mode, some failures)' '
|
|
cat >bundle-list <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
|
|
# Does not exist. Should be skipped.
|
|
[bundle "bundle-0"]
|
|
uri = file://$(pwd)/clone-from/bundle-0.bundle
|
|
|
|
[bundle "bundle-1"]
|
|
uri = file://$(pwd)/clone-from/bundle-1.bundle
|
|
|
|
[bundle "bundle-2"]
|
|
uri = file://$(pwd)/clone-from/bundle-2.bundle
|
|
|
|
# No bundle-3 means bundle-4 will not apply.
|
|
|
|
[bundle "bundle-4"]
|
|
uri = file://$(pwd)/clone-from/bundle-4.bundle
|
|
|
|
# Does not exist. Should be skipped.
|
|
[bundle "bundle-5"]
|
|
uri = file://$(pwd)/clone-from/bundle-5.bundle
|
|
EOF
|
|
|
|
GIT_TRACE2_PERF=1 \
|
|
git clone --bundle-uri="file://$(pwd)/bundle-list" \
|
|
clone-from clone-all-some 2>err &&
|
|
! grep "Repository lacks these prerequisite commits" err &&
|
|
! grep "fatal" err &&
|
|
grep "warning: failed to download bundle from URI" err &&
|
|
|
|
git -C clone-from for-each-ref --format="%(objectname)" >oids &&
|
|
git -C clone-all-some cat-file --batch-check <oids &&
|
|
|
|
git -C clone-all-some for-each-ref --format="%(refname)" >refs &&
|
|
grep "refs/bundles/" refs >actual &&
|
|
cat >expect <<-\EOF &&
|
|
refs/bundles/base
|
|
refs/bundles/left
|
|
EOF
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'clone bundle list (file, all mode, all failures)' '
|
|
cat >bundle-list <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
|
|
# Does not exist. Should be skipped.
|
|
[bundle "bundle-0"]
|
|
uri = file://$(pwd)/clone-from/bundle-0.bundle
|
|
|
|
# Does not exist. Should be skipped.
|
|
[bundle "bundle-5"]
|
|
uri = file://$(pwd)/clone-from/bundle-5.bundle
|
|
EOF
|
|
|
|
git clone --bundle-uri="file://$(pwd)/bundle-list" \
|
|
clone-from clone-all-fail 2>err &&
|
|
! grep "Repository lacks these prerequisite commits" err &&
|
|
! grep "fatal" err &&
|
|
grep "warning: failed to download bundle from URI" err &&
|
|
|
|
git -C clone-from for-each-ref --format="%(objectname)" >oids &&
|
|
git -C clone-all-fail cat-file --batch-check <oids &&
|
|
|
|
git -C clone-all-fail for-each-ref --format="%(refname)" >refs &&
|
|
! grep "refs/bundles/" refs
|
|
'
|
|
|
|
test_expect_success 'clone bundle list (file, any mode)' '
|
|
cat >bundle-list <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = any
|
|
|
|
# Does not exist. Should be skipped.
|
|
[bundle "bundle-0"]
|
|
uri = file://$(pwd)/clone-from/bundle-0.bundle
|
|
|
|
[bundle "bundle-1"]
|
|
uri = file://$(pwd)/clone-from/bundle-1.bundle
|
|
|
|
# Does not exist. Should be skipped.
|
|
[bundle "bundle-5"]
|
|
uri = file://$(pwd)/clone-from/bundle-5.bundle
|
|
EOF
|
|
|
|
git clone --bundle-uri="file://$(pwd)/bundle-list" \
|
|
clone-from clone-any-file 2>err &&
|
|
! grep "Repository lacks these prerequisite commits" err &&
|
|
|
|
git -C clone-from for-each-ref --format="%(objectname)" >oids &&
|
|
git -C clone-any-file cat-file --batch-check <oids &&
|
|
|
|
git -C clone-any-file for-each-ref --format="%(refname)" >refs &&
|
|
grep "refs/bundles/" refs >actual &&
|
|
cat >expect <<-\EOF &&
|
|
refs/bundles/base
|
|
EOF
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'clone bundle list (file, any mode, all failures)' '
|
|
cat >bundle-list <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = any
|
|
|
|
# Does not exist. Should be skipped.
|
|
[bundle "bundle-0"]
|
|
uri = $HTTPD_URL/bundle-0.bundle
|
|
|
|
# Does not exist. Should be skipped.
|
|
[bundle "bundle-5"]
|
|
uri = $HTTPD_URL/bundle-5.bundle
|
|
EOF
|
|
|
|
git clone --bundle-uri="file://$(pwd)/bundle-list" \
|
|
clone-from clone-any-fail 2>err &&
|
|
! grep "fatal" err &&
|
|
grep "warning: failed to download bundle from URI" err &&
|
|
|
|
git -C clone-from for-each-ref --format="%(objectname)" >oids &&
|
|
git -C clone-any-fail cat-file --batch-check <oids &&
|
|
|
|
git -C clone-any-fail for-each-ref --format="%(refname)" >refs &&
|
|
! grep "refs/bundles/" refs
|
|
'
|
|
|
|
#########################################################################
|
|
# HTTP tests begin here
|
|
|
|
. "$TEST_DIRECTORY"/lib-httpd.sh
|
|
start_httpd
|
|
|
|
test_expect_success 'fail to fetch from non-existent HTTP URL' '
|
|
test_when_finished rm -rf test &&
|
|
git clone --bundle-uri="$HTTPD_URL/does-not-exist" . test 2>err &&
|
|
grep "failed to download bundle from URI" err
|
|
'
|
|
|
|
test_expect_success 'fail to fetch from non-bundle HTTP URL' '
|
|
test_when_finished rm -rf test &&
|
|
echo bogus >"$HTTPD_DOCUMENT_ROOT_PATH/bogus" &&
|
|
git clone --bundle-uri="$HTTPD_URL/bogus" . test 2>err &&
|
|
grep "is not a bundle" err
|
|
'
|
|
|
|
test_expect_success 'clone HTTP bundle' '
|
|
cp clone-from/B.bundle "$HTTPD_DOCUMENT_ROOT_PATH/B.bundle" &&
|
|
|
|
git clone --no-local --mirror clone-from \
|
|
"$HTTPD_DOCUMENT_ROOT_PATH/fetch.git" &&
|
|
|
|
git clone --bundle-uri="$HTTPD_URL/B.bundle" \
|
|
"$HTTPD_URL/smart/fetch.git" clone-http &&
|
|
git -C clone-http rev-parse refs/bundles/topic >actual &&
|
|
git -C clone-from rev-parse topic >expect &&
|
|
test_cmp expect actual &&
|
|
|
|
test_config -C clone-http log.excludedecoration refs/bundle/
|
|
'
|
|
|
|
test_expect_success 'clone bundle list (HTTP, no heuristic)' '
|
|
test_when_finished rm -f trace*.txt &&
|
|
|
|
cp clone-from/bundle-*.bundle "$HTTPD_DOCUMENT_ROOT_PATH/" &&
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
|
|
[bundle "bundle-1"]
|
|
uri = $HTTPD_URL/bundle-1.bundle
|
|
|
|
[bundle "bundle-2"]
|
|
uri = $HTTPD_URL/bundle-2.bundle
|
|
|
|
[bundle "bundle-3"]
|
|
uri = $HTTPD_URL/bundle-3.bundle
|
|
|
|
[bundle "bundle-4"]
|
|
uri = $HTTPD_URL/bundle-4.bundle
|
|
EOF
|
|
|
|
GIT_TRACE2_EVENT="$(pwd)/trace-clone.txt" \
|
|
git clone --bundle-uri="$HTTPD_URL/bundle-list" \
|
|
clone-from clone-list-http 2>err &&
|
|
! grep "Repository lacks these prerequisite commits" err &&
|
|
|
|
git -C clone-from for-each-ref --format="%(objectname)" >oids &&
|
|
git -C clone-list-http cat-file --batch-check <oids &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-1.bundle
|
|
$HTTPD_URL/bundle-2.bundle
|
|
$HTTPD_URL/bundle-3.bundle
|
|
$HTTPD_URL/bundle-4.bundle
|
|
$HTTPD_URL/bundle-list
|
|
EOF
|
|
|
|
# Sort the list, since the order is not well-defined
|
|
# without a heuristic.
|
|
test_remote_https_urls <trace-clone.txt | sort >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'clone bundle list (HTTP, any mode)' '
|
|
cp clone-from/bundle-*.bundle "$HTTPD_DOCUMENT_ROOT_PATH/" &&
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = any
|
|
|
|
# Does not exist. Should be skipped.
|
|
[bundle "bundle-0"]
|
|
uri = $HTTPD_URL/bundle-0.bundle
|
|
|
|
[bundle "bundle-1"]
|
|
uri = $HTTPD_URL/bundle-1.bundle
|
|
|
|
# Does not exist. Should be skipped.
|
|
[bundle "bundle-5"]
|
|
uri = $HTTPD_URL/bundle-5.bundle
|
|
EOF
|
|
|
|
git clone --bundle-uri="$HTTPD_URL/bundle-list" \
|
|
clone-from clone-any-http 2>err &&
|
|
! grep "fatal" err &&
|
|
grep "warning: failed to download bundle from URI" err &&
|
|
|
|
git -C clone-from for-each-ref --format="%(objectname)" >oids &&
|
|
git -C clone-any-http cat-file --batch-check <oids &&
|
|
|
|
git -C clone-list-file for-each-ref --format="%(refname)" >refs &&
|
|
grep "refs/bundles/" refs >actual &&
|
|
cat >expect <<-\EOF &&
|
|
refs/bundles/base
|
|
refs/bundles/left
|
|
refs/bundles/merge
|
|
refs/bundles/right
|
|
EOF
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'clone bundle list (http, creationToken)' '
|
|
test_when_finished rm -f trace*.txt &&
|
|
|
|
cp clone-from/bundle-*.bundle "$HTTPD_DOCUMENT_ROOT_PATH/" &&
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
heuristic = creationToken
|
|
|
|
[bundle "bundle-1"]
|
|
uri = bundle-1.bundle
|
|
creationToken = 1
|
|
|
|
[bundle "bundle-2"]
|
|
uri = bundle-2.bundle
|
|
creationToken = 2
|
|
|
|
[bundle "bundle-3"]
|
|
uri = bundle-3.bundle
|
|
creationToken = 3
|
|
|
|
[bundle "bundle-4"]
|
|
uri = bundle-4.bundle
|
|
creationToken = 4
|
|
EOF
|
|
|
|
GIT_TRACE2_EVENT="$(pwd)/trace-clone.txt" git \
|
|
clone --bundle-uri="$HTTPD_URL/bundle-list" \
|
|
"$HTTPD_URL/smart/fetch.git" clone-list-http-2 &&
|
|
|
|
git -C clone-from for-each-ref --format="%(objectname)" >oids &&
|
|
git -C clone-list-http-2 cat-file --batch-check <oids &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/bundle-4.bundle
|
|
$HTTPD_URL/bundle-3.bundle
|
|
$HTTPD_URL/bundle-2.bundle
|
|
$HTTPD_URL/bundle-1.bundle
|
|
EOF
|
|
|
|
test_remote_https_urls <trace-clone.txt >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'clone incomplete bundle list (http, creationToken)' '
|
|
test_when_finished rm -f trace*.txt &&
|
|
|
|
cp clone-from/bundle-*.bundle "$HTTPD_DOCUMENT_ROOT_PATH/" &&
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
heuristic = creationToken
|
|
|
|
[bundle "bundle-1"]
|
|
uri = bundle-1.bundle
|
|
creationToken = 1
|
|
EOF
|
|
|
|
GIT_TRACE2_EVENT=$(pwd)/trace-clone.txt \
|
|
git clone --bundle-uri="$HTTPD_URL/bundle-list" \
|
|
--single-branch --branch=base --no-tags \
|
|
"$HTTPD_URL/smart/fetch.git" clone-token-http &&
|
|
|
|
test_cmp_config -C clone-token-http "$HTTPD_URL/bundle-list" fetch.bundleuri &&
|
|
test_cmp_config -C clone-token-http 1 fetch.bundlecreationtoken &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/bundle-1.bundle
|
|
EOF
|
|
|
|
test_remote_https_urls <trace-clone.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# We now have only one bundle ref.
|
|
git -C clone-token-http for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
|
|
cat >expect <<-\EOF &&
|
|
refs/bundles/base
|
|
EOF
|
|
test_cmp expect refs &&
|
|
|
|
# Add remaining bundles, exercising the "deepening" strategy
|
|
# for downloading via the creationToken heurisitc.
|
|
cat >>"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle "bundle-2"]
|
|
uri = bundle-2.bundle
|
|
creationToken = 2
|
|
|
|
[bundle "bundle-3"]
|
|
uri = bundle-3.bundle
|
|
creationToken = 3
|
|
|
|
[bundle "bundle-4"]
|
|
uri = bundle-4.bundle
|
|
creationToken = 4
|
|
EOF
|
|
|
|
GIT_TRACE2_EVENT="$(pwd)/trace1.txt" \
|
|
git -C clone-token-http fetch origin --no-tags \
|
|
refs/heads/merge:refs/heads/merge &&
|
|
test_cmp_config -C clone-token-http 4 fetch.bundlecreationtoken &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/bundle-4.bundle
|
|
$HTTPD_URL/bundle-3.bundle
|
|
$HTTPD_URL/bundle-2.bundle
|
|
EOF
|
|
|
|
test_remote_https_urls <trace1.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# We now have all bundle refs.
|
|
git -C clone-token-http for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
|
|
|
|
cat >expect <<-\EOF &&
|
|
refs/bundles/base
|
|
refs/bundles/left
|
|
refs/bundles/merge
|
|
refs/bundles/right
|
|
EOF
|
|
test_cmp expect refs
|
|
'
|
|
|
|
test_expect_success 'http clone with bundle.heuristic creates fetch.bundleURI' '
|
|
test_when_finished rm -rf fetch-http-4 trace*.txt &&
|
|
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
heuristic = creationToken
|
|
|
|
[bundle "bundle-1"]
|
|
uri = bundle-1.bundle
|
|
creationToken = 1
|
|
EOF
|
|
|
|
GIT_TRACE2_EVENT="$(pwd)/trace-clone.txt" \
|
|
git clone --single-branch --branch=base \
|
|
--bundle-uri="$HTTPD_URL/bundle-list" \
|
|
"$HTTPD_URL/smart/fetch.git" fetch-http-4 &&
|
|
|
|
test_cmp_config -C fetch-http-4 "$HTTPD_URL/bundle-list" fetch.bundleuri &&
|
|
test_cmp_config -C fetch-http-4 1 fetch.bundlecreationtoken &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/bundle-1.bundle
|
|
EOF
|
|
|
|
test_remote_https_urls <trace-clone.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# only received base ref from bundle-1
|
|
git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
|
|
cat >expect <<-\EOF &&
|
|
refs/bundles/base
|
|
EOF
|
|
test_cmp expect refs &&
|
|
|
|
cat >>"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle "bundle-2"]
|
|
uri = bundle-2.bundle
|
|
creationToken = 2
|
|
EOF
|
|
|
|
# Fetch the objects for bundle-2 _and_ bundle-3.
|
|
GIT_TRACE2_EVENT="$(pwd)/trace1.txt" \
|
|
git -C fetch-http-4 fetch origin --no-tags \
|
|
refs/heads/left:refs/heads/left \
|
|
refs/heads/right:refs/heads/right &&
|
|
test_cmp_config -C fetch-http-4 2 fetch.bundlecreationtoken &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/bundle-2.bundle
|
|
EOF
|
|
|
|
test_remote_https_urls <trace1.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# received left from bundle-2
|
|
git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
|
|
cat >expect <<-\EOF &&
|
|
refs/bundles/base
|
|
refs/bundles/left
|
|
EOF
|
|
test_cmp expect refs &&
|
|
|
|
# No-op fetch
|
|
GIT_TRACE2_EVENT="$(pwd)/trace1b.txt" \
|
|
git -C fetch-http-4 fetch origin --no-tags \
|
|
refs/heads/left:refs/heads/left \
|
|
refs/heads/right:refs/heads/right &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
EOF
|
|
test_remote_https_urls <trace1b.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
cat >>"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle "bundle-3"]
|
|
uri = bundle-3.bundle
|
|
creationToken = 3
|
|
|
|
[bundle "bundle-4"]
|
|
uri = bundle-4.bundle
|
|
creationToken = 4
|
|
EOF
|
|
|
|
# This fetch should skip bundle-3.bundle, since its objects are
|
|
# already local (we have the requisite commits for bundle-4.bundle).
|
|
GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
|
|
git -C fetch-http-4 fetch origin --no-tags \
|
|
refs/heads/merge:refs/heads/merge &&
|
|
test_cmp_config -C fetch-http-4 4 fetch.bundlecreationtoken &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/bundle-4.bundle
|
|
EOF
|
|
|
|
test_remote_https_urls <trace2.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# received merge ref from bundle-4, but right is missing
|
|
# because we did not download bundle-3.
|
|
git -C fetch-http-4 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
|
|
|
|
cat >expect <<-\EOF &&
|
|
refs/bundles/base
|
|
refs/bundles/left
|
|
refs/bundles/merge
|
|
EOF
|
|
test_cmp expect refs &&
|
|
|
|
# No-op fetch
|
|
GIT_TRACE2_EVENT="$(pwd)/trace2b.txt" \
|
|
git -C fetch-http-4 fetch origin &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
EOF
|
|
test_remote_https_urls <trace2b.txt >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'creationToken heuristic with failed downloads (clone)' '
|
|
test_when_finished rm -rf download-* trace*.txt &&
|
|
|
|
# Case 1: base bundle does not exist, nothing can unbundle
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
heuristic = creationToken
|
|
|
|
[bundle "bundle-1"]
|
|
uri = fake.bundle
|
|
creationToken = 1
|
|
|
|
[bundle "bundle-2"]
|
|
uri = bundle-2.bundle
|
|
creationToken = 2
|
|
|
|
[bundle "bundle-3"]
|
|
uri = bundle-3.bundle
|
|
creationToken = 3
|
|
|
|
[bundle "bundle-4"]
|
|
uri = bundle-4.bundle
|
|
creationToken = 4
|
|
EOF
|
|
|
|
GIT_TRACE2_EVENT="$(pwd)/trace-clone-1.txt" \
|
|
git clone --single-branch --branch=base \
|
|
--bundle-uri="$HTTPD_URL/bundle-list" \
|
|
"$HTTPD_URL/smart/fetch.git" download-1 &&
|
|
|
|
# Bundle failure does not set these configs.
|
|
test_must_fail git -C download-1 config fetch.bundleuri &&
|
|
test_must_fail git -C download-1 config fetch.bundlecreationtoken &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/bundle-4.bundle
|
|
$HTTPD_URL/bundle-3.bundle
|
|
$HTTPD_URL/bundle-2.bundle
|
|
$HTTPD_URL/fake.bundle
|
|
EOF
|
|
test_remote_https_urls <trace-clone-1.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# All bundles failed to unbundle
|
|
git -C download-1 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
|
|
test_must_be_empty refs &&
|
|
|
|
# Case 2: middle bundle does not exist, only two bundles can unbundle
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
heuristic = creationToken
|
|
|
|
[bundle "bundle-1"]
|
|
uri = bundle-1.bundle
|
|
creationToken = 1
|
|
|
|
[bundle "bundle-2"]
|
|
uri = fake.bundle
|
|
creationToken = 2
|
|
|
|
[bundle "bundle-3"]
|
|
uri = bundle-3.bundle
|
|
creationToken = 3
|
|
|
|
[bundle "bundle-4"]
|
|
uri = bundle-4.bundle
|
|
creationToken = 4
|
|
EOF
|
|
|
|
GIT_TRACE2_EVENT="$(pwd)/trace-clone-2.txt" \
|
|
git clone --single-branch --branch=base \
|
|
--bundle-uri="$HTTPD_URL/bundle-list" \
|
|
"$HTTPD_URL/smart/fetch.git" download-2 &&
|
|
|
|
# Bundle failure does not set these configs.
|
|
test_must_fail git -C download-2 config fetch.bundleuri &&
|
|
test_must_fail git -C download-2 config fetch.bundlecreationtoken &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/bundle-4.bundle
|
|
$HTTPD_URL/bundle-3.bundle
|
|
$HTTPD_URL/fake.bundle
|
|
$HTTPD_URL/bundle-1.bundle
|
|
EOF
|
|
test_remote_https_urls <trace-clone-2.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# bundle-1 and bundle-3 could unbundle, but bundle-4 could not
|
|
git -C download-2 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
|
|
cat >expect <<-EOF &&
|
|
refs/bundles/base
|
|
refs/bundles/right
|
|
EOF
|
|
test_cmp expect refs &&
|
|
|
|
# Case 3: top bundle does not exist, rest unbundle fine.
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
heuristic = creationToken
|
|
|
|
[bundle "bundle-1"]
|
|
uri = bundle-1.bundle
|
|
creationToken = 1
|
|
|
|
[bundle "bundle-2"]
|
|
uri = bundle-2.bundle
|
|
creationToken = 2
|
|
|
|
[bundle "bundle-3"]
|
|
uri = bundle-3.bundle
|
|
creationToken = 3
|
|
|
|
[bundle "bundle-4"]
|
|
uri = fake.bundle
|
|
creationToken = 4
|
|
EOF
|
|
|
|
GIT_TRACE2_EVENT="$(pwd)/trace-clone-3.txt" \
|
|
git clone --single-branch --branch=base \
|
|
--bundle-uri="$HTTPD_URL/bundle-list" \
|
|
"$HTTPD_URL/smart/fetch.git" download-3 &&
|
|
|
|
# As long as we have continguous successful downloads,
|
|
# we _do_ set these configs.
|
|
test_cmp_config -C download-3 "$HTTPD_URL/bundle-list" fetch.bundleuri &&
|
|
test_cmp_config -C download-3 3 fetch.bundlecreationtoken &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/fake.bundle
|
|
$HTTPD_URL/bundle-3.bundle
|
|
$HTTPD_URL/bundle-2.bundle
|
|
$HTTPD_URL/bundle-1.bundle
|
|
EOF
|
|
test_remote_https_urls <trace-clone-3.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# fake.bundle did not unbundle, but the others did.
|
|
git -C download-3 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
|
|
cat >expect <<-EOF &&
|
|
refs/bundles/base
|
|
refs/bundles/left
|
|
refs/bundles/right
|
|
EOF
|
|
test_cmp expect refs
|
|
'
|
|
|
|
# Expand the bundle list to include other interesting shapes, specifically
|
|
# interesting for use when fetching from a previous state.
|
|
#
|
|
# ---------------- bundle-7
|
|
# 7
|
|
# _/|\_
|
|
# ---/--|--\------ bundle-6
|
|
# 5 | 6
|
|
# --|---|---|----- bundle-4
|
|
# | 4 |
|
|
# | / \ /
|
|
# --|-|---|/------ bundle-3 (the client will be caught up to this point.)
|
|
# \ | 3
|
|
# ---\|---|------- bundle-2
|
|
# 2 |
|
|
# ----|---|------- bundle-1
|
|
# \ /
|
|
# 1
|
|
# |
|
|
# (previous commits)
|
|
test_expect_success 'expand incremental bundle list' '
|
|
(
|
|
cd clone-from &&
|
|
git checkout -b lefter left &&
|
|
test_commit 5 &&
|
|
git checkout -b righter right &&
|
|
test_commit 6 &&
|
|
git checkout -b top lefter &&
|
|
git merge -m "7" merge righter &&
|
|
|
|
git bundle create bundle-6.bundle lefter righter --not left right &&
|
|
git bundle create bundle-7.bundle top --not lefter merge righter &&
|
|
|
|
cp bundle-*.bundle "$HTTPD_DOCUMENT_ROOT_PATH/"
|
|
) &&
|
|
git -C "$HTTPD_DOCUMENT_ROOT_PATH/fetch.git" fetch origin +refs/heads/*:refs/heads/*
|
|
'
|
|
|
|
test_expect_success 'creationToken heuristic with failed downloads (fetch)' '
|
|
test_when_finished rm -rf download-* trace*.txt &&
|
|
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
heuristic = creationToken
|
|
|
|
[bundle "bundle-1"]
|
|
uri = bundle-1.bundle
|
|
creationToken = 1
|
|
|
|
[bundle "bundle-2"]
|
|
uri = bundle-2.bundle
|
|
creationToken = 2
|
|
|
|
[bundle "bundle-3"]
|
|
uri = bundle-3.bundle
|
|
creationToken = 3
|
|
EOF
|
|
|
|
git clone --single-branch --branch=left \
|
|
--bundle-uri="$HTTPD_URL/bundle-list" \
|
|
"$HTTPD_URL/smart/fetch.git" fetch-base &&
|
|
test_cmp_config -C fetch-base "$HTTPD_URL/bundle-list" fetch.bundleURI &&
|
|
test_cmp_config -C fetch-base 3 fetch.bundleCreationToken &&
|
|
|
|
# Case 1: all bundles exist: successful unbundling of all bundles
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
heuristic = creationToken
|
|
|
|
[bundle "bundle-1"]
|
|
uri = bundle-1.bundle
|
|
creationToken = 1
|
|
|
|
[bundle "bundle-2"]
|
|
uri = bundle-2.bundle
|
|
creationToken = 2
|
|
|
|
[bundle "bundle-3"]
|
|
uri = bundle-3.bundle
|
|
creationToken = 3
|
|
|
|
[bundle "bundle-4"]
|
|
uri = bundle-4.bundle
|
|
creationToken = 4
|
|
|
|
[bundle "bundle-6"]
|
|
uri = bundle-6.bundle
|
|
creationToken = 6
|
|
|
|
[bundle "bundle-7"]
|
|
uri = bundle-7.bundle
|
|
creationToken = 7
|
|
EOF
|
|
|
|
cp -r fetch-base fetch-1 &&
|
|
GIT_TRACE2_EVENT="$(pwd)/trace-fetch-1.txt" \
|
|
git -C fetch-1 fetch origin &&
|
|
test_cmp_config -C fetch-1 7 fetch.bundlecreationtoken &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/bundle-7.bundle
|
|
$HTTPD_URL/bundle-6.bundle
|
|
$HTTPD_URL/bundle-4.bundle
|
|
EOF
|
|
test_remote_https_urls <trace-fetch-1.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# Check which bundles have unbundled by refs
|
|
git -C fetch-1 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
|
|
cat >expect <<-EOF &&
|
|
refs/bundles/base
|
|
refs/bundles/left
|
|
refs/bundles/lefter
|
|
refs/bundles/merge
|
|
refs/bundles/right
|
|
refs/bundles/righter
|
|
refs/bundles/top
|
|
EOF
|
|
test_cmp expect refs &&
|
|
|
|
# Case 2: middle bundle does not exist, only bundle-4 can unbundle
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
heuristic = creationToken
|
|
|
|
[bundle "bundle-1"]
|
|
uri = bundle-1.bundle
|
|
creationToken = 1
|
|
|
|
[bundle "bundle-2"]
|
|
uri = bundle-2.bundle
|
|
creationToken = 2
|
|
|
|
[bundle "bundle-3"]
|
|
uri = bundle-3.bundle
|
|
creationToken = 3
|
|
|
|
[bundle "bundle-4"]
|
|
uri = bundle-4.bundle
|
|
creationToken = 4
|
|
|
|
[bundle "bundle-6"]
|
|
uri = fake.bundle
|
|
creationToken = 6
|
|
|
|
[bundle "bundle-7"]
|
|
uri = bundle-7.bundle
|
|
creationToken = 7
|
|
EOF
|
|
|
|
cp -r fetch-base fetch-2 &&
|
|
GIT_TRACE2_EVENT="$(pwd)/trace-fetch-2.txt" \
|
|
git -C fetch-2 fetch origin &&
|
|
|
|
# Since bundle-7 fails to unbundle, do not update creation token.
|
|
test_cmp_config -C fetch-2 3 fetch.bundlecreationtoken &&
|
|
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/bundle-7.bundle
|
|
$HTTPD_URL/fake.bundle
|
|
$HTTPD_URL/bundle-4.bundle
|
|
EOF
|
|
test_remote_https_urls <trace-fetch-2.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# Check which bundles have unbundled by refs
|
|
git -C fetch-2 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
|
|
cat >expect <<-EOF &&
|
|
refs/bundles/base
|
|
refs/bundles/left
|
|
refs/bundles/merge
|
|
refs/bundles/right
|
|
EOF
|
|
test_cmp expect refs &&
|
|
|
|
# Case 3: top bundle does not exist, rest unbundle fine.
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
heuristic = creationToken
|
|
|
|
[bundle "bundle-1"]
|
|
uri = bundle-1.bundle
|
|
creationToken = 1
|
|
|
|
[bundle "bundle-2"]
|
|
uri = bundle-2.bundle
|
|
creationToken = 2
|
|
|
|
[bundle "bundle-3"]
|
|
uri = bundle-3.bundle
|
|
creationToken = 3
|
|
|
|
[bundle "bundle-4"]
|
|
uri = bundle-4.bundle
|
|
creationToken = 4
|
|
|
|
[bundle "bundle-6"]
|
|
uri = bundle-6.bundle
|
|
creationToken = 6
|
|
|
|
[bundle "bundle-7"]
|
|
uri = fake.bundle
|
|
creationToken = 7
|
|
EOF
|
|
|
|
cp -r fetch-base fetch-3 &&
|
|
GIT_TRACE2_EVENT="$(pwd)/trace-fetch-3.txt" \
|
|
git -C fetch-3 fetch origin &&
|
|
|
|
# As long as we have continguous successful downloads,
|
|
# we _do_ set the maximum creation token.
|
|
test_cmp_config -C fetch-3 6 fetch.bundlecreationtoken &&
|
|
|
|
# NOTE: the fetch skips bundle-4 since bundle-6 successfully
|
|
# unbundles itself and bundle-7 failed to download.
|
|
cat >expect <<-EOF &&
|
|
$HTTPD_URL/bundle-list
|
|
$HTTPD_URL/fake.bundle
|
|
$HTTPD_URL/bundle-6.bundle
|
|
EOF
|
|
test_remote_https_urls <trace-fetch-3.txt >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# Check which bundles have unbundled by refs
|
|
git -C fetch-3 for-each-ref --format="%(refname)" "refs/bundles/*" >refs &&
|
|
cat >expect <<-EOF &&
|
|
refs/bundles/base
|
|
refs/bundles/left
|
|
refs/bundles/lefter
|
|
refs/bundles/right
|
|
refs/bundles/righter
|
|
EOF
|
|
test_cmp expect refs
|
|
'
|
|
|
|
test_expect_success 'bundles are downloaded once during fetch --all' '
|
|
test_when_finished rm -rf download-* trace*.txt fetch-mult &&
|
|
|
|
cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF &&
|
|
[bundle]
|
|
version = 1
|
|
mode = all
|
|
heuristic = creationToken
|
|
|
|
[bundle "bundle-1"]
|
|
uri = bundle-1.bundle
|
|
creationToken = 1
|
|
|
|
[bundle "bundle-2"]
|
|
uri = bundle-2.bundle
|
|
creationToken = 2
|
|
|
|
[bundle "bundle-3"]
|
|
uri = bundle-3.bundle
|
|
creationToken = 3
|
|
EOF
|
|
|
|
git clone --single-branch --branch=left \
|
|
--bundle-uri="$HTTPD_URL/bundle-list" \
|
|
"$HTTPD_URL/smart/fetch.git" fetch-mult &&
|
|
git -C fetch-mult remote add dup1 "$HTTPD_URL/smart/fetch.git" &&
|
|
git -C fetch-mult remote add dup2 "$HTTPD_URL/smart/fetch.git" &&
|
|
|
|
GIT_TRACE2_EVENT="$(pwd)/trace-mult.txt" \
|
|
git -C fetch-mult fetch --all &&
|
|
grep "\"child_start\".*\"git-remote-https\",\"$HTTPD_URL/bundle-list\"" \
|
|
trace-mult.txt >bundle-fetches &&
|
|
test_line_count = 1 bundle-fetches
|
|
'
|
|
# Do not add tests here unless they use the HTTP server, as they will
|
|
# not run unless the HTTP dependencies exist.
|
|
|
|
test_done
|