@matheusbsbs / matheus-bagliano / commits / ac093d0790
Fork 0

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 <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

brian m. carlson committed Jun 19, 2020 at 17:55 UTC ac093d0790cf9073e6cb03744b1d0fbc1e07d3f7
2 files changed +39 -2
remote-curl.c
+21 -2
@@ -252,6 +252,19 @@ static struct ref *parse_git_refs(struct discovery *heads, int for_push)
252 return list;
253 }
254
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 +
268 static struct ref *parse_info_refs(struct discovery *heads)
269 {
270 char *data, *start, *mid;
@@ -262,6 +275,12 @@ static struct ref *parse_info_refs(struct discovery *heads)
275 struct ref *ref = NULL;
276 struct ref *last_ref = NULL;
277
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 +
284 data = heads->buf;
285 start = NULL;
286 mid = data;
@@ -272,13 +291,13 @@ static struct ref *parse_info_refs(struct discovery *heads)
291 if (data[i] == '\t')
292 mid = &data[i];
293 if (data[i] == '\n') {
275 - if (mid - start != the_hash_algo->hexsz)
294 + if (mid - start != options.hash_algo->hexsz)
295 die(_("%sinfo/refs not valid: is this a git repository?"),
296 transport_anonymize_url(url.buf));
297 data[i] = 0;
298 ref_name = mid + 1;
299 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);
301 if (!refs)
302 refs = ref;
303 if (last_ref)
t/t5550-http-fetch-dumb.sh
+18
@@ -50,6 +50,24 @@ test_expect_success 'create password-protected repository' '
50 "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/repo.git"
51 '
52
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 +
71 setup_askpass_helper
72
73 test_expect_success 'cloning password-protected repository can fail' '