Skip to content

Commit ac093d0

Browse files
bk2204gitster
authored andcommitted
remote-curl: detect algorithm for dumb HTTP by size
When reading the info/refs file for a repository, we have no explicit way to detect which hash algorithm is in use because the file doesn't provide one. Detect the hash algorithm in use by the size of the first object ID. If we have an empty repository, we don't know what the hash algorithm is on the remote side, so default to whatever the local side has configured. Without doing this, we cannot clone an empty repository since we don't know its hash algorithm. Test this case appropriately, since we currently have no tests for cloning an empty repository with the dumb HTTP protocol. We anonymize the URL like elsewhere in the function in case the user has decided to include a secret in the URL. Signed-off-by: brian m. carlson <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d96dab8 commit ac093d0

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

remote-curl.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,19 @@ static struct ref *parse_git_refs(struct discovery *heads, int for_push)
252252
return list;
253253
}
254254

255+
static const struct git_hash_algo *detect_hash_algo(struct discovery *heads)
256+
{
257+
const char *p = memchr(heads->buf, '\t', heads->len);
258+
int algo;
259+
if (!p)
260+
return the_hash_algo;
261+
262+
algo = hash_algo_by_length((p - heads->buf) / 2);
263+
if (algo == GIT_HASH_UNKNOWN)
264+
return NULL;
265+
return &hash_algos[algo];
266+
}
267+
255268
static struct ref *parse_info_refs(struct discovery *heads)
256269
{
257270
char *data, *start, *mid;
@@ -262,6 +275,12 @@ static struct ref *parse_info_refs(struct discovery *heads)
262275
struct ref *ref = NULL;
263276
struct ref *last_ref = NULL;
264277

278+
options.hash_algo = detect_hash_algo(heads);
279+
if (!options.hash_algo)
280+
die("%sinfo/refs not valid: could not determine hash algorithm; "
281+
"is this a git repository?",
282+
transport_anonymize_url(url.buf));
283+
265284
data = heads->buf;
266285
start = NULL;
267286
mid = data;
@@ -272,13 +291,13 @@ static struct ref *parse_info_refs(struct discovery *heads)
272291
if (data[i] == '\t')
273292
mid = &data[i];
274293
if (data[i] == '\n') {
275-
if (mid - start != the_hash_algo->hexsz)
294+
if (mid - start != options.hash_algo->hexsz)
276295
die(_("%sinfo/refs not valid: is this a git repository?"),
277296
transport_anonymize_url(url.buf));
278297
data[i] = 0;
279298
ref_name = mid + 1;
280299
ref = alloc_ref(ref_name);
281-
get_oid_hex(start, &ref->old_oid);
300+
get_oid_hex_algop(start, &ref->old_oid, options.hash_algo);
282301
if (!refs)
283302
refs = ref;
284303
if (last_ref)

t/t5550-http-fetch-dumb.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,24 @@ test_expect_success 'create password-protected repository' '
5050
"$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/repo.git"
5151
'
5252

53+
test_expect_success 'create empty remote repository' '
54+
git init --bare "$HTTPD_DOCUMENT_ROOT_PATH/empty.git" &&
55+
(cd "$HTTPD_DOCUMENT_ROOT_PATH/empty.git" &&
56+
mkdir -p hooks &&
57+
write_script "hooks/post-update" <<-\EOF &&
58+
exec git update-server-info
59+
EOF
60+
hooks/post-update
61+
)
62+
'
63+
64+
test_expect_success 'empty dumb HTTP repository has default hash algorithm' '
65+
test_when_finished "rm -fr clone-empty" &&
66+
git clone $HTTPD_URL/dumb/empty.git clone-empty &&
67+
git -C clone-empty rev-parse --show-object-format >empty-format &&
68+
test "$(cat empty-format)" = "$(test_oid algo)"
69+
'
70+
5371
setup_askpass_helper
5472

5573
test_expect_success 'cloning password-protected repository can fail' '

0 commit comments

Comments
 (0)