blob: 4150412e2c0ebf6129137baf41c9d268d50c60bd [file] [log] [blame]
Jason Riedy731043f2006-01-25 12:38:36 -08001#include "git-compat-util.h"
Linus Torvaldsf7192592005-07-04 11:57:58 -07002#include "cache.h"
Linus Torvalds41cb7482005-07-05 15:44:09 -07003#include "pkt-line.h"
Junio C Hamanob10d0ec2005-07-08 00:02:52 -07004#include "quote.h"
Junio C Hamano6abf5c02005-10-16 00:25:26 -07005#include "refs.h"
Shawn O. Pearce15a1c0122007-03-12 19:00:19 -04006#include "run-command.h"
Daniel Barkalow6b628162007-05-12 11:45:59 -04007#include "remote.h"
Junio C Hamano47a59182013-07-08 13:56:53 -07008#include "connect.h"
Jeff King9d2e9422010-05-23 05:19:44 -04009#include "url.h"
Junio C Hamanoa45b5f02013-09-17 19:10:31 -070010#include "string-list.h"
Nguyễn Thái Ngọc Duy13eb4622013-12-05 20:02:29 +070011#include "sha1-array.h"
Linus Torvaldsf7192592005-07-04 11:57:58 -070012
David Rientjes96f1e582006-08-15 10:23:48 -070013static char *server_capabilities;
Junio C Hamano5d54cff2013-09-17 16:29:28 -070014static const char *parse_feature_value(const char *, const char *, int *);
Johannes Schindelin211b5f92005-10-28 04:48:54 +020015
Linus Torvalds2718ff02006-07-04 12:29:10 -070016static int check_ref(const char *name, int len, unsigned int flags)
17{
18 if (!flags)
19 return 1;
20
Andy Whitcroftc41e20b2006-09-05 20:00:17 +010021 if (len < 5 || memcmp(name, "refs/", 5))
Linus Torvalds2718ff02006-07-04 12:29:10 -070022 return 0;
23
24 /* Skip the "refs/" part */
25 name += 5;
26 len -= 5;
27
28 /* REF_NORMAL means that we don't want the magic fake tag refs */
Michael Haggerty8d9c5012011-09-15 23:10:25 +020029 if ((flags & REF_NORMAL) && check_refname_format(name, 0))
Linus Torvalds2718ff02006-07-04 12:29:10 -070030 return 0;
31
32 /* REF_HEADS means that we want regular branch heads */
33 if ((flags & REF_HEADS) && !memcmp(name, "heads/", 6))
34 return 1;
35
36 /* REF_TAGS means that we want tags */
37 if ((flags & REF_TAGS) && !memcmp(name, "tags/", 5))
38 return 1;
39
40 /* All type bits clear means that we are ok with anything */
41 return !(flags & ~REF_NORMAL);
42}
43
Daniel Barkalow45773702007-10-29 21:05:40 -040044int check_ref_type(const struct ref *ref, int flags)
45{
46 return check_ref(ref->name, strlen(ref->name), flags);
47}
48
Heiko Voigt46284dd2012-06-19 20:24:50 +020049static void die_initial_contact(int got_at_least_one_head)
50{
51 if (got_at_least_one_head)
52 die("The remote end hung up upon initial contact");
53 else
54 die("Could not read from remote repository.\n\n"
55 "Please make sure you have the correct access rights\n"
56 "and the repository exists.");
57}
58
Junio C Hamanoa45b5f02013-09-17 19:10:31 -070059static void parse_one_symref_info(struct string_list *symref, const char *val, int len)
60{
61 char *sym, *target;
62 struct string_list_item *item;
63
64 if (!len)
65 return; /* just "symref" */
66 /* e.g. "symref=HEAD:refs/heads/master" */
67 sym = xmalloc(len + 1);
68 memcpy(sym, val, len);
69 sym[len] = '\0';
70 target = strchr(sym, ':');
71 if (!target)
72 /* just "symref=something" */
73 goto reject;
74 *(target++) = '\0';
75 if (check_refname_format(sym, REFNAME_ALLOW_ONELEVEL) ||
76 check_refname_format(target, REFNAME_ALLOW_ONELEVEL))
77 /* "symref=bogus:pair */
78 goto reject;
79 item = string_list_append(symref, sym);
80 item->util = target;
81 return;
82reject:
83 free(sym);
84 return;
85}
86
87static void annotate_refs_with_symref_info(struct ref *ref)
88{
89 struct string_list symref = STRING_LIST_INIT_DUP;
90 const char *feature_list = server_capabilities;
91
92 while (feature_list) {
93 int len;
94 const char *val;
95
96 val = parse_feature_value(feature_list, "symref", &len);
97 if (!val)
98 break;
99 parse_one_symref_info(&symref, val, len);
100 feature_list = val + 1;
101 }
102 sort_string_list(&symref);
103
104 for (; ref; ref = ref->next) {
105 struct string_list_item *item;
106 item = string_list_lookup(&symref, ref->name);
107 if (!item)
108 continue;
109 ref->symref = xstrdup((char *)item->util);
110 }
111 string_list_clear(&symref, 0);
112}
113
Linus Torvaldsd1c133f2005-07-16 13:55:50 -0700114/*
115 * Read all the refs from the other end
116 */
Jeff King85edf4f2013-02-20 15:06:45 -0500117struct ref **get_remote_heads(int in, char *src_buf, size_t src_len,
118 struct ref **list, unsigned int flags,
Nguyễn Thái Ngọc Duyb06dcd72013-12-05 20:02:33 +0700119 struct sha1_array *extra_have,
120 struct sha1_array *shallow_points)
Linus Torvaldsd1c133f2005-07-16 13:55:50 -0700121{
Junio C Hamanoa45b5f02013-09-17 19:10:31 -0700122 struct ref **orig_list = list;
Heiko Voigt46284dd2012-06-19 20:24:50 +0200123 int got_at_least_one_head = 0;
124
Linus Torvaldsd1c133f2005-07-16 13:55:50 -0700125 *list = NULL;
126 for (;;) {
127 struct ref *ref;
128 unsigned char old_sha1[20];
Linus Torvaldsd1c133f2005-07-16 13:55:50 -0700129 char *name;
Johannes Schindelin211b5f92005-10-28 04:48:54 +0200130 int len, name_len;
Jeff King74543a02013-02-20 15:02:57 -0500131 char *buffer = packet_buffer;
Linus Torvaldsd1c133f2005-07-16 13:55:50 -0700132
Jeff King85edf4f2013-02-20 15:06:45 -0500133 len = packet_read(in, &src_buf, &src_len,
Jeff King4981fe72013-02-23 17:31:34 -0500134 packet_buffer, sizeof(packet_buffer),
Jeff King819b9292013-02-20 15:02:28 -0500135 PACKET_READ_GENTLE_ON_EOF |
136 PACKET_READ_CHOMP_NEWLINE);
Heiko Voigt46284dd2012-06-19 20:24:50 +0200137 if (len < 0)
138 die_initial_contact(got_at_least_one_head);
139
Linus Torvaldsd1c133f2005-07-16 13:55:50 -0700140 if (!len)
141 break;
Linus Torvaldsd1c133f2005-07-16 13:55:50 -0700142
Christian Couder59556542013-11-30 21:55:40 +0100143 if (len > 4 && starts_with(buffer, "ERR "))
Tom Preston-Wernera8073282008-11-01 11:44:45 -0700144 die("remote error: %s", buffer + 4);
145
Junio C Hamano92251b12014-01-17 12:21:14 -0800146 if (len == 48 && starts_with(buffer, "shallow ")) {
Nguyễn Thái Ngọc Duyb06dcd72013-12-05 20:02:33 +0700147 if (get_sha1_hex(buffer + 8, old_sha1))
148 die("protocol error: expected shallow sha-1, got '%s'", buffer + 8);
149 if (!shallow_points)
150 die("repository on the other end cannot be shallow");
151 sha1_array_append(shallow_points, old_sha1);
152 continue;
153 }
154
Linus Torvaldsd1c133f2005-07-16 13:55:50 -0700155 if (len < 42 || get_sha1_hex(buffer, old_sha1) || buffer[40] != ' ')
156 die("protocol error: expected sha/ref, got '%s'", buffer);
157 name = buffer + 41;
Junio C Hamano1a7141f2005-10-13 18:57:40 -0700158
Johannes Schindelin211b5f92005-10-28 04:48:54 +0200159 name_len = strlen(name);
160 if (len != name_len + 41) {
Jim Meyering8e0f7002008-01-31 18:26:32 +0100161 free(server_capabilities);
Shawn Pearce9befac42006-09-02 00:16:31 -0400162 server_capabilities = xstrdup(name + name_len + 1);
Johannes Schindelin211b5f92005-10-28 04:48:54 +0200163 }
164
Junio C Hamano40c155f2008-09-09 01:27:09 -0700165 if (extra_have &&
166 name_len == 5 && !memcmp(".have", name, 5)) {
Nguyễn Thái Ngọc Duy13eb4622013-12-05 20:02:29 +0700167 sha1_array_append(extra_have, old_sha1);
Junio C Hamano40c155f2008-09-09 01:27:09 -0700168 continue;
169 }
170
Linus Torvalds2718ff02006-07-04 12:29:10 -0700171 if (!check_ref(name, name_len, flags))
Junio C Hamanocfee10a2005-12-25 23:18:37 -0800172 continue;
René Scharfe59c69c02008-10-18 10:44:18 +0200173 ref = alloc_ref(buffer + 41);
Shawn Pearcee7024962006-08-23 02:49:00 -0400174 hashcpy(ref->old_sha1, old_sha1);
Linus Torvaldsd1c133f2005-07-16 13:55:50 -0700175 *list = ref;
176 list = &ref->next;
Heiko Voigt46284dd2012-06-19 20:24:50 +0200177 got_at_least_one_head = 1;
Linus Torvaldsd1c133f2005-07-16 13:55:50 -0700178 }
Junio C Hamanoa45b5f02013-09-17 19:10:31 -0700179
180 annotate_refs_with_symref_info(*orig_list);
181
Linus Torvaldsd1c133f2005-07-16 13:55:50 -0700182 return list;
183}
184
Junio C Hamano5d54cff2013-09-17 16:29:28 -0700185static const char *parse_feature_value(const char *feature_list, const char *feature, int *lenp)
Junio C Hamanof47182c2012-01-08 22:06:19 +0100186{
187 int len;
188
189 if (!feature_list)
190 return NULL;
191
192 len = strlen(feature);
193 while (*feature_list) {
194 const char *found = strstr(feature_list, feature);
195 if (!found)
196 return NULL;
Jeff King94427102012-08-13 21:59:27 -0400197 if (feature_list == found || isspace(found[-1])) {
198 const char *value = found + len;
199 /* feature with no value (e.g., "thin-pack") */
200 if (!*value || isspace(*value)) {
201 if (lenp)
202 *lenp = 0;
203 return value;
204 }
205 /* feature with a value (e.g., "agent=git/1.2.3") */
206 else if (*value == '=') {
207 value++;
208 if (lenp)
209 *lenp = strcspn(value, " \t\n");
210 return value;
211 }
212 /*
213 * otherwise we matched a substring of another feature;
214 * keep looking
215 */
216 }
Junio C Hamanof47182c2012-01-08 22:06:19 +0100217 feature_list = found + 1;
218 }
219 return NULL;
Johannes Schindelin211b5f92005-10-28 04:48:54 +0200220}
221
Jeff King94427102012-08-13 21:59:27 -0400222int parse_feature_request(const char *feature_list, const char *feature)
223{
224 return !!parse_feature_value(feature_list, feature, NULL);
225}
226
227const char *server_feature_value(const char *feature, int *len)
228{
229 return parse_feature_value(server_capabilities, feature, len);
230}
231
232int server_supports(const char *feature)
233{
234 return !!server_feature_value(feature, NULL);
235}
236
Linus Torvalds2386d652005-07-13 18:46:20 -0700237enum protocol {
238 PROTO_LOCAL = 1,
Torsten Bögershausenc59ab2e2013-11-28 20:50:03 +0100239 PROTO_FILE,
Linus Torvalds2386d652005-07-13 18:46:20 -0700240 PROTO_SSH,
Gary V. Vaughan4b055482010-05-14 09:31:35 +0000241 PROTO_GIT
Linus Torvalds2386d652005-07-13 18:46:20 -0700242};
243
Torsten Bögershausenc59ab2e2013-11-28 20:50:03 +0100244int url_is_local_not_ssh(const char *url)
245{
246 const char *colon = strchr(url, ':');
247 const char *slash = strchr(url, '/');
248 return !colon || (slash && slash < colon) ||
249 has_dos_drive_prefix(url);
250}
251
Torsten Bögershausen5610b7c2013-11-28 20:49:17 +0100252static const char *prot_name(enum protocol protocol)
253{
254 switch (protocol) {
255 case PROTO_LOCAL:
Torsten Bögershausenc59ab2e2013-11-28 20:50:03 +0100256 case PROTO_FILE:
Torsten Bögershausen5610b7c2013-11-28 20:49:17 +0100257 return "file";
258 case PROTO_SSH:
259 return "ssh";
260 case PROTO_GIT:
261 return "git";
262 default:
263 return "unkown protocol";
264 }
265}
266
Linus Torvalds2386d652005-07-13 18:46:20 -0700267static enum protocol get_protocol(const char *name)
268{
269 if (!strcmp(name, "ssh"))
270 return PROTO_SSH;
271 if (!strcmp(name, "git"))
272 return PROTO_GIT;
Linus Torvaldsc05186c2005-10-14 17:14:56 -0700273 if (!strcmp(name, "git+ssh"))
274 return PROTO_SSH;
275 if (!strcmp(name, "ssh+git"))
276 return PROTO_SSH;
Linus Torvalds72a4f4b2007-08-01 10:03:37 -0700277 if (!strcmp(name, "file"))
Torsten Bögershausenc59ab2e2013-11-28 20:50:03 +0100278 return PROTO_FILE;
Linus Torvalds2386d652005-07-13 18:46:20 -0700279 die("I don't handle protocol '%s'", name);
280}
281
YOSHIFUJI Hideaki5ba88442005-07-21 09:10:36 -0400282#define STR_(s) # s
283#define STR(s) STR_(s)
Linus Torvalds2386d652005-07-13 18:46:20 -0700284
Michael Lukashov72a534d2010-02-17 20:56:02 +0000285static void get_host_and_port(char **host, const char **port)
286{
287 char *colon, *end;
288
289 if (*host[0] == '[') {
290 end = strchr(*host + 1, ']');
291 if (end) {
292 *end = 0;
293 end++;
294 (*host)++;
295 } else
296 end = *host;
297 } else
298 end = *host;
299 colon = strchr(end, ':');
300
301 if (colon) {
302 *colon = 0;
303 *port = colon + 1;
304 }
305}
306
Eric Wonge47a8582011-12-06 04:39:36 +0000307static void enable_keepalive(int sockfd)
308{
309 int ka = 1;
310
311 if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &ka, sizeof(ka)) < 0)
312 fprintf(stderr, "unable to set SO_KEEPALIVE on socket: %s\n",
313 strerror(errno));
314}
315
hpa49744d62005-09-28 16:52:21 -0700316#ifndef NO_IPV6
hpa4c505f72005-09-28 16:37:58 -0700317
Alex Riesenba505322007-05-23 23:34:27 +0200318static const char *ai_name(const struct addrinfo *ai)
319{
Benjamin Kramer785a9852009-04-24 14:16:41 +0200320 static char addr[NI_MAXHOST];
321 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), NULL, 0,
322 NI_NUMERICHOST) != 0)
Alex Riesenba505322007-05-23 23:34:27 +0200323 strcpy(addr, "(unknown)");
Benjamin Kramer785a9852009-04-24 14:16:41 +0200324
Alex Riesenba505322007-05-23 23:34:27 +0200325 return addr;
326}
327
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500328/*
329 * Returns a connected socket() fd, or else die()s.
330 */
Michael S. Tsirkin7841ce72007-05-16 20:09:41 +0300331static int git_tcp_connect_sock(char *host, int flags)
Linus Torvalds2386d652005-07-13 18:46:20 -0700332{
Dave Zarzycki63a995b2011-07-12 09:28:34 -0700333 struct strbuf error_message = STRBUF_INIT;
334 int sockfd = -1;
Timo Hirvonen554fe202006-06-28 12:04:39 +0300335 const char *port = STR(DEFAULT_GIT_PORT);
YOSHIFUJI Hideaki5ba88442005-07-21 09:10:36 -0400336 struct addrinfo hints, *ai0, *ai;
337 int gai;
Alex Riesenba505322007-05-23 23:34:27 +0200338 int cnt = 0;
Linus Torvalds2386d652005-07-13 18:46:20 -0700339
Michael Lukashov72a534d2010-02-17 20:56:02 +0000340 get_host_and_port(&host, &port);
341 if (!*port)
342 port = "<none>";
YOSHIFUJI Hideaki5ba88442005-07-21 09:10:36 -0400343
344 memset(&hints, 0, sizeof(hints));
345 hints.ai_socktype = SOCK_STREAM;
346 hints.ai_protocol = IPPROTO_TCP;
347
Michael S. Tsirkin7841ce72007-05-16 20:09:41 +0300348 if (flags & CONNECT_VERBOSE)
349 fprintf(stderr, "Looking up %s ... ", host);
350
YOSHIFUJI Hideaki5ba88442005-07-21 09:10:36 -0400351 gai = getaddrinfo(host, port, &hints, &ai);
352 if (gai)
Linus Torvalds608d48b2007-03-27 09:50:20 -0700353 die("Unable to look up %s (port %s) (%s)", host, port, gai_strerror(gai));
YOSHIFUJI Hideaki5ba88442005-07-21 09:10:36 -0400354
Michael S. Tsirkin7841ce72007-05-16 20:09:41 +0300355 if (flags & CONNECT_VERBOSE)
356 fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);
357
Erik Faye-Lunde08afec2011-08-01 13:16:09 +0200358 for (ai0 = ai; ai; ai = ai->ai_next, cnt++) {
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500359 sockfd = socket(ai->ai_family,
360 ai->ai_socktype, ai->ai_protocol);
Dave Zarzycki63a995b2011-07-12 09:28:34 -0700361 if ((sockfd < 0) ||
362 (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0)) {
363 strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
364 host, cnt, ai_name(ai), strerror(errno));
365 if (0 <= sockfd)
366 close(sockfd);
YOSHIFUJI Hideaki5ba88442005-07-21 09:10:36 -0400367 sockfd = -1;
368 continue;
Linus Torvalds2386d652005-07-13 18:46:20 -0700369 }
Alex Riesenba505322007-05-23 23:34:27 +0200370 if (flags & CONNECT_VERBOSE)
371 fprintf(stderr, "%s ", ai_name(ai));
YOSHIFUJI Hideaki5ba88442005-07-21 09:10:36 -0400372 break;
Linus Torvalds2386d652005-07-13 18:46:20 -0700373 }
374
YOSHIFUJI Hideaki5ba88442005-07-21 09:10:36 -0400375 freeaddrinfo(ai0);
Linus Torvalds2386d652005-07-13 18:46:20 -0700376
Linus Torvalds2386d652005-07-13 18:46:20 -0700377 if (sockfd < 0)
Dave Zarzycki63a995b2011-07-12 09:28:34 -0700378 die("unable to connect to %s:\n%s", host, error_message.buf);
YOSHIFUJI Hideaki5ba88442005-07-21 09:10:36 -0400379
Eric Wonge47a8582011-12-06 04:39:36 +0000380 enable_keepalive(sockfd);
381
Michael S. Tsirkin7841ce72007-05-16 20:09:41 +0300382 if (flags & CONNECT_VERBOSE)
383 fprintf(stderr, "done.\n");
384
Dave Zarzycki63a995b2011-07-12 09:28:34 -0700385 strbuf_release(&error_message);
386
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500387 return sockfd;
Linus Torvalds2386d652005-07-13 18:46:20 -0700388}
389
hpa49744d62005-09-28 16:52:21 -0700390#else /* NO_IPV6 */
hpa4c505f72005-09-28 16:37:58 -0700391
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500392/*
393 * Returns a connected socket() fd, or else die()s.
394 */
Michael S. Tsirkin7841ce72007-05-16 20:09:41 +0300395static int git_tcp_connect_sock(char *host, int flags)
hpa4c505f72005-09-28 16:37:58 -0700396{
Erik Faye-Lund7203a2d2011-08-01 13:16:10 +0200397 struct strbuf error_message = STRBUF_INIT;
398 int sockfd = -1;
Michael Lukashov72a534d2010-02-17 20:56:02 +0000399 const char *port = STR(DEFAULT_GIT_PORT);
400 char *ep;
hpa4c505f72005-09-28 16:37:58 -0700401 struct hostent *he;
402 struct sockaddr_in sa;
403 char **ap;
404 unsigned int nport;
Alex Riesenba505322007-05-23 23:34:27 +0200405 int cnt;
hpa4c505f72005-09-28 16:37:58 -0700406
Michael Lukashov72a534d2010-02-17 20:56:02 +0000407 get_host_and_port(&host, &port);
hpa4c505f72005-09-28 16:37:58 -0700408
Michael S. Tsirkin7841ce72007-05-16 20:09:41 +0300409 if (flags & CONNECT_VERBOSE)
410 fprintf(stderr, "Looking up %s ... ", host);
411
hpa4c505f72005-09-28 16:37:58 -0700412 he = gethostbyname(host);
413 if (!he)
414 die("Unable to look up %s (%s)", host, hstrerror(h_errno));
415 nport = strtoul(port, &ep, 10);
416 if ( ep == port || *ep ) {
417 /* Not numeric */
418 struct servent *se = getservbyname(port,"tcp");
419 if ( !se )
Alexander Potashevd7530702009-01-04 21:38:41 +0300420 die("Unknown port %s", port);
hpa4c505f72005-09-28 16:37:58 -0700421 nport = se->s_port;
422 }
423
Michael S. Tsirkin7841ce72007-05-16 20:09:41 +0300424 if (flags & CONNECT_VERBOSE)
425 fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);
426
Alex Riesenba505322007-05-23 23:34:27 +0200427 for (cnt = 0, ap = he->h_addr_list; *ap; ap++, cnt++) {
hpa4c505f72005-09-28 16:37:58 -0700428 memset(&sa, 0, sizeof sa);
429 sa.sin_family = he->h_addrtype;
Peter Anvin6573faf2005-09-28 17:26:44 -0700430 sa.sin_port = htons(nport);
Paul Sericec6164212005-11-22 07:54:23 -0600431 memcpy(&sa.sin_addr, *ap, he->h_length);
hpa4c505f72005-09-28 16:37:58 -0700432
Erik Faye-Lund7203a2d2011-08-01 13:16:10 +0200433 sockfd = socket(he->h_addrtype, SOCK_STREAM, 0);
434 if ((sockfd < 0) ||
435 connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
436 strbuf_addf(&error_message, "%s[%d: %s]: errno=%s\n",
Alex Riesenba505322007-05-23 23:34:27 +0200437 host,
438 cnt,
439 inet_ntoa(*(struct in_addr *)&sa.sin_addr),
Erik Faye-Lund7203a2d2011-08-01 13:16:10 +0200440 strerror(errno));
441 if (0 <= sockfd)
442 close(sockfd);
hpa4c505f72005-09-28 16:37:58 -0700443 sockfd = -1;
444 continue;
445 }
Alex Riesenba505322007-05-23 23:34:27 +0200446 if (flags & CONNECT_VERBOSE)
447 fprintf(stderr, "%s ",
448 inet_ntoa(*(struct in_addr *)&sa.sin_addr));
hpa4c505f72005-09-28 16:37:58 -0700449 break;
450 }
451
452 if (sockfd < 0)
Erik Faye-Lund7203a2d2011-08-01 13:16:10 +0200453 die("unable to connect to %s:\n%s", host, error_message.buf);
hpa4c505f72005-09-28 16:37:58 -0700454
Eric Wonge47a8582011-12-06 04:39:36 +0000455 enable_keepalive(sockfd);
456
Michael S. Tsirkin7841ce72007-05-16 20:09:41 +0300457 if (flags & CONNECT_VERBOSE)
458 fprintf(stderr, "done.\n");
459
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500460 return sockfd;
hpa4c505f72005-09-28 16:37:58 -0700461}
462
hpa49744d62005-09-28 16:52:21 -0700463#endif /* NO_IPV6 */
hpa4c505f72005-09-28 16:37:58 -0700464
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500465
Michael S. Tsirkin7841ce72007-05-16 20:09:41 +0300466static void git_tcp_connect(int fd[2], char *host, int flags)
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500467{
Michael S. Tsirkin7841ce72007-05-16 20:09:41 +0300468 int sockfd = git_tcp_connect_sock(host, flags);
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500469
470 fd[0] = sockfd;
Junio C Hamanoec587fd2007-01-21 17:10:51 -0800471 fd[1] = dup(sockfd);
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500472}
473
474
David Rientjes96f1e582006-08-15 10:23:48 -0700475static char *git_proxy_command;
Paul Collinsf8014772005-11-04 14:57:16 +0000476
Johannes Schindelinef90d6d2008-05-14 18:46:53 +0100477static int git_proxy_command_options(const char *var, const char *value,
478 void *cb)
Paul Collinsf8014772005-11-04 14:57:16 +0000479{
Junio C Hamanoe814bc42005-11-19 03:48:56 -0800480 if (!strcmp(var, "core.gitproxy")) {
YOSHIFUJI Hideaki / 吉藤英明c3df8562005-11-22 12:18:23 +0900481 const char *for_pos;
482 int matchlen = -1;
483 int hostlen;
Erik Faye-Lund15112c92009-03-11 02:38:12 +0000484 const char *rhost_name = cb;
485 int rhost_len = strlen(rhost_name);
YOSHIFUJI Hideaki / 吉藤英明c3df8562005-11-22 12:18:23 +0900486
Junio C Hamanoe814bc42005-11-19 03:48:56 -0800487 if (git_proxy_command)
Paul Collinsf8014772005-11-04 14:57:16 +0000488 return 0;
Junio C Hamanoc64b9ad2008-02-11 10:52:15 -0800489 if (!value)
490 return config_error_nonbool(var);
Junio C Hamanoe814bc42005-11-19 03:48:56 -0800491 /* [core]
492 * ;# matches www.kernel.org as well
493 * gitproxy = netcatter-1 for kernel.org
494 * gitproxy = netcatter-2 for sample.xz
495 * gitproxy = netcatter-default
496 */
YOSHIFUJI Hideaki / 吉藤英明c3df8562005-11-22 12:18:23 +0900497 for_pos = strstr(value, " for ");
Junio C Hamanoe814bc42005-11-19 03:48:56 -0800498 if (!for_pos)
499 /* matches everybody */
500 matchlen = strlen(value);
501 else {
502 hostlen = strlen(for_pos + 5);
503 if (rhost_len < hostlen)
504 matchlen = -1;
505 else if (!strncmp(for_pos + 5,
506 rhost_name + rhost_len - hostlen,
507 hostlen) &&
508 ((rhost_len == hostlen) ||
509 rhost_name[rhost_len - hostlen -1] == '.'))
510 matchlen = for_pos - value;
511 else
512 matchlen = -1;
Paul Collinsf8014772005-11-04 14:57:16 +0000513 }
Junio C Hamanoe814bc42005-11-19 03:48:56 -0800514 if (0 <= matchlen) {
515 /* core.gitproxy = none for kernel.org */
Junio C Hamanoa6080a02007-06-07 00:04:01 -0700516 if (matchlen == 4 &&
Junio C Hamanoe814bc42005-11-19 03:48:56 -0800517 !memcmp(value, "none", 4))
518 matchlen = 0;
Pierre Habouzit182af832007-09-16 00:32:36 +0200519 git_proxy_command = xmemdupz(value, matchlen);
Junio C Hamanoe814bc42005-11-19 03:48:56 -0800520 }
521 return 0;
Paul Collinsf8014772005-11-04 14:57:16 +0000522 }
523
Johannes Schindelinef90d6d2008-05-14 18:46:53 +0100524 return git_default_config(var, value, cb);
Paul Collinsf8014772005-11-04 14:57:16 +0000525}
526
Junio C Hamanoe814bc42005-11-19 03:48:56 -0800527static int git_use_proxy(const char *host)
Paul Collinsf8014772005-11-04 14:57:16 +0000528{
529 git_proxy_command = getenv("GIT_PROXY_COMMAND");
Erik Faye-Lund15112c92009-03-11 02:38:12 +0000530 git_config(git_proxy_command_options, (void*)host);
Junio C Hamanoe814bc42005-11-19 03:48:56 -0800531 return (git_proxy_command && *git_proxy_command);
Paul Collinsf8014772005-11-04 14:57:16 +0000532}
533
Jeff King5cbf8242011-05-16 02:46:07 -0400534static struct child_process *git_proxy_connect(int fd[2], char *host)
Paul Collinsf8014772005-11-04 14:57:16 +0000535{
Timo Hirvonen554fe202006-06-28 12:04:39 +0300536 const char *port = STR(DEFAULT_GIT_PORT);
Jeff King5cbf8242011-05-16 02:46:07 -0400537 const char **argv;
538 struct child_process *proxy;
Paul Collinsf8014772005-11-04 14:57:16 +0000539
Michael Lukashov72a534d2010-02-17 20:56:02 +0000540 get_host_and_port(&host, &port);
Paul Collinsf8014772005-11-04 14:57:16 +0000541
Jeff King5cbf8242011-05-16 02:46:07 -0400542 argv = xmalloc(sizeof(*argv) * 4);
Shawn O. Pearce15a1c0122007-03-12 19:00:19 -0400543 argv[0] = git_proxy_command;
544 argv[1] = host;
545 argv[2] = port;
546 argv[3] = NULL;
Jeff King5cbf8242011-05-16 02:46:07 -0400547 proxy = xcalloc(1, sizeof(*proxy));
548 proxy->argv = argv;
549 proxy->in = -1;
550 proxy->out = -1;
551 if (start_command(proxy))
Shawn O. Pearce15a1c0122007-03-12 19:00:19 -0400552 die("cannot start proxy %s", argv[0]);
Jeff King5cbf8242011-05-16 02:46:07 -0400553 fd[0] = proxy->out; /* read from proxy stdout */
554 fd[1] = proxy->in; /* write to proxy stdin */
555 return proxy;
Paul Collinsf8014772005-11-04 14:57:16 +0000556}
557
Torsten Bögershausen83b05872013-11-28 20:49:54 +0100558static const char *get_port_numeric(const char *p)
Luben Tuikov2e776662007-09-01 02:36:31 -0700559{
560 char *end;
Luben Tuikov2e776662007-09-01 02:36:31 -0700561 if (p) {
René Scharfe8f148252008-12-21 02:12:11 +0100562 long port = strtol(p + 1, &end, 10);
563 if (end != p + 1 && *end == '\0' && 0 <= port && port < 65536) {
Torsten Bögershausen83b05872013-11-28 20:49:54 +0100564 return p;
Luben Tuikov2e776662007-09-01 02:36:31 -0700565 }
566 }
567
568 return NULL;
569}
570
Linus Torvaldsf7192592005-07-04 11:57:58 -0700571/*
Johannes Sixtcabc3c12013-11-28 20:49:01 +0100572 * Extract protocol and relevant parts from the specified connection URL.
573 * The caller must free() the returned strings.
Linus Torvaldsf7192592005-07-04 11:57:58 -0700574 */
Johannes Sixtcabc3c12013-11-28 20:49:01 +0100575static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
Torsten Bögershausen83b05872013-11-28 20:49:54 +0100576 char **ret_path)
Linus Torvaldsf7192592005-07-04 11:57:58 -0700577{
Jeff King9d2e9422010-05-23 05:19:44 -0400578 char *url;
Benjamin Kramer8e76bf32009-03-13 13:51:33 +0100579 char *host, *path;
YOSHIFUJI Hideaki / 吉藤英明356bece2005-12-21 19:23:42 +0900580 char *end;
Torsten Bögershausenc59ab2e2013-11-28 20:50:03 +0100581 int separator = '/';
Andreas Ericssonfaea9cc2005-11-17 20:37:14 +0100582 enum protocol protocol = PROTO_LOCAL;
Junio C Hamanof0b73672006-06-19 18:25:21 -0700583
Jeff King9d2e9422010-05-23 05:19:44 -0400584 if (is_url(url_orig))
585 url = url_decode(url_orig);
586 else
587 url = xstrdup(url_orig);
588
Andreas Ericssonfaea9cc2005-11-17 20:37:14 +0100589 host = strstr(url, "://");
Brian Gianforcaroeeefa7c2009-09-01 01:35:10 -0400590 if (host) {
Andreas Ericssonfaea9cc2005-11-17 20:37:14 +0100591 *host = '\0';
592 protocol = get_protocol(url);
593 host += 3;
YOSHIFUJI Hideaki / 吉藤英明356bece2005-12-21 19:23:42 +0900594 } else {
Linus Torvaldsf7192592005-07-04 11:57:58 -0700595 host = url;
Torsten Bögershausenc59ab2e2013-11-28 20:50:03 +0100596 if (!url_is_local_not_ssh(url)) {
597 protocol = PROTO_SSH;
598 separator = ':';
599 }
YOSHIFUJI Hideaki / 吉藤英明356bece2005-12-21 19:23:42 +0900600 }
601
Ilari Liusvaara9aa50532010-01-26 20:24:42 +0200602 /*
Torsten Bögershausen83b05872013-11-28 20:49:54 +0100603 * Don't do destructive transforms as protocol code does
604 * '[]' unwrapping in get_host_and_port()
Ilari Liusvaara9aa50532010-01-26 20:24:42 +0200605 */
YOSHIFUJI Hideaki / 吉藤英明356bece2005-12-21 19:23:42 +0900606 if (host[0] == '[') {
607 end = strchr(host + 1, ']');
608 if (end) {
YOSHIFUJI Hideaki / 吉藤英明356bece2005-12-21 19:23:42 +0900609 end++;
YOSHIFUJI Hideaki / 吉藤英明356bece2005-12-21 19:23:42 +0900610 } else
611 end = host;
612 } else
613 end = host;
614
Torsten Bögershausenc59ab2e2013-11-28 20:50:03 +0100615 if (protocol == PROTO_LOCAL)
Linus Torvalds72a4f4b2007-08-01 10:03:37 -0700616 path = end;
Torsten Bögershausenc59ab2e2013-11-28 20:50:03 +0100617 else if (protocol == PROTO_FILE && has_dos_drive_prefix(end))
618 path = end; /* "file://$(pwd)" may be "file://C:/projects/repo" */
619 else
620 path = strchr(end, separator);
Linus Torvalds2386d652005-07-13 18:46:20 -0700621
Andreas Ericssonfaea9cc2005-11-17 20:37:14 +0100622 if (!path || !*path)
623 die("No path specified. See 'man git-pull' for valid url syntax");
624
625 /*
626 * null-terminate hostname and point path to ~ for URL's like this:
627 * ssh://host.xz/~user/repo
628 */
Torsten Bögershausenc59ab2e2013-11-28 20:50:03 +0100629
630 end = path; /* Need to \0 terminate host here */
631 if (separator == ':')
632 path++; /* path starts after ':' */
633 if (protocol == PROTO_GIT || protocol == PROTO_SSH) {
Andreas Ericssonfaea9cc2005-11-17 20:37:14 +0100634 if (path[1] == '~')
635 path++;
Andreas Ericssonfaea9cc2005-11-17 20:37:14 +0100636 }
637
Torsten Bögershausenc59ab2e2013-11-28 20:50:03 +0100638 path = xstrdup(path);
639 *end = '\0';
640
Johannes Sixtcabc3c12013-11-28 20:49:01 +0100641 *ret_host = xstrdup(host);
Torsten Bögershausenc59ab2e2013-11-28 20:50:03 +0100642 *ret_path = path;
Johannes Sixtcabc3c12013-11-28 20:49:01 +0100643 free(url);
644 return protocol;
645}
646
Martin Sivak4852f722005-08-03 17:15:42 +0200647static struct child_process no_fork;
648
649/*
650 * This returns a dummy child_process if the transport protocol does not
651 * need fork(2), or a struct child_process object if it does. Once done,
652 * finish the connection with finish_connect() with the value returned from
Linus Torvaldsf7192592005-07-04 11:57:58 -0700653 * this function (it is safe to call finish_connect() with NULL to support
654 * the former case).
655 *
656 * If it returns, the connect is successful; it just dies on errors (this
657 * will hopefully be changed in a libification effort, to return NULL when
658 * the connection failed).
659 */
Johannes Sixtcabc3c12013-11-28 20:49:01 +0100660struct child_process *git_connect(int fd[2], const char *url,
Linus Torvaldsf7192592005-07-04 11:57:58 -0700661 const char *prog, int flags)
662{
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100663 char *hostandport, *path;
Linus Torvaldsf7192592005-07-04 11:57:58 -0700664 struct child_process *conn = &no_fork;
Johannes Sixtcabc3c12013-11-28 20:49:01 +0100665 enum protocol protocol;
Linus Torvaldsf7192592005-07-04 11:57:58 -0700666 const char **arg;
Johannes Sixtcabc3c12013-11-28 20:49:01 +0100667 struct strbuf cmd = STRBUF_INIT;
Linus Torvaldsf7192592005-07-04 11:57:58 -0700668
669 /* Without this we cannot rely on waitpid() to tell
670 * what happened to our children.
671 */
672 signal(SIGCHLD, SIG_DFL);
673
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100674 protocol = parse_connect_url(url, &hostandport, &path);
Torsten Bögershausen5610b7c2013-11-28 20:49:17 +0100675 if (flags & CONNECT_DIAG_URL) {
676 printf("Diag: url=%s\n", url ? url : "NULL");
677 printf("Diag: protocol=%s\n", prot_name(protocol));
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100678 printf("Diag: hostandport=%s\n", hostandport ? hostandport : "NULL");
Torsten Bögershausen5610b7c2013-11-28 20:49:17 +0100679 printf("Diag: path=%s\n", path ? path : "NULL");
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100680 conn = NULL;
681 } else if (protocol == PROTO_GIT) {
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500682 /* These underlying connection commands die() if they
683 * cannot connect.
684 */
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100685 char *target_host = xstrdup(hostandport);
686 if (git_use_proxy(hostandport))
687 conn = git_proxy_connect(fd, hostandport);
Serge E. Hallynda2a95b2006-04-17 10:14:47 -0500688 else
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100689 git_tcp_connect(fd, hostandport, flags);
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500690 /*
691 * Separate original protocol components prog and path
Shawn O. Pearce73bb33a2009-06-04 18:33:32 -0700692 * from extended host header with a NUL byte.
693 *
694 * Note: Do not add any other headers here! Doing so
695 * will cause older git-daemon servers to crash.
Jon Loeliger5ad312b2006-06-06 22:58:41 -0500696 */
697 packet_write(fd[1],
698 "%s %s%chost=%s%c",
699 prog, path, 0,
700 target_host, 0);
701 free(target_host);
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100702 } else {
703 conn = xcalloc(1, sizeof(*conn));
Linus Torvaldsf7192592005-07-04 11:57:58 -0700704
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100705 strbuf_addstr(&cmd, prog);
706 strbuf_addch(&cmd, ' ');
707 sq_quote_buf(&cmd, path);
Christian Couder0f503d72006-09-11 07:04:50 +0200708
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100709 conn->in = conn->out = -1;
710 conn->argv = arg = xcalloc(7, sizeof(*arg));
711 if (protocol == PROTO_SSH) {
712 const char *ssh = getenv("GIT_SSH");
713 int putty = ssh && strcasestr(ssh, "plink");
714 char *ssh_host = hostandport;
715 const char *port = NULL;
716 get_host_and_port(&ssh_host, &port);
717 port = get_port_numeric(port);
Christian Couder0f503d72006-09-11 07:04:50 +0200718
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100719 if (!ssh) ssh = "ssh";
Luben Tuikov2e776662007-09-01 02:36:31 -0700720
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100721 *arg++ = ssh;
722 if (putty && !strcasestr(ssh, "tortoiseplink"))
723 *arg++ = "-batch";
724 if (port) {
725 /* P is for PuTTY, p is for OpenSSH */
726 *arg++ = putty ? "-P" : "-p";
727 *arg++ = port;
728 }
729 *arg++ = ssh_host;
730 } else {
731 /* remove repo-local variables from the environment */
732 conn->env = local_repo_env;
733 conn->use_shell = 1;
Linus Torvaldsf7192592005-07-04 11:57:58 -0700734 }
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100735 *arg++ = cmd.buf;
736 *arg = NULL;
Johannes Sixtf364cb82007-10-19 21:47:54 +0200737
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100738 if (start_command(conn))
739 die("unable to fork");
Johannes Sixtf364cb82007-10-19 21:47:54 +0200740
Torsten Bögershausena2036d72013-11-28 20:50:15 +0100741 fd[0] = conn->out; /* read from child's stdout */
742 fd[1] = conn->in; /* write to child's stdin */
743 strbuf_release(&cmd);
744 }
745 free(hostandport);
Johannes Sixtcabc3c12013-11-28 20:49:01 +0100746 free(path);
Johannes Sixt98158e92007-10-19 21:47:53 +0200747 return conn;
Linus Torvaldsf7192592005-07-04 11:57:58 -0700748}
749
Jeff King7ffe8532011-05-16 02:52:11 -0400750int git_connection_is_socket(struct child_process *conn)
751{
752 return conn == &no_fork;
753}
754
Johannes Sixt98158e92007-10-19 21:47:53 +0200755int finish_connect(struct child_process *conn)
Linus Torvaldsf7192592005-07-04 11:57:58 -0700756{
Johannes Sixtf364cb82007-10-19 21:47:54 +0200757 int code;
Jeff King7ffe8532011-05-16 02:52:11 -0400758 if (!conn || git_connection_is_socket(conn))
Franck Bui-Huuf42a5c42006-09-12 11:00:13 +0200759 return 0;
760
Johannes Sixtf364cb82007-10-19 21:47:54 +0200761 code = finish_command(conn);
762 free(conn->argv);
Johannes Sixt98158e92007-10-19 21:47:53 +0200763 free(conn);
Johannes Sixtf364cb82007-10-19 21:47:54 +0200764 return code;
Linus Torvaldsf7192592005-07-04 11:57:58 -0700765}