summaryrefslogtreecommitdiff
path: root/connect.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2016-09-21 15:15:17 -0700
committerJunio C Hamano <gitster@pobox.com>2016-09-21 15:15:18 -0700
commit07d872434dbddef6c361fb77ed232081c35dfd6c (patch)
treed67f132eff5e84c6264c154fb1147ada05ff784f /connect.c
parentf6727b0509ec3417a5183ba6e658143275a734f5 (diff)
parenteb398797cdc97aae15419f5ac1316440936c31f1 (diff)
downloadgit-07d872434dbddef6c361fb77ed232081c35dfd6c.tar.gz
Merge branch 'jt/accept-capability-advertisement-when-fetching-from-void'
JGit can show a fake ref "capabilities^{}" to "git fetch" when it does not advertise any refs, but "git fetch" was not prepared to see such an advertisement. When the other side disconnects without giving any ref advertisement, we used to say "there may not be a repository at that URL", but we may have seen other advertisement like "shallow" and ".have" in which case we definitely know that a repository is there. The code to detect this case has also been updated. * jt/accept-capability-advertisement-when-fetching-from-void: connect: advertized capability is not a ref connect: tighten check for unexpected early hang up tests: move test_lazy_prereq JGIT to test-lib.sh
Diffstat (limited to 'connect.c')
-rw-r--r--connect.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/connect.c b/connect.c
index 722dc3fc54..7224b5ecc7 100644
--- a/connect.c
+++ b/connect.c
@@ -43,9 +43,9 @@ int check_ref_type(const struct ref *ref, int flags)
return check_ref(ref->name, flags);
}
-static void die_initial_contact(int got_at_least_one_head)
+static void die_initial_contact(int unexpected)
{
- if (got_at_least_one_head)
+ if (unexpected)
die("The remote end hung up upon initial contact");
else
die("Could not read from remote repository.\n\n"
@@ -115,10 +115,18 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t src_len,
struct sha1_array *shallow_points)
{
struct ref **orig_list = list;
- int got_at_least_one_head = 0;
+
+ /*
+ * A hang-up after seeing some response from the other end
+ * means that it is unexpected, as we know the other end is
+ * willing to talk to us. A hang-up before seeing any
+ * response does not necessarily mean an ACL problem, though.
+ */
+ int saw_response;
+ int got_dummy_ref_with_capabilities_declaration = 0;
*list = NULL;
- for (;;) {
+ for (saw_response = 0; ; saw_response = 1) {
struct ref *ref;
struct object_id old_oid;
char *name;
@@ -131,7 +139,7 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t src_len,
PACKET_READ_GENTLE_ON_EOF |
PACKET_READ_CHOMP_NEWLINE);
if (len < 0)
- die_initial_contact(got_at_least_one_head);
+ die_initial_contact(saw_response);
if (!len)
break;
@@ -165,13 +173,25 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t src_len,
continue;
}
+ if (!strcmp(name, "capabilities^{}")) {
+ if (saw_response)
+ die("protocol error: unexpected capabilities^{}");
+ if (got_dummy_ref_with_capabilities_declaration)
+ die("protocol error: multiple capabilities^{}");
+ got_dummy_ref_with_capabilities_declaration = 1;
+ continue;
+ }
+
if (!check_ref(name, flags))
continue;
+
+ if (got_dummy_ref_with_capabilities_declaration)
+ die("protocol error: unexpected ref after capabilities^{}");
+
ref = alloc_ref(buffer + GIT_SHA1_HEXSZ + 1);
oidcpy(&ref->old_oid, &old_oid);
*list = ref;
list = &ref->next;
- got_at_least_one_head = 1;
}
annotate_refs_with_symref_info(*orig_list);