struct refspec {
char *src;
char *dst;
+ char force;
};
+/*
+ * A:B means fast forward remote B with local A.
+ * +A:B means overwrite remote B with local A.
+ * +A is a shorthand for +A:A.
+ * A is a shorthand for A:A.
+ */
static struct refspec *parse_ref_spec(int nr_refspec, char **refspec)
{
int i;
- struct refspec *rs = xmalloc(sizeof(*rs) * (nr_refspec + 1));
+ struct refspec *rs = xcalloc(sizeof(*rs), (nr_refspec + 1));
for (i = 0; i < nr_refspec; i++) {
char *sp, *dp, *ep;
sp = refspec[i];
+ if (*sp == '+') {
+ rs[i].force = 1;
+ sp++;
+ }
ep = strchr(sp, ':');
if (ep) {
dp = ep + 1;
error("dst ref %s receives from more than one src.",
matched_dst->name);
}
- else
+ else {
matched_dst->peer_ref = matched_src;
+ matched_dst->force = rs[i].force;
+ }
}
return -errs;
}
return PROTO_SSH;
if (!strcmp(name, "git"))
return PROTO_GIT;
+ if (!strcmp(name, "git+ssh"))
+ return PROTO_SSH;
+ if (!strcmp(name, "ssh+git"))
+ return PROTO_SSH;
die("I don't handle protocol '%s'", name);
}
#define STR_(s) # s
#define STR(s) STR_(s)
+#ifndef NO_IPV6
+
static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
{
int sockfd = -1;
return 0;
}
+#else /* NO_IPV6 */
+
+static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
+{
+ int sockfd = -1;
+ char *colon, *end;
+ char *port = STR(DEFAULT_GIT_PORT), *ep;
+ struct hostent *he;
+ struct sockaddr_in sa;
+ char **ap;
+ unsigned int nport;
+
+ if (host[0] == '[') {
+ end = strchr(host + 1, ']');
+ if (end) {
+ *end = 0;
+ end++;
+ host++;
+ } else
+ end = host;
+ } else
+ end = host;
+ colon = strchr(end, ':');
+
+ if (colon) {
+ *colon = 0;
+ port = colon + 1;
+ }
+
+
+ he = gethostbyname(host);
+ if (!he)
+ die("Unable to look up %s (%s)", host, hstrerror(h_errno));
+ nport = strtoul(port, &ep, 10);
+ if ( ep == port || *ep ) {
+ /* Not numeric */
+ struct servent *se = getservbyname(port,"tcp");
+ if ( !se )
+ die("Unknown port %s\n", port);
+ nport = se->s_port;
+ }
+
+ for (ap = he->h_addr_list; *ap; ap++) {
+ sockfd = socket(he->h_addrtype, SOCK_STREAM, 0);
+ if (sockfd < 0)
+ continue;
+
+ memset(&sa, 0, sizeof sa);
+ sa.sin_family = he->h_addrtype;
+ sa.sin_port = htons(nport);
+ memcpy(&sa.sin_addr, ap, he->h_length);
+
+ if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
+ close(sockfd);
+ sockfd = -1;
+ continue;
+ }
+ break;
+ }
+
+ if (sockfd < 0)
+ die("unable to connect a socket (%s)", strerror(errno));
+
+ fd[0] = sockfd;
+ fd[1] = sockfd;
+ packet_write(sockfd, "%s %s\n", prog, path);
+ return 0;
+}
+
+#endif /* NO_IPV6 */
+
/*
* Yeah, yeah, fixme. Need to pass in the heads etc.
*/
close(pipefd[1][0]);
close(pipefd[1][1]);
if (protocol == PROTO_SSH) {
- const char *ssh = getenv("GIT_SSH") ? : "ssh";
- const char *ssh_basename = strrchr(ssh, '/');
+ const char *ssh, *ssh_basename;
+ ssh = getenv("GIT_SSH");
+ if (!ssh) ssh = "ssh";
+ ssh_basename = strrchr(ssh, '/');
if (!ssh_basename)
ssh_basename = ssh;
else