X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=connect.c;h=b157cf1cc718bbd7b8f4598b2dcb3a7ba92bb8e3;hb=031260064840e6e8c6bc36d7856a091ba80330c2;hp=a6657b13848b5474ffde7edb0ad60ed969f22852;hpb=f69714c38c6f3296a4bfba0d057e0f1605373f49;p=git.git diff --git a/connect.c b/connect.c index a6657b13..b157cf1c 100644 --- a/connect.c +++ b/connect.c @@ -82,15 +82,26 @@ int path_match(const char *path, int nr, char **match) 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; @@ -216,8 +227,10 @@ static int match_explicit_refs(struct ref *src, struct ref *dst, 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; } @@ -277,6 +290,8 @@ static enum protocol get_protocol(const char *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; @@ -333,6 +348,77 @@ static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path) 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. */ @@ -383,8 +469,10 @@ int git_connect(int fd[2], char *url, const char *prog) 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