Signed-off-by: Mike Hommey <mh@xxxxxxxxxxxx> --- connect.c | 54 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/connect.c b/connect.c index 4be06f4..0819c25 100644 --- a/connect.c +++ b/connect.c @@ -588,11 +588,13 @@ static char *get_port(char *host) * Extract protocol and relevant parts from the specified connection URL. * The caller must free() the returned strings. */ -static enum protocol parse_connect_url(const char *url_orig, char **ret_host, - char **ret_port, char **ret_path) +static enum protocol parse_connect_url(const char *url_orig, char **ret_user, + char **ret_host, char **ret_port, + char **ret_path) { char *url; char *host, *path; + const char *user = NULL; const char *port = NULL; char *end; int separator = '/'; @@ -650,23 +652,31 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host, get_host_and_port(&host, &port); - if (*host && !port) { + if (*host) { /* - * get_host_and_port does not return a port in the - * [host:port]:path case. In that case, it is called with - * "[host:port]" and returns "host:port" and NULL. - * To support this undocumented legacy we still need to split - * the port. - * "host:port" may also look like "user@host:port". As the - * `user` portion tends to be less strict than `host:port`, - * we first put it out of the equation: since a hostname - * cannot contain a '@', we start from the last '@' in the - * string. + * At this point, the host part may look like user@host:port. + * As the `user` portion tends to be less strict than + * `host:port`, we first put it out of the equation: since a + * hostname cannot contain a '@', we start from the last '@' + * in the string. */ char *end_user = strrchr(host, '@'); - port = get_port(end_user ? end_user : host); + if (end_user) { + *end_user = '\0'; + user = host; + host = end_user + 1; + } } + /* + * get_host_and_port does not return a port in the [host:port]:path + * case. In that case, it is called with "[host:port]" and returns + * "host:port" and NULL. + * To support this undocumented legacy we still need to split the port. + */ + if (!port) + port = get_port(host); + *ret_user = user ? xstrdup(user) : NULL; *ret_host = xstrdup(host); *ret_port = port ? xstrdup(port) : NULL; *ret_path = path; @@ -690,7 +700,7 @@ static struct child_process no_fork = CHILD_PROCESS_INIT; struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags) { - char *host, *port, *path; + char *user, *host, *port, *path; struct child_process *conn = &no_fork; enum protocol protocol; struct strbuf cmd = STRBUF_INIT; @@ -700,11 +710,14 @@ struct child_process *git_connect(int fd[2], const char *url, */ signal(SIGCHLD, SIG_DFL); - protocol = parse_connect_url(url, &host, &port, &path); + protocol = parse_connect_url(url, &user, &host, &port, &path); if (flags & CONNECT_DIAG_URL) { printf("Diag: url=%s\n", url ? url : "NULL"); printf("Diag: protocol=%s\n", prot_name(protocol)); - printf("Diag: userandhost=%s\n", host ? host : "NULL"); + if (user) + printf("Diag: userandhost=%s@%s\n", user, host); + else + printf("Diag: userandhost=%s\n", host ? host : "NULL"); printf("Diag: port=%s\n", port ? port : "NONE"); printf("Diag: path=%s\n", path ? path : "NULL"); conn = NULL; @@ -813,7 +826,11 @@ struct child_process *git_connect(int fd[2], const char *url, argv_array_push(&conn->args, putty ? "-P" : "-p"); argv_array_push(&conn->args, port); } - argv_array_push(&conn->args, host); + if (user) + argv_array_pushf(&conn->args, "%s@%s", + user, host); + else + argv_array_push(&conn->args, host); } else { transport_check_allowed("file"); } @@ -826,6 +843,7 @@ struct child_process *git_connect(int fd[2], const char *url, fd[1] = conn->in; /* write to child's stdin */ strbuf_release(&cmd); } + free(user); free(host); free(port); free(path); -- 2.8.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html