mirror of
https://github.com/git/git.git
synced 2024-05-24 04:56:09 +02:00
remote-curl: fix parsing of detached SHA256 heads
The dumb HTTP transport tries to read the remote HEAD reference by downloading the "HEAD" file and then parsing it via `http_fetch_ref()`. This function will either parse the file as an object ID in case it is exactly `the_hash_algo->hexsz` long, or otherwise it will check whether the reference starts with "ref :" and parse it as a symbolic ref. This is broken when parsing detached HEADs of a remote SHA256 repository because we never update `the_hash_algo` to the discovered remote object hash. Consequently, `the_hash_algo` will always be the fallback SHA1 hash algorithm, which will cause us to fail parsing HEAD altogteher when it contains a SHA256 object ID. Fix this issue by setting up `the_hash_algo` via `repo_set_hash_algo()`. While at it, let's make the expected SHA1 fallback explicit in our code, which also addresses an upcoming issue where we are going to remove the SHA1 fallback for `the_hash_algo`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
813f17fd6b
commit
bd455cec37
|
@ -266,12 +266,23 @@ static struct ref *parse_git_refs(struct discovery *heads, int for_push)
|
|||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to detect the hash algorithm used by the remote repository when using
|
||||
* the dumb HTTP transport. As dumb transports cannot tell us the object hash
|
||||
* directly have to derive it from the advertised ref lengths.
|
||||
*/
|
||||
static const struct git_hash_algo *detect_hash_algo(struct discovery *heads)
|
||||
{
|
||||
const char *p = memchr(heads->buf, '\t', heads->len);
|
||||
int algo;
|
||||
|
||||
/*
|
||||
* In case the remote has no refs we have no way to reliably determine
|
||||
* the object hash used by that repository. In that case we simply fall
|
||||
* back to SHA1, which may or may not be correct.
|
||||
*/
|
||||
if (!p)
|
||||
return the_hash_algo;
|
||||
return &hash_algos[GIT_HASH_SHA1];
|
||||
|
||||
algo = hash_algo_by_length((p - heads->buf) / 2);
|
||||
if (algo == GIT_HASH_UNKNOWN)
|
||||
|
@ -295,6 +306,12 @@ static struct ref *parse_info_refs(struct discovery *heads)
|
|||
"is this a git repository?",
|
||||
transport_anonymize_url(url.buf));
|
||||
|
||||
/*
|
||||
* Set the repository's hash algo to whatever we have just detected.
|
||||
* This ensures that we can correctly parse the remote references.
|
||||
*/
|
||||
repo_set_hash_algo(the_repository, hash_algo_by_ptr(options.hash_algo));
|
||||
|
||||
data = heads->buf;
|
||||
start = NULL;
|
||||
mid = data;
|
||||
|
|
|
@ -55,6 +55,21 @@ test_expect_success 'list refs from outside any repository' '
|
|||
test_cmp expect actual
|
||||
'
|
||||
|
||||
|
||||
test_expect_success 'list detached HEAD from outside any repository' '
|
||||
git clone --mirror "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
|
||||
"$HTTPD_DOCUMENT_ROOT_PATH/repo-detached.git" &&
|
||||
git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo-detached.git" \
|
||||
update-ref --no-deref HEAD refs/heads/main &&
|
||||
git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo-detached.git" update-server-info &&
|
||||
cat >expect <<-EOF &&
|
||||
$(git rev-parse main) HEAD
|
||||
$(git rev-parse main) refs/heads/main
|
||||
EOF
|
||||
nongit git ls-remote "$HTTPD_URL/dumb/repo-detached.git" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'create password-protected repository' '
|
||||
mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/" &&
|
||||
cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
|
||||
|
|
Loading…
Reference in New Issue