Skip to content

Commit 633390b

Browse files
committed
Merge branch 'bc/clone-empty-repo-via-protocol-v0'
The server side of "git clone" now advertises the necessary hints to clients to help them to clone from an empty repository and learn object hash algorithm and the (unborn) branch pointed at by HEAD, even over the older v0/v1 protocol. * bc/clone-empty-repo-via-protocol-v0: upload-pack: advertise capabilities when cloning empty repos
2 parents b04671b + 933e3a4 commit 633390b

File tree

3 files changed

+73
-7
lines changed

3 files changed

+73
-7
lines changed

t/t5551-http-fetch-smart.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,33 @@ test_expect_success 'client falls back from v2 to v0 to match server' '
611611
grep symref=HEAD:refs/heads/ trace
612612
'
613613

614+
test_expect_success 'create empty http-accessible SHA-256 repository' '
615+
mkdir "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
616+
(cd "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" &&
617+
git --bare init --object-format=sha256
618+
)
619+
'
620+
621+
test_expect_success 'clone empty SHA-256 repository with protocol v2' '
622+
rm -fr sha256 &&
623+
echo sha256 >expected &&
624+
git -c protocol.version=2 clone "$HTTPD_URL/smart/sha256.git" &&
625+
git -C sha256 rev-parse --show-object-format >actual &&
626+
test_cmp actual expected &&
627+
git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
628+
test_must_be_empty actual
629+
'
630+
631+
test_expect_success 'clone empty SHA-256 repository with protocol v0' '
632+
rm -fr sha256 &&
633+
echo sha256 >expected &&
634+
GIT_TRACE=1 GIT_TRACE_PACKET=1 git -c protocol.version=0 clone "$HTTPD_URL/smart/sha256.git" &&
635+
git -C sha256 rev-parse --show-object-format >actual &&
636+
test_cmp actual expected &&
637+
git ls-remote "$HTTPD_URL/smart/sha256.git" >actual &&
638+
test_must_be_empty actual
639+
'
640+
614641
test_expect_success 'passing hostname resolution information works' '
615642
BOGUS_HOST=gitbogusexamplehost.invalid &&
616643
BOGUS_HTTPD_URL=$HTTPD_PROTO://$BOGUS_HOST:$LIB_HTTPD_PORT &&

t/t5700-protocol-v1.sh

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,15 +244,28 @@ test_expect_success 'push with ssh:// using protocol v1' '
244244
grep "push< version 1" log
245245
'
246246

247+
test_expect_success 'clone propagates object-format from empty repo' '
248+
test_when_finished "rm -fr src256 dst256" &&
249+
250+
echo sha256 >expect &&
251+
git init --object-format=sha256 src256 &&
252+
git clone --no-local src256 dst256 &&
253+
git -C dst256 rev-parse --show-object-format >actual &&
254+
255+
test_cmp expect actual
256+
'
257+
247258
# Test protocol v1 with 'http://' transport
248259
#
249260
. "$TEST_DIRECTORY"/lib-httpd.sh
250261
start_httpd
251262

252-
test_expect_success 'create repo to be served by http:// transport' '
263+
test_expect_success 'create repos to be served by http:// transport' '
253264
git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" &&
254265
git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" config http.receivepack true &&
255-
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one
266+
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one &&
267+
git init --object-format=sha256 "$HTTPD_DOCUMENT_ROOT_PATH/sha256" &&
268+
git -C "$HTTPD_DOCUMENT_ROOT_PATH/sha256" config http.receivepack true
256269
'
257270

258271
test_expect_success 'clone with http:// using protocol v1' '
@@ -269,6 +282,20 @@ test_expect_success 'clone with http:// using protocol v1' '
269282
grep "git< version 1" log
270283
'
271284

285+
test_expect_success 'clone with http:// using protocol v1 with empty SHA-256 repo' '
286+
GIT_TRACE_PACKET=1 GIT_TRACE_CURL=1 git -c protocol.version=1 \
287+
clone "$HTTPD_URL/smart/sha256" sha256 2>log &&
288+
289+
echo sha256 >expect &&
290+
git -C sha256 rev-parse --show-object-format >actual &&
291+
test_cmp expect actual &&
292+
293+
# Client requested to use protocol v1
294+
grep "Git-Protocol: version=1" log &&
295+
# Server responded using protocol v1
296+
grep "git< version 1" log
297+
'
298+
272299
test_expect_success 'fetch with http:// using protocol v1' '
273300
test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two &&
274301

upload-pack.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ struct upload_pack_data {
120120
unsigned allow_ref_in_want : 1; /* v2 only */
121121
unsigned allow_sideband_all : 1; /* v2 only */
122122
unsigned advertise_sid : 1;
123+
unsigned sent_capabilities : 1;
123124
};
124125

125126
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) {
12061207
strbuf_addf(buf, " session-id=%s", trace2_session_id());
12071208
}
12081209

1209-
static int send_ref(const char *refname, const struct object_id *oid,
1210-
int flag UNUSED, void *cb_data)
1210+
static void write_v0_ref(struct upload_pack_data *data,
1211+
const char *refname, const char *refname_nons,
1212+
const struct object_id *oid)
12111213
{
12121214
static const char *capabilities = "multi_ack thin-pack side-band"
12131215
" side-band-64k ofs-delta shallow deepen-since deepen-not"
12141216
" deepen-relative no-progress include-tag multi_ack_detailed";
1215-
const char *refname_nons = strip_namespace(refname);
12161217
struct object_id peeled;
1217-
struct upload_pack_data *data = cb_data;
12181218

12191219
if (mark_our_ref(refname_nons, refname, oid, &data->hidden_refs))
1220-
return 0;
1220+
return;
12211221

12221222
if (capabilities) {
12231223
struct strbuf symref_info = STRBUF_INIT;
@@ -1240,12 +1240,20 @@ static int send_ref(const char *refname, const struct object_id *oid,
12401240
git_user_agent_sanitized());
12411241
strbuf_release(&symref_info);
12421242
strbuf_release(&session_id);
1243+
data->sent_capabilities = 1;
12431244
} else {
12441245
packet_fwrite_fmt(stdout, "%s %s\n", oid_to_hex(oid), refname_nons);
12451246
}
12461247
capabilities = NULL;
12471248
if (!peel_iterated_oid(oid, &peeled))
12481249
packet_fwrite_fmt(stdout, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
1250+
return;
1251+
}
1252+
1253+
static int send_ref(const char *refname, const struct object_id *oid,
1254+
int flag UNUSED, void *cb_data)
1255+
{
1256+
write_v0_ref(cb_data, refname, strip_namespace(refname), oid);
12491257
return 0;
12501258
}
12511259

@@ -1379,6 +1387,10 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,
13791387
data.no_done = 1;
13801388
head_ref_namespaced(send_ref, &data);
13811389
for_each_namespaced_ref(send_ref, &data);
1390+
if (!data.sent_capabilities) {
1391+
const char *refname = "capabilities^{}";
1392+
write_v0_ref(&data, refname, refname, null_oid());
1393+
}
13821394
/*
13831395
* fflush stdout before calling advertise_shallow_grafts because send_ref
13841396
* uses stdio.

0 commit comments

Comments
 (0)