connect: treat generic proxy processes like ssh processes

The git_connect function returns two ends of a pipe for
talking with a remote, plus a struct child_process
representing the other end of the pipe. If we have a direct
socket connection, then this points to a special "no_fork"
child process.

The code path for doing git-over-pipes or git-over-ssh sets
up this child process to point to the child git command or
the ssh process. When we call finish_connect eventually, we
check wait() on the command and report its return value.

The code path for git://, on the other hand, always sets it
to no_fork. In the case of a direct TCP connection, this
makes sense; we have no child process. But in the case of a
proxy command (configured by core.gitproxy), we do have a
child process, but we throw away its pid, and therefore
ignore its return code.

Instead, let's keep that information in the proxy case, and
respect its return code, which can help catch some errors
(though depending on your proxy command, it will be errors
reported by the proxy command itself, and not propagated
from git commands. Still, it is probably better to propagate
such errors than to ignore them).

It also means that the child_process field can reliably be
used to determine whether the returned descriptors are
actually a full-duplex socket, which means we should be
using shutdown() instead of a simple close.

Signed-off-by: Jeff King <peff@peff.net>
Helped-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jeff King 2011-05-16 02:46:07 -04:00 committed by Junio C Hamano
parent 61432146ad
commit 5cbf8246d2

View File

@ -403,12 +403,12 @@ static int git_use_proxy(const char *host)
return (git_proxy_command && *git_proxy_command); return (git_proxy_command && *git_proxy_command);
} }
static void git_proxy_connect(int fd[2], char *host) static struct child_process *git_proxy_connect(int fd[2], char *host)
{ {
const char *port = STR(DEFAULT_GIT_PORT); const char *port = STR(DEFAULT_GIT_PORT);
char *colon, *end; char *colon, *end;
const char *argv[4]; const char **argv;
struct child_process proxy; struct child_process *proxy;
if (host[0] == '[') { if (host[0] == '[') {
end = strchr(host + 1, ']'); end = strchr(host + 1, ']');
@ -427,18 +427,20 @@ static void git_proxy_connect(int fd[2], char *host)
port = colon + 1; port = colon + 1;
} }
argv = xmalloc(sizeof(*argv) * 4);
argv[0] = git_proxy_command; argv[0] = git_proxy_command;
argv[1] = host; argv[1] = host;
argv[2] = port; argv[2] = port;
argv[3] = NULL; argv[3] = NULL;
memset(&proxy, 0, sizeof(proxy)); proxy = xcalloc(1, sizeof(*proxy));
proxy.argv = argv; proxy->argv = argv;
proxy.in = -1; proxy->in = -1;
proxy.out = -1; proxy->out = -1;
if (start_command(&proxy)) if (start_command(proxy))
die("cannot start proxy %s", argv[0]); die("cannot start proxy %s", argv[0]);
fd[0] = proxy.out; /* read from proxy stdout */ fd[0] = proxy->out; /* read from proxy stdout */
fd[1] = proxy.in; /* write to proxy stdin */ fd[1] = proxy->in; /* write to proxy stdin */
return proxy;
} }
#define MAX_CMD_LEN 1024 #define MAX_CMD_LEN 1024
@ -479,7 +481,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
char *host, *path; char *host, *path;
char *end; char *end;
int c; int c;
struct child_process *conn; struct child_process *conn = &no_fork;
enum protocol protocol = PROTO_LOCAL; enum protocol protocol = PROTO_LOCAL;
int free_path = 0; int free_path = 0;
char *port = NULL; char *port = NULL;
@ -553,7 +555,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
*/ */
char *target_host = xstrdup(host); char *target_host = xstrdup(host);
if (git_use_proxy(host)) if (git_use_proxy(host))
git_proxy_connect(fd, host); conn = git_proxy_connect(fd, host);
else else
git_tcp_connect(fd, host, flags); git_tcp_connect(fd, host, flags);
/* /*
@ -571,7 +573,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
free(url); free(url);
if (free_path) if (free_path)
free(path); free(path);
return &no_fork; return conn;
} }
conn = xcalloc(1, sizeof(*conn)); conn = xcalloc(1, sizeof(*conn));