summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2023-05-17 14:40:05 -0700
committerJunio C Hamano <gitster@pobox.com>2023-05-17 14:40:05 -0700
commitd320de7ee9e997b7a35b50916609e58acd5936d8 (patch)
tree595cc6e851f4087d589d30d7f01a707898213bbd
parentfa1900a383ff96d7dcd6ba7b37dcb773632dc655 (diff)
parent933e3a4ee205353d8f093d5dfcd226fa432c4e58 (diff)
downloadgit-next.tar.gz
Merge branch 'bc/clone-empty-repo-via-protocol-v0' into nextnext
* bc/clone-empty-repo-via-protocol-v0: upload-pack: advertise capabilities when cloning empty repos
-rwxr-xr-xt/t5551-http-fetch-smart.sh27
-rwxr-xr-xt/t5700-protocol-v1.sh31
-rw-r--r--upload-pack.c22
3 files changed, 73 insertions, 7 deletions
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 0908534f25..21b7767cbd 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -611,6 +611,33 @@ test_expect_success 'client falls back from v2 to v0 to match server' '
grep symref=HEAD:refs/heads/ trace
'
+test_expect_success 'create empty http-accessible SHA-256 repository' '
+ mkdir "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
+ (cd "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
+ git --bare init --object-format=sha256
+ )
+'
+
+test_expect_success 'clone empty SHA-256 repository with protocol v2' '
+ rm -fr sha256 &&
+ echo sha256 >expected &&
+ git -c protocol.version=2 clone "$HTTPD_URL/smart/sha256.git" &&
+ git -C sha256 rev-parse --show-object-format >actual &&
+ test_cmp actual expected &&
+ git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
+ test_must_be_empty actual
+'
+
+test_expect_success 'clone empty SHA-256 repository with protocol v0' '
+ rm -fr sha256 &&
+ echo sha256 >expected &&
+ GIT_TRACE=1 GIT_TRACE_PACKET=1 git -c protocol.version=0 clone "$HTTPD_URL/smart/sha256.git" &&
+ git -C sha256 rev-parse --show-object-format >actual &&
+ test_cmp actual expected &&
+ git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
+ test_must_be_empty actual
+'
+
test_expect_success 'passing hostname resolution information works' '
BOGUS_HOST=gitbogusexamplehost.invalid &&
BOGUS_HTTPD_URL=$HTTPD_PROTO://$BOGUS_HOST:$LIB_HTTPD_PORT &&
diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh
index 6c8d4c6cf1..a73b4d4ff6 100755
--- a/t/t5700-protocol-v1.sh
+++ b/t/t5700-protocol-v1.sh
@@ -244,15 +244,28 @@ test_expect_success 'push with ssh:// using protocol v1' '
grep "push< version 1" log
'
+test_expect_success 'clone propagates object-format from empty repo' '
+ test_when_finished "rm -fr src256 dst256" &&
+
+ echo sha256 >expect &&
+ git init --object-format=sha256 src256 &&
+ git clone --no-local src256 dst256 &&
+ git -C dst256 rev-parse --show-object-format >actual &&
+
+ test_cmp expect actual
+'
+
# Test protocol v1 with 'http://' transport
#
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
-test_expect_success 'create repo to be served by http:// transport' '
+test_expect_success 'create repos to be served by http:// transport' '
git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" config http.receivepack true &&
- test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one
+ test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one &&
+ git init --object-format=sha256 "$HTTPD_DOCUMENT_ROOT_PATH/sha256" &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/sha256" config http.receivepack true
'
test_expect_success 'clone with http:// using protocol v1' '
@@ -269,6 +282,20 @@ test_expect_success 'clone with http:// using protocol v1' '
grep "git< version 1" log
'
+test_expect_success 'clone with http:// using protocol v1 with empty SHA-256 repo' '
+ GIT_TRACE_PACKET=1 GIT_TRACE_CURL=1 git -c protocol.version=1 \
+ clone "$HTTPD_URL/smart/sha256" sha256 2>log &&
+
+ echo sha256 >expect &&
+ git -C sha256 rev-parse --show-object-format >actual &&
+ test_cmp expect actual &&
+
+ # Client requested to use protocol v1
+ grep "Git-Protocol: version=1" log &&
+ # Server responded using protocol v1
+ grep "git< version 1" log
+'
+
test_expect_success 'fetch with http:// using protocol v1' '
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two &&
diff --git a/upload-pack.c b/upload-pack.c
index 08633dc121..d3312006a3 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -120,6 +120,7 @@ struct upload_pack_data {
unsigned allow_ref_in_want : 1; /* v2 only */
unsigned allow_sideband_all : 1; /* v2 only */
unsigned advertise_sid : 1;
+ unsigned sent_capabilities : 1;
};
static void upload_pack_data_init(struct upload_pack_data *data)
@@ -1206,18 +1207,17 @@ static void format_session_id(struct strbuf *buf, struct upload_pack_data *d) {
strbuf_addf(buf, " session-id=%s", trace2_session_id());
}
-static int send_ref(const char *refname, const struct object_id *oid,
- int flag UNUSED, void *cb_data)
+static void write_v0_ref(struct upload_pack_data *data,
+ const char *refname, const char *refname_nons,
+ const struct object_id *oid)
{
static const char *capabilities = "multi_ack thin-pack side-band"
" side-band-64k ofs-delta shallow deepen-since deepen-not"
" deepen-relative no-progress include-tag multi_ack_detailed";
- const char *refname_nons = strip_namespace(refname);
struct object_id peeled;
- struct upload_pack_data *data = cb_data;
if (mark_our_ref(refname_nons, refname, oid, &data->hidden_refs))
- return 0;
+ return;
if (capabilities) {
struct strbuf symref_info = STRBUF_INIT;
@@ -1240,12 +1240,20 @@ static int send_ref(const char *refname, const struct object_id *oid,
git_user_agent_sanitized());
strbuf_release(&symref_info);
strbuf_release(&session_id);
+ data->sent_capabilities = 1;
} else {
packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(oid), refname_nons);
}
capabilities = NULL;
if (!peel_iterated_oid(oid, &peeled))
packet_fwrite_fmt(stdout, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
+ return;
+}
+
+static int send_ref(const char *refname, const struct object_id *oid,
+ int flag UNUSED, void *cb_data)
+{
+ write_v0_ref(cb_data, refname, strip_namespace(refname), oid);
return 0;
}
@@ -1379,6 +1387,10 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,
data.no_done = 1;
head_ref_namespaced(send_ref, &data);
for_each_namespaced_ref(send_ref, &data);
+ if (!data.sent_capabilities) {
+ const char *refname = "capabilities^{}";
+ write_v0_ref(&data, refname, refname, null_oid());
+ }
/*
* fflush stdout before calling advertise_shallow_grafts because send_ref
* uses stdio.