diff options
Diffstat (limited to 'connect.c')
-rw-r--r-- | connect.c | 110 |
1 files changed, 71 insertions, 39 deletions
@@ -9,6 +9,7 @@ #include "url.h" #include "string-list.h" #include "sha1-array.h" +#include "transport.h" static char *server_capabilities; static const char *parse_feature_value(const char *, const char *, int *); @@ -119,7 +120,7 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t src_len, *list = NULL; for (;;) { struct ref *ref; - unsigned char old_sha1[20]; + struct object_id old_oid; char *name; int len, name_len; char *buffer = packet_buffer; @@ -138,34 +139,36 @@ struct ref **get_remote_heads(int in, char *src_buf, size_t src_len, if (len > 4 && skip_prefix(buffer, "ERR ", &arg)) die("remote error: %s", arg); - if (len == 48 && skip_prefix(buffer, "shallow ", &arg)) { - if (get_sha1_hex(arg, old_sha1)) + if (len == GIT_SHA1_HEXSZ + strlen("shallow ") && + skip_prefix(buffer, "shallow ", &arg)) { + if (get_oid_hex(arg, &old_oid)) die("protocol error: expected shallow sha-1, got '%s'", arg); if (!shallow_points) die("repository on the other end cannot be shallow"); - sha1_array_append(shallow_points, old_sha1); + sha1_array_append(shallow_points, old_oid.hash); continue; } - if (len < 42 || get_sha1_hex(buffer, old_sha1) || buffer[40] != ' ') + if (len < GIT_SHA1_HEXSZ + 2 || get_oid_hex(buffer, &old_oid) || + buffer[GIT_SHA1_HEXSZ] != ' ') die("protocol error: expected sha/ref, got '%s'", buffer); - name = buffer + 41; + name = buffer + GIT_SHA1_HEXSZ + 1; name_len = strlen(name); - if (len != name_len + 41) { + if (len != name_len + GIT_SHA1_HEXSZ + 1) { free(server_capabilities); server_capabilities = xstrdup(name + name_len + 1); } if (extra_have && !strcmp(name, ".have")) { - sha1_array_append(extra_have, old_sha1); + sha1_array_append(extra_have, old_oid.hash); continue; } if (!check_ref(name, flags)) continue; - ref = alloc_ref(buffer + 41); - hashcpy(ref->old_sha1, old_sha1); + 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; @@ -254,7 +257,7 @@ static const char *prot_name(enum protocol protocol) case PROTO_GIT: return "git"; default: - return "unkown protocol"; + return "unknown protocol"; } } @@ -264,9 +267,9 @@ static enum protocol get_protocol(const char *name) return PROTO_SSH; if (!strcmp(name, "git")) return PROTO_GIT; - if (!strcmp(name, "git+ssh")) + if (!strcmp(name, "git+ssh")) /* deprecated - do not use */ return PROTO_SSH; - if (!strcmp(name, "ssh+git")) + if (!strcmp(name, "ssh+git")) /* deprecated - do not use */ return PROTO_SSH; if (!strcmp(name, "file")) return PROTO_FILE; @@ -332,7 +335,7 @@ static const char *ai_name(const struct addrinfo *ai) static char addr[NI_MAXHOST]; if (getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), NULL, 0, NI_NUMERICHOST) != 0) - strcpy(addr, "(unknown)"); + xsnprintf(addr, sizeof(addr), "(unknown)"); return addr; } @@ -354,6 +357,10 @@ static int git_tcp_connect_sock(char *host, int flags) port = "<none>"; memset(&hints, 0, sizeof(hints)); + if (flags & CONNECT_IPV4) + hints.ai_family = AF_INET; + else if (flags & CONNECT_IPV6) + hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; @@ -694,6 +701,8 @@ struct child_process *git_connect(int fd[2], const char *url, else target_host = xstrdup(hostandport); + transport_check_allowed("git"); + /* These underlying connection commands die() if they * cannot connect. */ @@ -721,12 +730,16 @@ struct child_process *git_connect(int fd[2], const char *url, strbuf_addch(&cmd, ' '); sq_quote_buf(&cmd, path); + /* remove repo-local variables from the environment */ + conn->env = local_repo_env; + conn->use_shell = 1; conn->in = conn->out = -1; if (protocol == PROTO_SSH) { const char *ssh; - int putty; + int putty = 0, tortoiseplink = 0; char *ssh_host = hostandport; const char *port = NULL; + transport_check_allowed("ssh"); get_host_and_port(&ssh_host, &port); if (!port) @@ -743,32 +756,51 @@ struct child_process *git_connect(int fd[2], const char *url, free(path); free(conn); return NULL; - } else { - ssh = getenv("GIT_SSH_COMMAND"); - if (ssh) { - conn->use_shell = 1; - putty = 0; - } else { - ssh = getenv("GIT_SSH"); - if (!ssh) - ssh = "ssh"; - putty = !!strcasestr(ssh, "plink"); - } - - argv_array_push(&conn->args, ssh); - if (putty && !strcasestr(ssh, "tortoiseplink")) - argv_array_push(&conn->args, "-batch"); - if (port) { - /* P is for PuTTY, p is for OpenSSH */ - argv_array_push(&conn->args, putty ? "-P" : "-p"); - argv_array_push(&conn->args, port); - } - argv_array_push(&conn->args, ssh_host); } + + ssh = getenv("GIT_SSH_COMMAND"); + if (!ssh) { + const char *base; + char *ssh_dup; + + /* + * GIT_SSH is the no-shell version of + * GIT_SSH_COMMAND (and must remain so for + * historical compatibility). + */ + conn->use_shell = 0; + + ssh = getenv("GIT_SSH"); + if (!ssh) + ssh = "ssh"; + + ssh_dup = xstrdup(ssh); + base = basename(ssh_dup); + + tortoiseplink = !strcasecmp(base, "tortoiseplink") || + !strcasecmp(base, "tortoiseplink.exe"); + putty = tortoiseplink || + !strcasecmp(base, "plink") || + !strcasecmp(base, "plink.exe"); + + free(ssh_dup); + } + + argv_array_push(&conn->args, ssh); + if (flags & CONNECT_IPV4) + argv_array_push(&conn->args, "-4"); + else if (flags & CONNECT_IPV6) + argv_array_push(&conn->args, "-6"); + if (tortoiseplink) + argv_array_push(&conn->args, "-batch"); + if (port) { + /* P is for PuTTY, p is for OpenSSH */ + argv_array_push(&conn->args, putty ? "-P" : "-p"); + argv_array_push(&conn->args, port); + } + argv_array_push(&conn->args, ssh_host); } else { - /* remove repo-local variables from the environment */ - conn->env = local_repo_env; - conn->use_shell = 1; + transport_check_allowed("file"); } argv_array_push(&conn->args, cmd.buf); |