summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerrick Stolee <derrickstolee@github.com>2022-12-22 15:14:17 (GMT)
committerJunio C Hamano <gitster@pobox.com>2022-12-25 07:24:24 (GMT)
commit876094ac16870727207e6afc0b26060101a52359 (patch)
tree54e5ac961903b138d57997670589c370c54590bb
parent12b0a14b9e5f140a9a4d5a3e3c47fae00a53c6fc (diff)
downloadgit-876094ac16870727207e6afc0b26060101a52359.zip
git-876094ac16870727207e6afc0b26060101a52359.tar.gz
git-876094ac16870727207e6afc0b26060101a52359.tar.bz2
clone: unbundle the advertised bundles
A previous change introduced the transport methods to acquire a bundle list from the 'bundle-uri' protocol v2 command, when advertised _and_ when the client has chosen to enable the feature. Teach Git to download and unbundle the data advertised by those bundles during 'git clone'. This takes place between the ref advertisement and the object data download, and stateful connections will linger while the client downloads bundles. In the future, we should consider closing the remote connection during this process. Also, since the --bundle-uri option exists, we do not want to mix the advertised bundles with the user-specified bundles. Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/clone.c25
-rw-r--r--t/lib-bundle-uri-protocol.sh21
-rwxr-xr-xt/t5601-clone.sh59
3 files changed, 98 insertions, 7 deletions
diff --git a/builtin/clone.c b/builtin/clone.c
index 5866873..430b2e9 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1271,11 +1271,26 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (refs)
mapped_refs = wanted_peer_refs(refs, &remote->fetch);
- /*
- * Populate transport->got_remote_bundle_uri and
- * transport->bundle_uri. We might get nothing.
- */
- transport_get_remote_bundle_uri(transport);
+ if (!bundle_uri) {
+ /*
+ * Populate transport->got_remote_bundle_uri and
+ * transport->bundle_uri. We might get nothing.
+ */
+ transport_get_remote_bundle_uri(transport);
+
+ if (transport->bundles &&
+ hashmap_get_size(&transport->bundles->bundles)) {
+ /* At this point, we need the_repository to match the cloned repo. */
+ if (repo_init(the_repository, git_dir, work_tree))
+ warning(_("failed to initialize the repo, skipping bundle URI"));
+ else if (fetch_bundle_list(the_repository,
+ transport->bundles))
+ warning(_("failed to fetch advertised bundles"));
+ } else {
+ clear_bundle_list(transport->bundles);
+ FREE_AND_NULL(transport->bundles);
+ }
+ }
if (mapped_refs) {
int hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
diff --git a/t/lib-bundle-uri-protocol.sh b/t/lib-bundle-uri-protocol.sh
index 3022ea4..a4a1af8 100644
--- a/t/lib-bundle-uri-protocol.sh
+++ b/t/lib-bundle-uri-protocol.sh
@@ -85,7 +85,7 @@ test_expect_success "connect with $BUNDLE_URI_PROTOCOL:// using protocol v2: hav
'
test_expect_success "clone with $BUNDLE_URI_PROTOCOL:// using protocol v2: request bundle-uris" '
- test_when_finished "rm -rf log cloned cloned2" &&
+ test_when_finished "rm -rf log* cloned*" &&
GIT_TRACE_PACKET="$PWD/log" \
git \
@@ -117,7 +117,24 @@ test_expect_success "clone with $BUNDLE_URI_PROTOCOL:// using protocol v2: reque
grep "< bundle-uri" log &&
# Client issued bundle-uri command
- grep "> command=bundle-uri" log
+ grep "> command=bundle-uri" log &&
+
+ GIT_TRACE_PACKET="$PWD/log3" \
+ git \
+ -c transfer.bundleURI=true \
+ -c protocol.version=2 \
+ clone --bundle-uri="$BUNDLE_URI_BUNDLE_URI" \
+ "$BUNDLE_URI_REPO_URI" cloned3 \
+ >actual 2>err &&
+
+ # Server responded using protocol v2
+ grep "< version 2" log3 &&
+
+ # Server advertised bundle-uri capability
+ grep "< bundle-uri" log3 &&
+
+ # Client did not issue bundle-uri command (--bundle-uri override)
+ ! grep "> command=bundle-uri" log3
'
# The remaining tests will all assume transfer.bundleURI=true
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index b2524a2..1928ea1 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -772,6 +772,65 @@ test_expect_success 'reject cloning shallow repository using HTTP' '
git clone --no-reject-shallow $HTTPD_URL/smart/repo.git repo
'
+test_expect_success 'auto-discover bundle URI from HTTP clone' '
+ test_when_finished rm -rf trace.txt repo2 "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" &&
+ git -C src bundle create "$HTTPD_DOCUMENT_ROOT_PATH/everything.bundle" --all &&
+ git clone --bare --no-local src "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" &&
+
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" config \
+ uploadpack.advertiseBundleURIs true &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" config \
+ bundle.version 1 &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" config \
+ bundle.mode all &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo2.git" config \
+ bundle.everything.uri "$HTTPD_URL/everything.bundle" &&
+
+ GIT_TRACE2_EVENT="$(pwd)/trace.txt" \
+ git -c protocol.version=2 \
+ -c transfer.bundleURI=true clone \
+ $HTTPD_URL/smart/repo2.git repo2 &&
+ cat >pattern <<-EOF &&
+ "event":"child_start".*"argv":\["git-remote-https","$HTTPD_URL/everything.bundle"\]
+ EOF
+ grep -f pattern trace.txt
+'
+
+test_expect_success 'auto-discover multiple bundles from HTTP clone' '
+ test_when_finished rm -rf trace.txt repo3 "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" &&
+
+ test_commit -C src new &&
+ git -C src bundle create "$HTTPD_DOCUMENT_ROOT_PATH/new.bundle" HEAD~1..HEAD &&
+ git clone --bare --no-local src "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" &&
+
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" config \
+ uploadpack.advertiseBundleURIs true &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" config \
+ bundle.version 1 &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" config \
+ bundle.mode all &&
+
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" config \
+ bundle.everything.uri "$HTTPD_URL/everything.bundle" &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo3.git" config \
+ bundle.new.uri "$HTTPD_URL/new.bundle" &&
+
+ GIT_TRACE2_EVENT="$(pwd)/trace.txt" \
+ git -c protocol.version=2 \
+ -c transfer.bundleURI=true clone \
+ $HTTPD_URL/smart/repo3.git repo3 &&
+
+ # We should fetch _both_ bundles
+ cat >pattern <<-EOF &&
+ "event":"child_start".*"argv":\["git-remote-https","$HTTPD_URL/everything.bundle"\]
+ EOF
+ grep -f pattern trace.txt &&
+ cat >pattern <<-EOF &&
+ "event":"child_start".*"argv":\["git-remote-https","$HTTPD_URL/new.bundle"\]
+ EOF
+ grep -f pattern trace.txt
+'
+
# DO NOT add non-httpd-specific tests here, because the last part of this
# test script is only executed when httpd is available and enabled.