blob: 28d9d1063880b9b7e6ec18ea18c18f77fb99ef32 [file] [log] [blame]
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001#include "cache.h"
2#include "remote.h"
3#include "strbuf.h"
4#include "walker.h"
5#include "http.h"
Björn Steinbrinkd01a8e32009-10-14 00:11:09 +02006#include "exec_cmd.h"
Shawn O. Pearceae4efe12009-10-30 17:47:30 -07007#include "run-command.h"
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -07008#include "pkt-line.h"
Junio C Hamano05c1eb12013-08-02 15:14:50 -07009#include "string-list.h"
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -070010#include "sideband.h"
Junio C Hamano222b1212013-07-08 22:16:31 -070011#include "argv-array.h"
Jeff King2501aff2013-09-28 04:31:45 -040012#include "credential.h"
Nguyễn Thái Ngọc Duy16094882013-12-05 20:02:50 +070013#include "sha1-array.h"
Dave Borowitz30261092015-08-19 11:26:46 -040014#include "send-pack.h"
Daniel Barkalowa2d725b2009-08-05 01:01:56 -040015
Shawn O. Pearce37a87682009-10-30 17:47:26 -070016static struct remote *remote;
Jeff Kingb227bbc2013-09-28 04:35:25 -040017/* always ends with a trailing slash */
18static struct strbuf url = STRBUF_INIT;
Shawn O. Pearce37a87682009-10-30 17:47:26 -070019
Shawn O. Pearceef08ef92009-10-30 17:47:29 -070020struct options {
21 int verbosity;
22 unsigned long depth;
Nguyễn Thái Ngọc Duy508ea882016-06-12 17:53:59 +070023 char *deepen_since;
Nguyễn Thái Ngọc Duya45a2602016-06-12 17:54:04 +070024 struct string_list deepen_not;
Shawn O. Pearceef08ef92009-10-30 17:47:29 -070025 unsigned progress : 1,
Nguyễn Thái Ngọc Duy9ba38042013-07-21 15:18:05 +070026 check_self_contained_and_connected : 1,
Nguyễn Thái Ngọc Duy16094882013-12-05 20:02:50 +070027 cloning : 1,
28 update_shallow : 1,
Shawn O. Pearceae4efe12009-10-30 17:47:30 -070029 followtags : 1,
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -070030 dry_run : 1,
Junio C Hamano0ea47f92014-09-15 14:59:00 -070031 thin : 1,
Dave Borowitz30261092015-08-19 11:26:46 -040032 /* One of the SEND_PACK_PUSH_CERT_* constants. */
Nguyễn Thái Ngọc Duycccf74e2016-06-12 17:54:09 +070033 push_cert : 2,
34 deepen_relative : 1;
Shawn O. Pearceef08ef92009-10-30 17:47:29 -070035};
36static struct options options;
Junio C Hamano05c1eb12013-08-02 15:14:50 -070037static struct string_list cas_options = STRING_LIST_INIT_DUP;
Shawn O. Pearceef08ef92009-10-30 17:47:29 -070038
Shawn O. Pearceef08ef92009-10-30 17:47:29 -070039static int set_option(const char *name, const char *value)
40{
41 if (!strcmp(name, "verbosity")) {
42 char *end;
43 int v = strtol(value, &end, 10);
44 if (value == end || *end)
45 return -1;
46 options.verbosity = v;
47 return 0;
48 }
49 else if (!strcmp(name, "progress")) {
50 if (!strcmp(value, "true"))
51 options.progress = 1;
52 else if (!strcmp(value, "false"))
53 options.progress = 0;
54 else
55 return -1;
Shawn O. Pearce249b2002009-10-30 17:47:42 -070056 return 0;
Shawn O. Pearceef08ef92009-10-30 17:47:29 -070057 }
58 else if (!strcmp(name, "depth")) {
59 char *end;
60 unsigned long v = strtoul(value, &end, 10);
61 if (value == end || *end)
62 return -1;
63 options.depth = v;
Shawn O. Pearce249b2002009-10-30 17:47:42 -070064 return 0;
Shawn O. Pearceef08ef92009-10-30 17:47:29 -070065 }
Nguyễn Thái Ngọc Duy508ea882016-06-12 17:53:59 +070066 else if (!strcmp(name, "deepen-since")) {
67 options.deepen_since = xstrdup(value);
68 return 0;
69 }
Nguyễn Thái Ngọc Duya45a2602016-06-12 17:54:04 +070070 else if (!strcmp(name, "deepen-not")) {
71 string_list_append(&options.deepen_not, value);
72 return 0;
73 }
Nguyễn Thái Ngọc Duycccf74e2016-06-12 17:54:09 +070074 else if (!strcmp(name, "deepen-relative")) {
75 if (!strcmp(value, "true"))
76 options.deepen_relative = 1;
77 else if (!strcmp(value, "false"))
78 options.deepen_relative = 0;
79 else
80 return -1;
81 return 0;
82 }
Shawn O. Pearceef08ef92009-10-30 17:47:29 -070083 else if (!strcmp(name, "followtags")) {
84 if (!strcmp(value, "true"))
85 options.followtags = 1;
86 else if (!strcmp(value, "false"))
87 options.followtags = 0;
88 else
89 return -1;
Shawn O. Pearce249b2002009-10-30 17:47:42 -070090 return 0;
Shawn O. Pearceef08ef92009-10-30 17:47:29 -070091 }
Shawn O. Pearceae4efe12009-10-30 17:47:30 -070092 else if (!strcmp(name, "dry-run")) {
93 if (!strcmp(value, "true"))
94 options.dry_run = 1;
95 else if (!strcmp(value, "false"))
96 options.dry_run = 0;
97 else
98 return -1;
99 return 0;
100 }
Nguyễn Thái Ngọc Duy9ba38042013-07-21 15:18:05 +0700101 else if (!strcmp(name, "check-connectivity")) {
102 if (!strcmp(value, "true"))
103 options.check_self_contained_and_connected = 1;
104 else if (!strcmp(value, "false"))
105 options.check_self_contained_and_connected = 0;
106 else
107 return -1;
108 return 0;
109 }
Junio C Hamano05c1eb12013-08-02 15:14:50 -0700110 else if (!strcmp(name, "cas")) {
111 struct strbuf val = STRBUF_INIT;
112 strbuf_addf(&val, "--" CAS_OPT_NAME "=%s", value);
113 string_list_append(&cas_options, val.buf);
114 strbuf_release(&val);
115 return 0;
Nguyễn Thái Ngọc Duy16094882013-12-05 20:02:50 +0700116 } else if (!strcmp(name, "cloning")) {
117 if (!strcmp(value, "true"))
118 options.cloning = 1;
119 else if (!strcmp(value, "false"))
120 options.cloning = 0;
121 else
122 return -1;
123 return 0;
124 } else if (!strcmp(name, "update-shallow")) {
125 if (!strcmp(value, "true"))
126 options.update_shallow = 1;
127 else if (!strcmp(value, "false"))
128 options.update_shallow = 0;
129 else
130 return -1;
131 return 0;
Junio C Hamano0ea47f92014-09-15 14:59:00 -0700132 } else if (!strcmp(name, "pushcert")) {
133 if (!strcmp(value, "true"))
Dave Borowitz30261092015-08-19 11:26:46 -0400134 options.push_cert = SEND_PACK_PUSH_CERT_ALWAYS;
Junio C Hamano0ea47f92014-09-15 14:59:00 -0700135 else if (!strcmp(value, "false"))
Dave Borowitz30261092015-08-19 11:26:46 -0400136 options.push_cert = SEND_PACK_PUSH_CERT_NEVER;
137 else if (!strcmp(value, "if-asked"))
138 options.push_cert = SEND_PACK_PUSH_CERT_IF_ASKED;
Junio C Hamano0ea47f92014-09-15 14:59:00 -0700139 else
140 return -1;
141 return 0;
Eric Wongc915f112016-02-03 04:09:14 +0000142
143#if LIBCURL_VERSION_NUM >= 0x070a08
144 } else if (!strcmp(name, "family")) {
145 if (!strcmp(value, "ipv4"))
146 git_curl_ipresolve = CURL_IPRESOLVE_V4;
147 else if (!strcmp(value, "ipv6"))
148 git_curl_ipresolve = CURL_IPRESOLVE_V6;
149 else if (!strcmp(value, "all"))
150 git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER;
151 else
152 return -1;
153 return 0;
154#endif /* LIBCURL_VERSION_NUM >= 0x070a08 */
Nguyễn Thái Ngọc Duy16094882013-12-05 20:02:50 +0700155 } else {
Shawn O. Pearceef08ef92009-10-30 17:47:29 -0700156 return 1 /* unsupported */;
157 }
158}
159
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700160struct discovery {
161 const char *service;
162 char *buf_alloc;
163 char *buf;
164 size_t len;
Jeff King2a455202013-02-20 15:07:19 -0500165 struct ref *refs;
Nguyễn Thái Ngọc Duy16094882013-12-05 20:02:50 +0700166 struct sha1_array shallow;
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700167 unsigned proto_git : 1;
168};
169static struct discovery *last_discovery;
170
Jeff Kingb8054bb2013-02-20 15:07:11 -0500171static struct ref *parse_git_refs(struct discovery *heads, int for_push)
172{
173 struct ref *list = NULL;
174 get_remote_heads(-1, heads->buf, heads->len, &list,
Nguyễn Thái Ngọc Duy16094882013-12-05 20:02:50 +0700175 for_push ? REF_NORMAL : 0, NULL, &heads->shallow);
Jeff Kingb8054bb2013-02-20 15:07:11 -0500176 return list;
177}
178
179static struct ref *parse_info_refs(struct discovery *heads)
180{
181 char *data, *start, *mid;
182 char *ref_name;
183 int i = 0;
184
185 struct ref *refs = NULL;
186 struct ref *ref = NULL;
187 struct ref *last_ref = NULL;
188
189 data = heads->buf;
190 start = NULL;
191 mid = data;
192 while (i < heads->len) {
193 if (!start) {
194 start = &data[i];
195 }
196 if (data[i] == '\t')
197 mid = &data[i];
198 if (data[i] == '\n') {
199 if (mid - start != 40)
Jeff Kingb227bbc2013-09-28 04:35:25 -0400200 die("%sinfo/refs not valid: is this a git repository?",
201 url.buf);
Jeff Kingb8054bb2013-02-20 15:07:11 -0500202 data[i] = 0;
203 ref_name = mid + 1;
Jeff King6f687c22015-09-24 17:08:09 -0400204 ref = alloc_ref(ref_name);
brian m. carlsonf4e54d02015-11-10 02:22:20 +0000205 get_oid_hex(start, &ref->old_oid);
Jeff Kingb8054bb2013-02-20 15:07:11 -0500206 if (!refs)
207 refs = ref;
208 if (last_ref)
209 last_ref->next = ref;
210 last_ref = ref;
211 start = NULL;
212 }
213 i++;
214 }
215
216 ref = alloc_ref("HEAD");
Jeff Kingb227bbc2013-09-28 04:35:25 -0400217 if (!http_fetch_ref(url.buf, ref) &&
Jeff Kingb8054bb2013-02-20 15:07:11 -0500218 !resolve_remote_symref(ref, refs)) {
219 ref->next = refs;
220 refs = ref;
221 } else {
222 free(ref);
223 }
224
225 return refs;
226}
227
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700228static void free_discovery(struct discovery *d)
229{
230 if (d) {
231 if (d == last_discovery)
232 last_discovery = NULL;
Nguyễn Thái Ngọc Duy16094882013-12-05 20:02:50 +0700233 free(d->shallow.sha1);
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700234 free(d->buf_alloc);
Jeff King2a455202013-02-20 15:07:19 -0500235 free_refs(d->refs);
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700236 free(d);
237 }
238}
239
Jeff Kingfc1b7742014-05-22 05:30:29 -0400240static int show_http_message(struct strbuf *type, struct strbuf *charset,
241 struct strbuf *msg)
Jeff King426e70d2013-04-05 18:17:23 -0400242{
243 const char *p, *eol;
244
245 /*
246 * We only show text/plain parts, as other types are likely
247 * to be ugly to look at on the user's terminal.
Jeff King426e70d2013-04-05 18:17:23 -0400248 */
Jeff Kingbf197fd2014-05-22 05:29:47 -0400249 if (strcmp(type->buf, "text/plain"))
Jeff King426e70d2013-04-05 18:17:23 -0400250 return -1;
Jeff Kingfc1b7742014-05-22 05:30:29 -0400251 if (charset->len)
252 strbuf_reencode(msg, charset->buf, get_log_output_encoding());
Jeff King426e70d2013-04-05 18:17:23 -0400253
254 strbuf_trim(msg);
255 if (!msg->len)
256 return -1;
257
258 p = msg->buf;
259 do {
260 eol = strchrnul(p, '\n');
261 fprintf(stderr, "remote: %.*s\n", (int)(eol - p), p);
262 p = eol + 1;
263 } while(*eol);
264 return 0;
265}
266
David Aguilar24d36f12014-08-31 13:11:31 -0700267static struct discovery *discover_refs(const char *service, int for_push)
Daniel Barkalowa2d725b2009-08-05 01:01:56 -0400268{
Shawn Pearce4656bf42013-01-31 13:02:07 -0800269 struct strbuf exp = STRBUF_INIT;
270 struct strbuf type = STRBUF_INIT;
Jeff Kingfc1b7742014-05-22 05:30:29 -0400271 struct strbuf charset = STRBUF_INIT;
Daniel Barkalowa2d725b2009-08-05 01:01:56 -0400272 struct strbuf buffer = STRBUF_INIT;
Jeff Kingc65d5692013-09-28 04:35:10 -0400273 struct strbuf refs_url = STRBUF_INIT;
Jeff King050ef362013-09-28 04:35:35 -0400274 struct strbuf effective_url = STRBUF_INIT;
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700275 struct discovery *last = last_discovery;
Jeff King243c3292012-09-20 13:00:22 -0400276 int http_ret, maybe_smart = 0;
Jeff Kingfcaa6e62016-12-06 13:24:38 -0500277 struct http_get_options http_options;
Daniel Barkalowa2d725b2009-08-05 01:01:56 -0400278
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700279 if (last && !strcmp(service, last->service))
280 return last;
281 free_discovery(last);
Daniel Barkalowa2d725b2009-08-05 01:01:56 -0400282
Jeff Kingb227bbc2013-09-28 04:35:25 -0400283 strbuf_addf(&refs_url, "%sinfo/refs", url.buf);
Christian Couder59556542013-11-30 21:55:40 +0100284 if ((starts_with(url.buf, "http://") || starts_with(url.buf, "https://")) &&
Jeff King02572c22012-09-20 17:30:58 -0400285 git_env_bool("GIT_SMART_HTTP", 1)) {
Jeff King243c3292012-09-20 13:00:22 -0400286 maybe_smart = 1;
Jeff Kingb227bbc2013-09-28 04:35:25 -0400287 if (!strchr(url.buf, '?'))
Jeff Kingc65d5692013-09-28 04:35:10 -0400288 strbuf_addch(&refs_url, '?');
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700289 else
Jeff Kingc65d5692013-09-28 04:35:10 -0400290 strbuf_addch(&refs_url, '&');
291 strbuf_addf(&refs_url, "service=%s", service);
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700292 }
Daniel Barkalowa2d725b2009-08-05 01:01:56 -0400293
Jeff Kingfcaa6e62016-12-06 13:24:38 -0500294 memset(&http_options, 0, sizeof(http_options));
295 http_options.content_type = &type;
296 http_options.charset = &charset;
297 http_options.effective_url = &effective_url;
298 http_options.base_url = &url;
Jeff King50d34132016-12-06 13:24:41 -0500299 http_options.initial_request = 1;
Jeff Kingfcaa6e62016-12-06 13:24:38 -0500300 http_options.no_cache = 1;
301 http_options.keep_error = 1;
Jeff King1bbcc222013-09-28 04:31:23 -0400302
Jeff Kingfcaa6e62016-12-06 13:24:38 -0500303 http_ret = http_get_strbuf(refs_url.buf, &buffer, &http_options);
Daniel Barkalowa2d725b2009-08-05 01:01:56 -0400304 switch (http_ret) {
305 case HTTP_OK:
306 break;
307 case HTTP_MISSING_TARGET:
Jeff Kingfc1b7742014-05-22 05:30:29 -0400308 show_http_message(&type, &charset, &buffer);
Jeff Kingb227bbc2013-09-28 04:35:25 -0400309 die("repository '%s' not found", url.buf);
Scott Chacon42653c02010-04-01 15:14:35 -0700310 case HTTP_NOAUTH:
Jeff Kingfc1b7742014-05-22 05:30:29 -0400311 show_http_message(&type, &charset, &buffer);
Jeff Kingb227bbc2013-09-28 04:35:25 -0400312 die("Authentication failed for '%s'", url.buf);
Daniel Barkalowa2d725b2009-08-05 01:01:56 -0400313 default:
Jeff Kingfc1b7742014-05-22 05:30:29 -0400314 show_http_message(&type, &charset, &buffer);
Jeff Kingb227bbc2013-09-28 04:35:25 -0400315 die("unable to access '%s': %s", url.buf, curl_errorstr);
Daniel Barkalowa2d725b2009-08-05 01:01:56 -0400316 }
317
Jeff King50d34132016-12-06 13:24:41 -0500318 if (options.verbosity && !starts_with(refs_url.buf, url.buf))
319 warning(_("redirecting to %s"), url.buf);
320
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700321 last= xcalloc(1, sizeof(*last_discovery));
322 last->service = service;
323 last->buf_alloc = strbuf_detach(&buffer, &last->len);
324 last->buf = last->buf_alloc;
325
Shawn Pearce4656bf42013-01-31 13:02:07 -0800326 strbuf_addf(&exp, "application/x-%s-advertisement", service);
327 if (maybe_smart &&
328 (5 <= last->len && last->buf[4] == '#') &&
329 !strbuf_cmp(&exp, &type)) {
Jeff King4981fe72013-02-23 17:31:34 -0500330 char *line;
331
Shawn Pearce4656bf42013-01-31 13:02:07 -0800332 /*
333 * smart HTTP response; validate that the service
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700334 * pkt-line matches our request.
335 */
Jeff King4981fe72013-02-23 17:31:34 -0500336 line = packet_read_line_buf(&last->buf, &last->len, NULL);
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700337
Shawn Pearce4656bf42013-01-31 13:02:07 -0800338 strbuf_reset(&exp);
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700339 strbuf_addf(&exp, "# service=%s", service);
Jeff King4981fe72013-02-23 17:31:34 -0500340 if (strcmp(line, exp.buf))
341 die("invalid server response; got '%s'", line);
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700342 strbuf_release(&exp);
343
344 /* The header can include additional metadata lines, up
345 * until a packet flush marker. Ignore these now, but
346 * in the future we might start to scan them.
347 */
Jeff King4981fe72013-02-23 17:31:34 -0500348 while (packet_read_line_buf(&last->buf, &last->len, NULL))
349 ;
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700350
351 last->proto_git = 1;
352 }
353
Jeff King2a455202013-02-20 15:07:19 -0500354 if (last->proto_git)
355 last->refs = parse_git_refs(last, for_push);
356 else
357 last->refs = parse_info_refs(last);
358
Jeff Kingc65d5692013-09-28 04:35:10 -0400359 strbuf_release(&refs_url);
Shawn Pearce4656bf42013-01-31 13:02:07 -0800360 strbuf_release(&exp);
361 strbuf_release(&type);
Jeff Kingfc1b7742014-05-22 05:30:29 -0400362 strbuf_release(&charset);
Jeff King050ef362013-09-28 04:35:35 -0400363 strbuf_release(&effective_url);
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700364 strbuf_release(&buffer);
365 last_discovery = last;
366 return last;
367}
368
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700369static struct ref *get_refs(int for_push)
370{
371 struct discovery *heads;
372
373 if (for_push)
Jeff King2a455202013-02-20 15:07:19 -0500374 heads = discover_refs("git-receive-pack", for_push);
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700375 else
Jeff King2a455202013-02-20 15:07:19 -0500376 heads = discover_refs("git-upload-pack", for_push);
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700377
Jeff King2a455202013-02-20 15:07:19 -0500378 return heads->refs;
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -0700379}
380
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700381static void output_refs(struct ref *refs)
382{
383 struct ref *posn;
384 for (posn = refs; posn; posn = posn->next) {
385 if (posn->symref)
386 printf("@%s %s\n", posn->symref, posn->name);
387 else
brian m. carlsonf4e54d02015-11-10 02:22:20 +0000388 printf("%s %s\n", oid_to_hex(&posn->old_oid), posn->name);
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700389 }
390 printf("\n");
391 fflush(stdout);
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700392}
393
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700394struct rpc_state {
395 const char *service_name;
396 const char **argv;
Ivan Todoroski81507492012-04-02 17:14:44 +0200397 struct strbuf *stdin_preamble;
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700398 char *service_url;
399 char *hdr_content_type;
400 char *hdr_accept;
401 char *buf;
402 size_t alloc;
403 size_t len;
404 size_t pos;
405 int in;
406 int out;
407 struct strbuf result;
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700408 unsigned gzip_request : 1;
Martin Storsjö6c81a992009-12-01 12:33:39 +0200409 unsigned initial_buffer : 1;
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700410};
411
412static size_t rpc_out(void *ptr, size_t eltsize,
413 size_t nmemb, void *buffer_)
414{
415 size_t max = eltsize * nmemb;
416 struct rpc_state *rpc = buffer_;
417 size_t avail = rpc->len - rpc->pos;
418
419 if (!avail) {
Martin Storsjö6c81a992009-12-01 12:33:39 +0200420 rpc->initial_buffer = 0;
Jeff King4981fe72013-02-23 17:31:34 -0500421 avail = packet_read(rpc->out, NULL, NULL, rpc->buf, rpc->alloc, 0);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700422 if (!avail)
423 return 0;
424 rpc->pos = 0;
425 rpc->len = avail;
426 }
427
Tay Ray Chuan48310602009-11-24 10:31:30 +0800428 if (max < avail)
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700429 avail = max;
430 memcpy(ptr, rpc->buf + rpc->pos, avail);
431 rpc->pos += avail;
432 return avail;
433}
434
Martin Storsjö6c81a992009-12-01 12:33:39 +0200435#ifndef NO_CURL_IOCTL
Junio C Hamano5092d3e2010-01-11 22:30:36 -0800436static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
Martin Storsjö6c81a992009-12-01 12:33:39 +0200437{
438 struct rpc_state *rpc = clientp;
439
440 switch (cmd) {
441 case CURLIOCMD_NOP:
442 return CURLIOE_OK;
443
444 case CURLIOCMD_RESTARTREAD:
445 if (rpc->initial_buffer) {
446 rpc->pos = 0;
447 return CURLIOE_OK;
448 }
Jeff Kingb725b272014-07-09 17:47:05 -0400449 error("unable to rewind rpc post data - try increasing http.postBuffer");
Martin Storsjö6c81a992009-12-01 12:33:39 +0200450 return CURLIOE_FAILRESTART;
451
452 default:
453 return CURLIOE_UNKNOWNCMD;
454 }
455}
456#endif
457
Dan McGeea04ff3e2011-05-03 23:47:27 +0800458static size_t rpc_in(char *ptr, size_t eltsize,
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700459 size_t nmemb, void *buffer_)
460{
461 size_t size = eltsize * nmemb;
462 struct rpc_state *rpc = buffer_;
463 write_or_die(rpc->in, ptr, size);
464 return size;
465}
466
Jeff King3a347ed2013-10-31 02:36:26 -0400467static int run_slot(struct active_request_slot *slot,
468 struct slot_results *results)
Shawn O. Pearce206b0992011-02-15 08:57:24 -0800469{
Jeff Kingb81401c2012-08-27 09:27:15 -0400470 int err;
Jeff King3a347ed2013-10-31 02:36:26 -0400471 struct slot_results results_buf;
Shawn O. Pearce206b0992011-02-15 08:57:24 -0800472
Jeff King3a347ed2013-10-31 02:36:26 -0400473 if (!results)
474 results = &results_buf;
475
Jeff Kingbeed3362014-02-18 05:34:20 -0500476 err = run_one_slot(slot, results);
Shawn O. Pearce206b0992011-02-15 08:57:24 -0800477
Jeff Kingb81401c2012-08-27 09:27:15 -0400478 if (err != HTTP_OK && err != HTTP_REAUTH) {
Shawn Pearce00540452016-02-13 17:39:34 -0800479 struct strbuf msg = STRBUF_INIT;
480 if (results->http_code && results->http_code != 200)
481 strbuf_addf(&msg, "HTTP %ld", results->http_code);
482 if (results->curl_result != CURLE_OK) {
483 if (msg.len)
484 strbuf_addch(&msg, ' ');
485 strbuf_addf(&msg, "curl %d", results->curl_result);
486 if (curl_errorstr[0]) {
487 strbuf_addch(&msg, ' ');
488 strbuf_addstr(&msg, curl_errorstr);
489 }
490 }
491 error("RPC failed; %s", msg.buf);
492 strbuf_release(&msg);
Shawn O. Pearce206b0992011-02-15 08:57:24 -0800493 }
494
495 return err;
496}
497
Jeff King3a347ed2013-10-31 02:36:26 -0400498static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
Shawn O. Pearce206b0992011-02-15 08:57:24 -0800499{
500 struct active_request_slot *slot;
Johannes Schindelin8cb01e22016-04-27 14:20:37 +0200501 struct curl_slist *headers = http_copy_default_headers();
Shawn O. Pearce206b0992011-02-15 08:57:24 -0800502 struct strbuf buf = STRBUF_INIT;
503 int err;
504
505 slot = get_active_slot();
506
507 headers = curl_slist_append(headers, rpc->hdr_content_type);
508 headers = curl_slist_append(headers, rpc->hdr_accept);
509
510 curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
511 curl_easy_setopt(slot->curl, CURLOPT_POST, 1);
512 curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
Shawn O. Pearceaa90b962012-09-19 16:12:02 -0700513 curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL);
Shawn O. Pearce206b0992011-02-15 08:57:24 -0800514 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000");
515 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4);
516 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
517 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
518 curl_easy_setopt(slot->curl, CURLOPT_FILE, &buf);
519
Jeff King3a347ed2013-10-31 02:36:26 -0400520 err = run_slot(slot, results);
Shawn O. Pearce206b0992011-02-15 08:57:24 -0800521
522 curl_slist_free_all(headers);
523 strbuf_release(&buf);
524 return err;
525}
526
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700527static int post_rpc(struct rpc_state *rpc)
528{
529 struct active_request_slot *slot;
Johannes Schindelin8cb01e22016-04-27 14:20:37 +0200530 struct curl_slist *headers = http_copy_default_headers();
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700531 int use_gzip = rpc->gzip_request;
532 char *gzip_body = NULL;
Ramsay Jones37711542012-11-21 19:08:51 +0000533 size_t gzip_size = 0;
Shawn O. Pearce206b0992011-02-15 08:57:24 -0800534 int err, large_request = 0;
Brian M. Carlsonc80d96c2013-10-31 02:36:51 -0400535 int needs_100_continue = 0;
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700536
537 /* Try to load the entire request, if we can fit it into the
538 * allocated buffer space we can use HTTP/1.0 and avoid the
539 * chunked encoding mess.
540 */
541 while (1) {
542 size_t left = rpc->alloc - rpc->len;
543 char *buf = rpc->buf + rpc->len;
544 int n;
545
546 if (left < LARGE_PACKET_MAX) {
547 large_request = 1;
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700548 use_gzip = 0;
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700549 break;
550 }
551
Jeff King4981fe72013-02-23 17:31:34 -0500552 n = packet_read(rpc->out, NULL, NULL, buf, left, 0);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700553 if (!n)
554 break;
555 rpc->len += n;
556 }
557
Shawn O. Pearce206b0992011-02-15 08:57:24 -0800558 if (large_request) {
Brian M. Carlsonc80d96c2013-10-31 02:36:51 -0400559 struct slot_results results;
560
Jeff Kingb81401c2012-08-27 09:27:15 -0400561 do {
Brian M. Carlsonc80d96c2013-10-31 02:36:51 -0400562 err = probe_rpc(rpc, &results);
Jeff King2501aff2013-09-28 04:31:45 -0400563 if (err == HTTP_REAUTH)
564 credential_fill(&http_auth);
Jeff Kingb81401c2012-08-27 09:27:15 -0400565 } while (err == HTTP_REAUTH);
566 if (err != HTTP_OK)
567 return -1;
Brian M. Carlsonc80d96c2013-10-31 02:36:51 -0400568
569 if (results.auth_avail & CURLAUTH_GSSNEGOTIATE)
570 needs_100_continue = 1;
Shawn O. Pearce206b0992011-02-15 08:57:24 -0800571 }
572
Jeff Kingabf8df82012-10-12 03:35:33 -0400573 headers = curl_slist_append(headers, rpc->hdr_content_type);
574 headers = curl_slist_append(headers, rpc->hdr_accept);
Brian M. Carlsonc80d96c2013-10-31 02:36:51 -0400575 headers = curl_slist_append(headers, needs_100_continue ?
576 "Expect: 100-continue" : "Expect:");
Jeff Kingabf8df82012-10-12 03:35:33 -0400577
578retry:
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700579 slot = get_active_slot();
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700580
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700581 curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
Martin Storsjöd21f9792009-11-23 11:03:28 +0800582 curl_easy_setopt(slot->curl, CURLOPT_POST, 1);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700583 curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
Shawn O. Pearceaa90b962012-09-19 16:12:02 -0700584 curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip");
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700585
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700586 if (large_request) {
587 /* The request body is large and the size cannot be predicted.
588 * We must use chunked encoding to send it.
589 */
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700590 headers = curl_slist_append(headers, "Transfer-Encoding: chunked");
Martin Storsjö6c81a992009-12-01 12:33:39 +0200591 rpc->initial_buffer = 1;
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700592 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, rpc_out);
593 curl_easy_setopt(slot->curl, CURLOPT_INFILE, rpc);
Martin Storsjö6c81a992009-12-01 12:33:39 +0200594#ifndef NO_CURL_IOCTL
595 curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, rpc_ioctl);
596 curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, rpc);
597#endif
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700598 if (options.verbosity > 1) {
599 fprintf(stderr, "POST %s (chunked)\n", rpc->service_name);
600 fflush(stderr);
601 }
602
Jeff King2e736fd2012-10-31 07:29:16 -0400603 } else if (gzip_body) {
604 /*
605 * If we are looping to retry authentication, then the previous
606 * run will have set up the headers and gzip buffer already,
607 * and we just need to send it.
608 */
609 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body);
610 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size);
611
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700612 } else if (use_gzip && 1024 < rpc->len) {
613 /* The client backend isn't giving us compressed data so
614 * we can try to deflate it ourselves, this may save on.
615 * the transfer time.
616 */
Junio C Hamanoef49a7a2011-06-10 11:52:15 -0700617 git_zstream stream;
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700618 int ret;
619
Junio C Hamano55bb5c92011-06-10 10:55:10 -0700620 git_deflate_init_gzip(&stream, Z_BEST_COMPRESSION);
Jeff Kingdf126e12012-10-31 07:20:15 -0400621 gzip_size = git_deflate_bound(&stream, rpc->len);
622 gzip_body = xmalloc(gzip_size);
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700623
624 stream.next_in = (unsigned char *)rpc->buf;
625 stream.avail_in = rpc->len;
626 stream.next_out = (unsigned char *)gzip_body;
Jeff Kingdf126e12012-10-31 07:20:15 -0400627 stream.avail_out = gzip_size;
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700628
Junio C Hamano55bb5c92011-06-10 10:55:10 -0700629 ret = git_deflate(&stream, Z_FINISH);
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700630 if (ret != Z_STREAM_END)
631 die("cannot deflate request; zlib deflate error %d", ret);
632
Junio C Hamano55bb5c92011-06-10 10:55:10 -0700633 ret = git_deflate_end_gently(&stream);
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700634 if (ret != Z_OK)
635 die("cannot deflate request; zlib end error %d", ret);
636
Jeff Kingdf126e12012-10-31 07:20:15 -0400637 gzip_size = stream.total_out;
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700638
639 headers = curl_slist_append(headers, "Content-Encoding: gzip");
640 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body);
Jeff Kingdf126e12012-10-31 07:20:15 -0400641 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size);
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700642
643 if (options.verbosity > 1) {
644 fprintf(stderr, "POST %s (gzip %lu to %lu bytes)\n",
645 rpc->service_name,
Jeff Kingdf126e12012-10-31 07:20:15 -0400646 (unsigned long)rpc->len, (unsigned long)gzip_size);
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700647 fflush(stderr);
648 }
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700649 } else {
650 /* We know the complete request size in advance, use the
651 * more normal Content-Length approach.
652 */
653 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, rpc->buf);
654 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, rpc->len);
655 if (options.verbosity > 1) {
656 fprintf(stderr, "POST %s (%lu bytes)\n",
657 rpc->service_name, (unsigned long)rpc->len);
658 fflush(stderr);
659 }
660 }
661
662 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
663 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, rpc_in);
664 curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc);
665
Jeff King3a347ed2013-10-31 02:36:26 -0400666 err = run_slot(slot, NULL);
Jeff King2501aff2013-09-28 04:31:45 -0400667 if (err == HTTP_REAUTH && !large_request) {
668 credential_fill(&http_auth);
Jeff Kingabf8df82012-10-12 03:35:33 -0400669 goto retry;
Jeff King2501aff2013-09-28 04:31:45 -0400670 }
Jeff Kingb81401c2012-08-27 09:27:15 -0400671 if (err != HTTP_OK)
672 err = -1;
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700673
674 curl_slist_free_all(headers);
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700675 free(gzip_body);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700676 return err;
677}
678
679static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
680{
681 const char *svc = rpc->service_name;
682 struct strbuf buf = STRBUF_INIT;
Ivan Todoroski81507492012-04-02 17:14:44 +0200683 struct strbuf *preamble = rpc->stdin_preamble;
René Scharfed3180272014-08-19 21:09:35 +0200684 struct child_process client = CHILD_PROCESS_INIT;
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700685 int err = 0;
686
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700687 client.in = -1;
688 client.out = -1;
689 client.git_cmd = 1;
690 client.argv = rpc->argv;
691 if (start_command(&client))
692 exit(1);
Ivan Todoroski81507492012-04-02 17:14:44 +0200693 if (preamble)
694 write_or_die(client.in, preamble->buf, preamble->len);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700695 if (heads)
696 write_or_die(client.in, heads->buf, heads->len);
697
698 rpc->alloc = http_post_buffer;
699 rpc->buf = xmalloc(rpc->alloc);
700 rpc->in = client.in;
701 rpc->out = client.out;
702 strbuf_init(&rpc->result, 0);
703
Jeff Kingb227bbc2013-09-28 04:35:25 -0400704 strbuf_addf(&buf, "%s%s", url.buf, svc);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700705 rpc->service_url = strbuf_detach(&buf, NULL);
706
707 strbuf_addf(&buf, "Content-Type: application/x-%s-request", svc);
708 rpc->hdr_content_type = strbuf_detach(&buf, NULL);
709
Shawn O. Pearce8efa5f62010-01-12 09:54:04 -0800710 strbuf_addf(&buf, "Accept: application/x-%s-result", svc);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700711 rpc->hdr_accept = strbuf_detach(&buf, NULL);
712
713 while (!err) {
Jeff King4981fe72013-02-23 17:31:34 -0500714 int n = packet_read(rpc->out, NULL, NULL, rpc->buf, rpc->alloc, 0);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700715 if (!n)
716 break;
717 rpc->pos = 0;
718 rpc->len = n;
719 err |= post_rpc(rpc);
720 }
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700721
722 close(client.in);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700723 client.in = -1;
Shawn O. Pearce6cdf0222011-10-04 16:20:19 -0700724 if (!err) {
725 strbuf_read(&rpc->result, client.out, 0);
726 } else {
727 char buf[4096];
728 for (;;)
729 if (xread(client.out, buf, sizeof(buf)) <= 0)
730 break;
731 }
Shawn O. Pearceb4ee10f2010-08-06 14:19:44 -0700732
733 close(client.out);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700734 client.out = -1;
735
736 err |= finish_command(&client);
737 free(rpc->service_url);
738 free(rpc->hdr_content_type);
739 free(rpc->hdr_accept);
740 free(rpc->buf);
741 strbuf_release(&buf);
742 return err;
743}
744
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700745static int fetch_dumb(int nr_heads, struct ref **to_fetch)
746{
Tay Ray Chuan26e1e0b2010-03-02 18:49:31 +0800747 struct walker *walker;
Jeff Kingb32fa952016-02-22 17:44:25 -0500748 char **targets;
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700749 int ret, i;
750
Jeff Kingb32fa952016-02-22 17:44:25 -0500751 ALLOC_ARRAY(targets, nr_heads);
Nguyễn Thái Ngọc Duy508ea882016-06-12 17:53:59 +0700752 if (options.depth || options.deepen_since)
753 die("dumb http transport does not support shallow capabilities");
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700754 for (i = 0; i < nr_heads; i++)
brian m. carlsonf4e54d02015-11-10 02:22:20 +0000755 targets[i] = xstrdup(oid_to_hex(&to_fetch[i]->old_oid));
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700756
Jeff Kingb227bbc2013-09-28 04:35:25 -0400757 walker = get_http_walker(url.buf);
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700758 walker->get_all = 1;
759 walker->get_tree = 1;
760 walker->get_history = 1;
Shawn O. Pearceef08ef92009-10-30 17:47:29 -0700761 walker->get_verbosely = options.verbosity >= 3;
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700762 walker->get_recover = 0;
763 ret = walker_fetch(walker, nr_heads, targets, NULL, NULL);
Tay Ray Chuan26e1e0b2010-03-02 18:49:31 +0800764 walker_free(walker);
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700765
766 for (i = 0; i < nr_heads; i++)
767 free(targets[i]);
768 free(targets);
769
Jeff Kingb725b272014-07-09 17:47:05 -0400770 return ret ? error("fetch failed.") : 0;
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700771}
772
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700773static int fetch_git(struct discovery *heads,
774 int nr_heads, struct ref **to_fetch)
775{
776 struct rpc_state rpc;
Ivan Todoroski81507492012-04-02 17:14:44 +0200777 struct strbuf preamble = STRBUF_INIT;
Nguyễn Thái Ngọc Duyb5f62eb2016-06-12 17:53:43 +0700778 int i, err;
779 struct argv_array args = ARGV_ARRAY_INIT;
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700780
Nguyễn Thái Ngọc Duyb5f62eb2016-06-12 17:53:43 +0700781 argv_array_pushl(&args, "fetch-pack", "--stateless-rpc",
782 "--stdin", "--lock-pack", NULL);
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700783 if (options.followtags)
Nguyễn Thái Ngọc Duyb5f62eb2016-06-12 17:53:43 +0700784 argv_array_push(&args, "--include-tag");
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700785 if (options.thin)
Nguyễn Thái Ngọc Duyb5f62eb2016-06-12 17:53:43 +0700786 argv_array_push(&args, "--thin");
787 if (options.verbosity >= 3)
788 argv_array_pushl(&args, "-v", "-v", NULL);
Nguyễn Thái Ngọc Duy9ba38042013-07-21 15:18:05 +0700789 if (options.check_self_contained_and_connected)
Nguyễn Thái Ngọc Duyb5f62eb2016-06-12 17:53:43 +0700790 argv_array_push(&args, "--check-self-contained-and-connected");
Nguyễn Thái Ngọc Duy16094882013-12-05 20:02:50 +0700791 if (options.cloning)
Nguyễn Thái Ngọc Duyb5f62eb2016-06-12 17:53:43 +0700792 argv_array_push(&args, "--cloning");
Nguyễn Thái Ngọc Duy16094882013-12-05 20:02:50 +0700793 if (options.update_shallow)
Nguyễn Thái Ngọc Duyb5f62eb2016-06-12 17:53:43 +0700794 argv_array_push(&args, "--update-shallow");
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700795 if (!options.progress)
Nguyễn Thái Ngọc Duyb5f62eb2016-06-12 17:53:43 +0700796 argv_array_push(&args, "--no-progress");
797 if (options.depth)
798 argv_array_pushf(&args, "--depth=%lu", options.depth);
Nguyễn Thái Ngọc Duy508ea882016-06-12 17:53:59 +0700799 if (options.deepen_since)
800 argv_array_pushf(&args, "--shallow-since=%s", options.deepen_since);
Nguyễn Thái Ngọc Duya45a2602016-06-12 17:54:04 +0700801 for (i = 0; i < options.deepen_not.nr; i++)
802 argv_array_pushf(&args, "--shallow-exclude=%s",
803 options.deepen_not.items[i].string);
Nguyễn Thái Ngọc Duycccf74e2016-06-12 17:54:09 +0700804 if (options.deepen_relative && options.depth)
805 argv_array_push(&args, "--deepen-relative");
Nguyễn Thái Ngọc Duyb5f62eb2016-06-12 17:53:43 +0700806 argv_array_push(&args, url.buf);
Ivan Todoroski81507492012-04-02 17:14:44 +0200807
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700808 for (i = 0; i < nr_heads; i++) {
809 struct ref *ref = to_fetch[i];
Jeff King94ee8e22015-01-28 12:58:50 -0500810 if (!*ref->name)
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700811 die("cannot fetch by sha1 over smart http");
Nguyễn Thái Ngọc Duy58f2ed02013-12-05 20:02:49 +0700812 packet_buf_write(&preamble, "%s %s\n",
brian m. carlsonf4e54d02015-11-10 02:22:20 +0000813 oid_to_hex(&ref->old_oid), ref->name);
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700814 }
Ivan Todoroski81507492012-04-02 17:14:44 +0200815 packet_buf_flush(&preamble);
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700816
817 memset(&rpc, 0, sizeof(rpc));
818 rpc.service_name = "git-upload-pack",
Nguyễn Thái Ngọc Duyb5f62eb2016-06-12 17:53:43 +0700819 rpc.argv = args.argv;
Ivan Todoroski81507492012-04-02 17:14:44 +0200820 rpc.stdin_preamble = &preamble;
Shawn O. Pearceb8538602009-10-30 17:47:43 -0700821 rpc.gzip_request = 1;
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700822
823 err = rpc_service(&rpc, heads);
824 if (rpc.result.len)
Jeff Kingcdf4fb82013-02-20 15:01:56 -0500825 write_or_die(1, rpc.result.buf, rpc.result.len);
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700826 strbuf_release(&rpc.result);
Ivan Todoroski81507492012-04-02 17:14:44 +0200827 strbuf_release(&preamble);
Nguyễn Thái Ngọc Duyb5f62eb2016-06-12 17:53:43 +0700828 argv_array_clear(&args);
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700829 return err;
830}
831
832static int fetch(int nr_heads, struct ref **to_fetch)
833{
Jeff King2a455202013-02-20 15:07:19 -0500834 struct discovery *d = discover_refs("git-upload-pack", 0);
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700835 if (d->proto_git)
836 return fetch_git(d, nr_heads, to_fetch);
837 else
838 return fetch_dumb(nr_heads, to_fetch);
839}
840
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700841static void parse_fetch(struct strbuf *buf)
842{
843 struct ref **to_fetch = NULL;
844 struct ref *list_head = NULL;
845 struct ref **list = &list_head;
846 int alloc_heads = 0, nr_heads = 0;
847
848 do {
Jeff King95b567c2014-06-18 15:48:29 -0400849 const char *p;
850 if (skip_prefix(buf->buf, "fetch ", &p)) {
851 const char *name;
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700852 struct ref *ref;
brian m. carlson8338c912015-11-10 02:22:22 +0000853 struct object_id old_oid;
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700854
brian m. carlson8338c912015-11-10 02:22:22 +0000855 if (get_oid_hex(p, &old_oid))
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700856 die("protocol error: expected sha/ref, got %s'", p);
brian m. carlson8338c912015-11-10 02:22:22 +0000857 if (p[GIT_SHA1_HEXSZ] == ' ')
858 name = p + GIT_SHA1_HEXSZ + 1;
859 else if (!p[GIT_SHA1_HEXSZ])
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700860 name = "";
861 else
862 die("protocol error: expected sha/ref, got %s'", p);
863
864 ref = alloc_ref(name);
brian m. carlson8338c912015-11-10 02:22:22 +0000865 oidcpy(&ref->old_oid, &old_oid);
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700866
867 *list = ref;
868 list = &ref->next;
869
870 ALLOC_GROW(to_fetch, nr_heads + 1, alloc_heads);
871 to_fetch[nr_heads++] = ref;
872 }
873 else
874 die("http transport does not support %s", buf->buf);
875
876 strbuf_reset(buf);
Junio C Hamano8f309ae2016-01-13 15:31:17 -0800877 if (strbuf_getline_lf(buf, stdin) == EOF)
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700878 return;
879 if (!*buf->buf)
880 break;
881 } while (1);
882
Shawn O. Pearce249b2002009-10-30 17:47:42 -0700883 if (fetch(nr_heads, to_fetch))
Shawn O. Pearce292ce462009-10-30 17:47:28 -0700884 exit(128); /* error already reported */
885 free_refs(list_head);
886 free(to_fetch);
887
888 printf("\n");
889 fflush(stdout);
890 strbuf_reset(buf);
891}
892
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700893static int push_dav(int nr_spec, char **specs)
894{
Jeff King850d2fe2016-02-22 17:44:21 -0500895 struct child_process child = CHILD_PROCESS_INIT;
896 size_t i;
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700897
Jeff King850d2fe2016-02-22 17:44:21 -0500898 child.git_cmd = 1;
899 argv_array_push(&child.args, "http-push");
900 argv_array_push(&child.args, "--helper-status");
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700901 if (options.dry_run)
Jeff King850d2fe2016-02-22 17:44:21 -0500902 argv_array_push(&child.args, "--dry-run");
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700903 if (options.verbosity > 1)
Jeff King850d2fe2016-02-22 17:44:21 -0500904 argv_array_push(&child.args, "--verbose");
905 argv_array_push(&child.args, url.buf);
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700906 for (i = 0; i < nr_spec; i++)
Jeff King850d2fe2016-02-22 17:44:21 -0500907 argv_array_push(&child.args, specs[i]);
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700908
Jeff King850d2fe2016-02-22 17:44:21 -0500909 if (run_command(&child))
910 die("git-http-push failed");
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700911 return 0;
912}
913
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700914static int push_git(struct discovery *heads, int nr_spec, char **specs)
915{
916 struct rpc_state rpc;
Junio C Hamano222b1212013-07-08 22:16:31 -0700917 int i, err;
918 struct argv_array args;
Junio C Hamano05c1eb12013-08-02 15:14:50 -0700919 struct string_list_item *cas_option;
Jeff King26be19b2014-08-21 08:21:20 -0400920 struct strbuf preamble = STRBUF_INIT;
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700921
Junio C Hamano222b1212013-07-08 22:16:31 -0700922 argv_array_init(&args);
923 argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status",
924 NULL);
925
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700926 if (options.thin)
Junio C Hamano222b1212013-07-08 22:16:31 -0700927 argv_array_push(&args, "--thin");
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700928 if (options.dry_run)
Junio C Hamano222b1212013-07-08 22:16:31 -0700929 argv_array_push(&args, "--dry-run");
Dave Borowitz30261092015-08-19 11:26:46 -0400930 if (options.push_cert == SEND_PACK_PUSH_CERT_ALWAYS)
931 argv_array_push(&args, "--signed=yes");
932 else if (options.push_cert == SEND_PACK_PUSH_CERT_IF_ASKED)
933 argv_array_push(&args, "--signed=if-asked");
Clemens Buchacherc207e342012-01-08 22:06:20 +0100934 if (options.verbosity == 0)
Junio C Hamano222b1212013-07-08 22:16:31 -0700935 argv_array_push(&args, "--quiet");
Clemens Buchacherc207e342012-01-08 22:06:20 +0100936 else if (options.verbosity > 1)
Junio C Hamano222b1212013-07-08 22:16:31 -0700937 argv_array_push(&args, "--verbose");
938 argv_array_push(&args, options.progress ? "--progress" : "--no-progress");
Junio C Hamano05c1eb12013-08-02 15:14:50 -0700939 for_each_string_list_item(cas_option, &cas_options)
Junio C Hamano2233ad42013-09-09 14:30:29 -0700940 argv_array_push(&args, cas_option->string);
Jeff Kingb227bbc2013-09-28 04:35:25 -0400941 argv_array_push(&args, url.buf);
Jeff King26be19b2014-08-21 08:21:20 -0400942
943 argv_array_push(&args, "--stdin");
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700944 for (i = 0; i < nr_spec; i++)
Jeff King26be19b2014-08-21 08:21:20 -0400945 packet_buf_write(&preamble, "%s\n", specs[i]);
946 packet_buf_flush(&preamble);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700947
948 memset(&rpc, 0, sizeof(rpc));
949 rpc.service_name = "git-receive-pack",
Junio C Hamano222b1212013-07-08 22:16:31 -0700950 rpc.argv = args.argv;
Jeff King26be19b2014-08-21 08:21:20 -0400951 rpc.stdin_preamble = &preamble;
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700952
953 err = rpc_service(&rpc, heads);
954 if (rpc.result.len)
Jeff Kingcdf4fb82013-02-20 15:01:56 -0500955 write_or_die(1, rpc.result.buf, rpc.result.len);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700956 strbuf_release(&rpc.result);
Jeff King26be19b2014-08-21 08:21:20 -0400957 strbuf_release(&preamble);
Junio C Hamano222b1212013-07-08 22:16:31 -0700958 argv_array_clear(&args);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700959 return err;
960}
961
962static int push(int nr_spec, char **specs)
963{
Jeff King2a455202013-02-20 15:07:19 -0500964 struct discovery *heads = discover_refs("git-receive-pack", 1);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -0700965 int ret;
966
967 if (heads->proto_git)
968 ret = push_git(heads, nr_spec, specs);
969 else
970 ret = push_dav(nr_spec, specs);
971 free_discovery(heads);
972 return ret;
973}
974
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700975static void parse_push(struct strbuf *buf)
976{
977 char **specs = NULL;
Shawn O. Pearce5238cbf2012-01-19 19:12:09 -0800978 int alloc_spec = 0, nr_spec = 0, i, ret;
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700979
980 do {
Christian Couder59556542013-11-30 21:55:40 +0100981 if (starts_with(buf->buf, "push ")) {
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700982 ALLOC_GROW(specs, nr_spec + 1, alloc_spec);
983 specs[nr_spec++] = xstrdup(buf->buf + 5);
984 }
985 else
986 die("http transport does not support %s", buf->buf);
987
988 strbuf_reset(buf);
Junio C Hamano8f309ae2016-01-13 15:31:17 -0800989 if (strbuf_getline_lf(buf, stdin) == EOF)
Jim Meyeringdc4cd762011-06-20 09:40:06 +0200990 goto free_specs;
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700991 if (!*buf->buf)
992 break;
993 } while (1);
994
Shawn O. Pearce5238cbf2012-01-19 19:12:09 -0800995 ret = push(nr_spec, specs);
Shawn O. Pearceae4efe12009-10-30 17:47:30 -0700996 printf("\n");
997 fflush(stdout);
Jim Meyeringdc4cd762011-06-20 09:40:06 +0200998
Shawn O. Pearce5238cbf2012-01-19 19:12:09 -0800999 if (ret)
1000 exit(128); /* error already reported */
1001
Jim Meyeringdc4cd762011-06-20 09:40:06 +02001002 free_specs:
1003 for (i = 0; i < nr_spec; i++)
1004 free(specs[i]);
1005 free(specs);
Shawn O. Pearceae4efe12009-10-30 17:47:30 -07001006}
1007
Jeff King3f2e2292016-07-01 01:58:58 -04001008int cmd_main(int argc, const char **argv)
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001009{
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001010 struct strbuf buf = STRBUF_INIT;
Daniel Barkalowa45d3d72009-11-03 21:52:35 -05001011 int nongit;
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001012
Daniel Barkalowa45d3d72009-11-03 21:52:35 -05001013 setup_git_directory_gently(&nongit);
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001014 if (argc < 2) {
Jeff Kingcdaa4e92014-07-09 17:47:20 -04001015 error("remote-curl: usage: git remote-curl <remote> [<url>]");
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001016 return 1;
1017 }
1018
Shawn O. Pearceef08ef92009-10-30 17:47:29 -07001019 options.verbosity = 1;
1020 options.progress = !!isatty(2);
Shawn O. Pearcede1a2fd2009-10-30 17:47:41 -07001021 options.thin = 1;
Nguyễn Thái Ngọc Duya45a2602016-06-12 17:54:04 +07001022 string_list_init(&options.deepen_not, 1);
Shawn O. Pearceef08ef92009-10-30 17:47:29 -07001023
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001024 remote = remote_get(argv[1]);
1025
1026 if (argc > 2) {
Jeff Kingb227bbc2013-09-28 04:35:25 -04001027 end_url_with_slash(&url, argv[2]);
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001028 } else {
Jeff Kingb227bbc2013-09-28 04:35:25 -04001029 end_url_with_slash(&url, remote->url[0]);
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001030 }
1031
Jeff Kingb227bbc2013-09-28 04:35:25 -04001032 http_init(remote, url.buf, 0);
Tay Ray Chuan888692b2010-03-02 18:49:29 +08001033
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001034 do {
Jeff King95b567c2014-06-18 15:48:29 -04001035 const char *arg;
1036
Junio C Hamano8f309ae2016-01-13 15:31:17 -08001037 if (strbuf_getline_lf(&buf, stdin) == EOF) {
Sverre Rabbelier1843f0c2011-07-16 15:03:29 +02001038 if (ferror(stdin))
Jeff Kingcdaa4e92014-07-09 17:47:20 -04001039 error("remote-curl: error reading command stream from git");
Sverre Rabbelier1843f0c2011-07-16 15:03:29 +02001040 return 1;
1041 }
1042 if (buf.len == 0)
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001043 break;
Christian Couder59556542013-11-30 21:55:40 +01001044 if (starts_with(buf.buf, "fetch ")) {
Daniel Barkalowa45d3d72009-11-03 21:52:35 -05001045 if (nongit)
Jeff Kingcdaa4e92014-07-09 17:47:20 -04001046 die("remote-curl: fetch attempted without a local repo");
Shawn O. Pearce292ce462009-10-30 17:47:28 -07001047 parse_fetch(&buf);
1048
Christian Couder59556542013-11-30 21:55:40 +01001049 } else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {
Shawn O. Pearce97cc7bc2009-10-30 17:47:40 -07001050 int for_push = !!strstr(buf.buf + 4, "for-push");
1051 output_refs(get_refs(for_push));
Shawn O. Pearceae4efe12009-10-30 17:47:30 -07001052
Christian Couder59556542013-11-30 21:55:40 +01001053 } else if (starts_with(buf.buf, "push ")) {
Shawn O. Pearceae4efe12009-10-30 17:47:30 -07001054 parse_push(&buf);
1055
Jeff King95b567c2014-06-18 15:48:29 -04001056 } else if (skip_prefix(buf.buf, "option ", &arg)) {
1057 char *value = strchr(arg, ' ');
Shawn O. Pearceef08ef92009-10-30 17:47:29 -07001058 int result;
1059
1060 if (value)
1061 *value++ = '\0';
1062 else
1063 value = "true";
1064
Jeff King95b567c2014-06-18 15:48:29 -04001065 result = set_option(arg, value);
Shawn O. Pearceef08ef92009-10-30 17:47:29 -07001066 if (!result)
1067 printf("ok\n");
1068 else if (result < 0)
1069 printf("error invalid value\n");
1070 else
1071 printf("unsupported\n");
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001072 fflush(stdout);
Shawn O. Pearceef08ef92009-10-30 17:47:29 -07001073
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001074 } else if (!strcmp(buf.buf, "capabilities")) {
1075 printf("fetch\n");
Shawn O. Pearceef08ef92009-10-30 17:47:29 -07001076 printf("option\n");
Shawn O. Pearceae4efe12009-10-30 17:47:30 -07001077 printf("push\n");
Nguyễn Thái Ngọc Duy9ba38042013-07-21 15:18:05 +07001078 printf("check-connectivity\n");
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001079 printf("\n");
1080 fflush(stdout);
1081 } else {
Jeff Kingcdaa4e92014-07-09 17:47:20 -04001082 error("remote-curl: unknown command '%s' from git", buf.buf);
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001083 return 1;
1084 }
1085 strbuf_reset(&buf);
1086 } while (1);
Tay Ray Chuan888692b2010-03-02 18:49:29 +08001087
1088 http_cleanup();
1089
Daniel Barkalowa2d725b2009-08-05 01:01:56 -04001090 return 0;
1091}