diff options
Diffstat (limited to 'connect.c')
-rw-r--r-- | connect.c | 47 |
1 files changed, 40 insertions, 7 deletions
@@ -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); @@ -658,6 +678,19 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host, static struct child_process no_fork = CHILD_PROCESS_INIT; +static const char *get_ssh_command(void) +{ + const char *ssh; + + if ((ssh = getenv("GIT_SSH_COMMAND"))) + return ssh; + + if (!git_config_get_string_const("core.sshcommand", &ssh)) + return ssh; + + return NULL; +} + /* * This returns a dummy child_process if the transport protocol does not * need fork(2), or a struct child_process object if it does. Once done, @@ -758,7 +791,7 @@ struct child_process *git_connect(int fd[2], const char *url, return NULL; } - ssh = getenv("GIT_SSH_COMMAND"); + ssh = get_ssh_command(); if (!ssh) { const char *base; char *ssh_dup; |