continue;
if (nr_match && !path_match(name, nr_match, match))
continue;
- ref = xcalloc(1, sizeof(*ref) + len - 40);
+ ref = alloc_ref(len - 40);
hashcpy(ref->old_sha1, old_sha1);
memcpy(ref->name, buffer + 41, len - 40);
*list = ref;
return PROTO_SSH;
if (!strcmp(name, "ssh+git"))
return PROTO_SSH;
+ if (!strcmp(name, "file"))
+ return PROTO_LOCAL;
die("I don't handle protocol '%s'", name);
}
#ifndef NO_IPV6
+static const char *ai_name(const struct addrinfo *ai)
+{
+ static char addr[INET_ADDRSTRLEN];
+ if ( AF_INET == ai->ai_family ) {
+ struct sockaddr_in *in;
+ in = (struct sockaddr_in *)ai->ai_addr;
+ inet_ntop(ai->ai_family, &in->sin_addr, addr, sizeof(addr));
+ } else if ( AF_INET6 == ai->ai_family ) {
+ struct sockaddr_in6 *in;
+ in = (struct sockaddr_in6 *)ai->ai_addr;
+ inet_ntop(ai->ai_family, &in->sin6_addr, addr, sizeof(addr));
+ } else {
+ strcpy(addr, "(unknown)");
+ }
+ return addr;
+}
+
/*
* Returns a connected socket() fd, or else die()s.
*/
const char *port = STR(DEFAULT_GIT_PORT);
struct addrinfo hints, *ai0, *ai;
int gai;
+ int cnt = 0;
if (host[0] == '[') {
end = strchr(host + 1, ']');
}
if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
saved_errno = errno;
+ fprintf(stderr, "%s[%d: %s]: errno=%s\n",
+ host,
+ cnt,
+ ai_name(ai),
+ strerror(saved_errno));
close(sockfd);
sockfd = -1;
continue;
}
+ if (flags & CONNECT_VERBOSE)
+ fprintf(stderr, "%s ", ai_name(ai));
break;
}
struct sockaddr_in sa;
char **ap;
unsigned int nport;
+ int cnt;
if (host[0] == '[') {
end = strchr(host + 1, ']');
if (flags & CONNECT_VERBOSE)
fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);
- for (ap = he->h_addr_list; *ap; ap++) {
+ for (cnt = 0, ap = he->h_addr_list; *ap; ap++, cnt++) {
sockfd = socket(he->h_addrtype, SOCK_STREAM, 0);
if (sockfd < 0) {
saved_errno = errno;
if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
saved_errno = errno;
+ fprintf(stderr, "%s[%d: %s]: errno=%s\n",
+ host,
+ cnt,
+ inet_ntoa(*(struct in_addr *)&sa.sin_addr),
+ strerror(saved_errno));
close(sockfd);
sockfd = -1;
continue;
}
+ if (flags & CONNECT_VERBOSE)
+ fprintf(stderr, "%s ",
+ inet_ntoa(*(struct in_addr *)&sa.sin_addr));
break;
}
}
if (0 <= matchlen) {
/* core.gitproxy = none for kernel.org */
- if (matchlen == 4 &&
+ if (matchlen == 4 &&
!memcmp(value, "none", 4))
matchlen = 0;
git_proxy_command = xmalloc(matchlen + 1);
#define MAX_CMD_LEN 1024
+char *get_port(char *host)
+{
+ char *end;
+ char *p = strchr(host, ':');
+
+ if (p) {
+ strtol(p+1, &end, 10);
+ if (*end == '\0') {
+ *p = '\0';
+ return p+1;
+ }
+ }
+
+ return NULL;
+}
+
/*
* This returns 0 if the transport protocol does not need fork(2),
* or a process id if it does. Once done, finish the connection
pid_t pid;
enum protocol protocol = PROTO_LOCAL;
int free_path = 0;
+ char *port = NULL;
/* Without this we cannot rely on waitpid() to tell
* what happened to our children.
end = host;
path = strchr(end, c);
- if (c == ':') {
- if (path) {
+ if (path) {
+ if (c == ':') {
protocol = PROTO_SSH;
*path++ = '\0';
- } else
- path = host;
- }
+ }
+ } else
+ path = end;
if (!path || !*path)
die("No path specified. See 'man git-pull' for valid url syntax");
*ptr = '\0';
}
+ /*
+ * Add support for ssh port: ssh://host.xy:<port>/...
+ */
+ if (protocol == PROTO_SSH && host != url)
+ port = get_port(host);
+
if (protocol == PROTO_GIT) {
/* These underlying connection commands die() if they
* cannot connect.
ssh_basename = ssh;
else
ssh_basename++;
- execlp(ssh, ssh_basename, host, command, NULL);
+
+ if (!port)
+ execlp(ssh, ssh_basename, host, command, NULL);
+ else
+ execlp(ssh, ssh_basename, "-p", port, host,
+ command, NULL);
}
else {
unsetenv(ALTERNATE_DB_ENVIRONMENT);
unsetenv(DB_ENVIRONMENT);
unsetenv(GIT_DIR_ENVIRONMENT);
+ unsetenv(GIT_WORK_TREE_ENVIRONMENT);
unsetenv(GRAFT_ENVIRONMENT);
unsetenv(INDEX_ENVIRONMENT);
execlp("sh", "sh", "-c", command, NULL);