fetch: define shallow boundary with --shallow-exclude
[git] / remote-curl.c
1 #include "cache.h"
2 #include "remote.h"
3 #include "strbuf.h"
4 #include "walker.h"
5 #include "http.h"
6 #include "exec_cmd.h"
7 #include "run-command.h"
8 #include "pkt-line.h"
9 #include "string-list.h"
10 #include "sideband.h"
11 #include "argv-array.h"
12 #include "credential.h"
13 #include "sha1-array.h"
14 #include "send-pack.h"
15
16 static struct remote *remote;
17 /* always ends with a trailing slash */
18 static struct strbuf url = STRBUF_INIT;
19
20 struct options {
21         int verbosity;
22         unsigned long depth;
23         char *deepen_since;
24         struct string_list deepen_not;
25         unsigned progress : 1,
26                 check_self_contained_and_connected : 1,
27                 cloning : 1,
28                 update_shallow : 1,
29                 followtags : 1,
30                 dry_run : 1,
31                 thin : 1,
32                 /* One of the SEND_PACK_PUSH_CERT_* constants. */
33                 push_cert : 2;
34 };
35 static struct options options;
36 static struct string_list cas_options = STRING_LIST_INIT_DUP;
37
38 static int set_option(const char *name, const char *value)
39 {
40         if (!strcmp(name, "verbosity")) {
41                 char *end;
42                 int v = strtol(value, &end, 10);
43                 if (value == end || *end)
44                         return -1;
45                 options.verbosity = v;
46                 return 0;
47         }
48         else if (!strcmp(name, "progress")) {
49                 if (!strcmp(value, "true"))
50                         options.progress = 1;
51                 else if (!strcmp(value, "false"))
52                         options.progress = 0;
53                 else
54                         return -1;
55                 return 0;
56         }
57         else if (!strcmp(name, "depth")) {
58                 char *end;
59                 unsigned long v = strtoul(value, &end, 10);
60                 if (value == end || *end)
61                         return -1;
62                 options.depth = v;
63                 return 0;
64         }
65         else if (!strcmp(name, "deepen-since")) {
66                 options.deepen_since = xstrdup(value);
67                 return 0;
68         }
69         else if (!strcmp(name, "deepen-not")) {
70                 string_list_append(&options.deepen_not, value);
71                 return 0;
72         }
73         else if (!strcmp(name, "followtags")) {
74                 if (!strcmp(value, "true"))
75                         options.followtags = 1;
76                 else if (!strcmp(value, "false"))
77                         options.followtags = 0;
78                 else
79                         return -1;
80                 return 0;
81         }
82         else if (!strcmp(name, "dry-run")) {
83                 if (!strcmp(value, "true"))
84                         options.dry_run = 1;
85                 else if (!strcmp(value, "false"))
86                         options.dry_run = 0;
87                 else
88                         return -1;
89                 return 0;
90         }
91         else if (!strcmp(name, "check-connectivity")) {
92                 if (!strcmp(value, "true"))
93                         options.check_self_contained_and_connected = 1;
94                 else if (!strcmp(value, "false"))
95                         options.check_self_contained_and_connected = 0;
96                 else
97                         return -1;
98                 return 0;
99         }
100         else if (!strcmp(name, "cas")) {
101                 struct strbuf val = STRBUF_INIT;
102                 strbuf_addf(&val, "--" CAS_OPT_NAME "=%s", value);
103                 string_list_append(&cas_options, val.buf);
104                 strbuf_release(&val);
105                 return 0;
106         } else if (!strcmp(name, "cloning")) {
107                 if (!strcmp(value, "true"))
108                         options.cloning = 1;
109                 else if (!strcmp(value, "false"))
110                         options.cloning = 0;
111                 else
112                         return -1;
113                 return 0;
114         } else if (!strcmp(name, "update-shallow")) {
115                 if (!strcmp(value, "true"))
116                         options.update_shallow = 1;
117                 else if (!strcmp(value, "false"))
118                         options.update_shallow = 0;
119                 else
120                         return -1;
121                 return 0;
122         } else if (!strcmp(name, "pushcert")) {
123                 if (!strcmp(value, "true"))
124                         options.push_cert = SEND_PACK_PUSH_CERT_ALWAYS;
125                 else if (!strcmp(value, "false"))
126                         options.push_cert = SEND_PACK_PUSH_CERT_NEVER;
127                 else if (!strcmp(value, "if-asked"))
128                         options.push_cert = SEND_PACK_PUSH_CERT_IF_ASKED;
129                 else
130                         return -1;
131                 return 0;
132         } else {
133                 return 1 /* unsupported */;
134         }
135 }
136
137 struct discovery {
138         const char *service;
139         char *buf_alloc;
140         char *buf;
141         size_t len;
142         struct ref *refs;
143         struct sha1_array shallow;
144         unsigned proto_git : 1;
145 };
146 static struct discovery *last_discovery;
147
148 static struct ref *parse_git_refs(struct discovery *heads, int for_push)
149 {
150         struct ref *list = NULL;
151         get_remote_heads(-1, heads->buf, heads->len, &list,
152                          for_push ? REF_NORMAL : 0, NULL, &heads->shallow);
153         return list;
154 }
155
156 static struct ref *parse_info_refs(struct discovery *heads)
157 {
158         char *data, *start, *mid;
159         char *ref_name;
160         int i = 0;
161
162         struct ref *refs = NULL;
163         struct ref *ref = NULL;
164         struct ref *last_ref = NULL;
165
166         data = heads->buf;
167         start = NULL;
168         mid = data;
169         while (i < heads->len) {
170                 if (!start) {
171                         start = &data[i];
172                 }
173                 if (data[i] == '\t')
174                         mid = &data[i];
175                 if (data[i] == '\n') {
176                         if (mid - start != 40)
177                                 die("%sinfo/refs not valid: is this a git repository?",
178                                     url.buf);
179                         data[i] = 0;
180                         ref_name = mid + 1;
181                         ref = alloc_ref(ref_name);
182                         get_oid_hex(start, &ref->old_oid);
183                         if (!refs)
184                                 refs = ref;
185                         if (last_ref)
186                                 last_ref->next = ref;
187                         last_ref = ref;
188                         start = NULL;
189                 }
190                 i++;
191         }
192
193         ref = alloc_ref("HEAD");
194         if (!http_fetch_ref(url.buf, ref) &&
195             !resolve_remote_symref(ref, refs)) {
196                 ref->next = refs;
197                 refs = ref;
198         } else {
199                 free(ref);
200         }
201
202         return refs;
203 }
204
205 static void free_discovery(struct discovery *d)
206 {
207         if (d) {
208                 if (d == last_discovery)
209                         last_discovery = NULL;
210                 free(d->shallow.sha1);
211                 free(d->buf_alloc);
212                 free_refs(d->refs);
213                 free(d);
214         }
215 }
216
217 static int show_http_message(struct strbuf *type, struct strbuf *charset,
218                              struct strbuf *msg)
219 {
220         const char *p, *eol;
221
222         /*
223          * We only show text/plain parts, as other types are likely
224          * to be ugly to look at on the user's terminal.
225          */
226         if (strcmp(type->buf, "text/plain"))
227                 return -1;
228         if (charset->len)
229                 strbuf_reencode(msg, charset->buf, get_log_output_encoding());
230
231         strbuf_trim(msg);
232         if (!msg->len)
233                 return -1;
234
235         p = msg->buf;
236         do {
237                 eol = strchrnul(p, '\n');
238                 fprintf(stderr, "remote: %.*s\n", (int)(eol - p), p);
239                 p = eol + 1;
240         } while(*eol);
241         return 0;
242 }
243
244 static struct discovery *discover_refs(const char *service, int for_push)
245 {
246         struct strbuf exp = STRBUF_INIT;
247         struct strbuf type = STRBUF_INIT;
248         struct strbuf charset = STRBUF_INIT;
249         struct strbuf buffer = STRBUF_INIT;
250         struct strbuf refs_url = STRBUF_INIT;
251         struct strbuf effective_url = STRBUF_INIT;
252         struct discovery *last = last_discovery;
253         int http_ret, maybe_smart = 0;
254         struct http_get_options options;
255
256         if (last && !strcmp(service, last->service))
257                 return last;
258         free_discovery(last);
259
260         strbuf_addf(&refs_url, "%sinfo/refs", url.buf);
261         if ((starts_with(url.buf, "http://") || starts_with(url.buf, "https://")) &&
262              git_env_bool("GIT_SMART_HTTP", 1)) {
263                 maybe_smart = 1;
264                 if (!strchr(url.buf, '?'))
265                         strbuf_addch(&refs_url, '?');
266                 else
267                         strbuf_addch(&refs_url, '&');
268                 strbuf_addf(&refs_url, "service=%s", service);
269         }
270
271         memset(&options, 0, sizeof(options));
272         options.content_type = &type;
273         options.charset = &charset;
274         options.effective_url = &effective_url;
275         options.base_url = &url;
276         options.no_cache = 1;
277         options.keep_error = 1;
278
279         http_ret = http_get_strbuf(refs_url.buf, &buffer, &options);
280         switch (http_ret) {
281         case HTTP_OK:
282                 break;
283         case HTTP_MISSING_TARGET:
284                 show_http_message(&type, &charset, &buffer);
285                 die("repository '%s' not found", url.buf);
286         case HTTP_NOAUTH:
287                 show_http_message(&type, &charset, &buffer);
288                 die("Authentication failed for '%s'", url.buf);
289         default:
290                 show_http_message(&type, &charset, &buffer);
291                 die("unable to access '%s': %s", url.buf, curl_errorstr);
292         }
293
294         last= xcalloc(1, sizeof(*last_discovery));
295         last->service = service;
296         last->buf_alloc = strbuf_detach(&buffer, &last->len);
297         last->buf = last->buf_alloc;
298
299         strbuf_addf(&exp, "application/x-%s-advertisement", service);
300         if (maybe_smart &&
301             (5 <= last->len && last->buf[4] == '#') &&
302             !strbuf_cmp(&exp, &type)) {
303                 char *line;
304
305                 /*
306                  * smart HTTP response; validate that the service
307                  * pkt-line matches our request.
308                  */
309                 line = packet_read_line_buf(&last->buf, &last->len, NULL);
310
311                 strbuf_reset(&exp);
312                 strbuf_addf(&exp, "# service=%s", service);
313                 if (strcmp(line, exp.buf))
314                         die("invalid server response; got '%s'", line);
315                 strbuf_release(&exp);
316
317                 /* The header can include additional metadata lines, up
318                  * until a packet flush marker.  Ignore these now, but
319                  * in the future we might start to scan them.
320                  */
321                 while (packet_read_line_buf(&last->buf, &last->len, NULL))
322                         ;
323
324                 last->proto_git = 1;
325         }
326
327         if (last->proto_git)
328                 last->refs = parse_git_refs(last, for_push);
329         else
330                 last->refs = parse_info_refs(last);
331
332         strbuf_release(&refs_url);
333         strbuf_release(&exp);
334         strbuf_release(&type);
335         strbuf_release(&charset);
336         strbuf_release(&effective_url);
337         strbuf_release(&buffer);
338         last_discovery = last;
339         return last;
340 }
341
342 static struct ref *get_refs(int for_push)
343 {
344         struct discovery *heads;
345
346         if (for_push)
347                 heads = discover_refs("git-receive-pack", for_push);
348         else
349                 heads = discover_refs("git-upload-pack", for_push);
350
351         return heads->refs;
352 }
353
354 static void output_refs(struct ref *refs)
355 {
356         struct ref *posn;
357         for (posn = refs; posn; posn = posn->next) {
358                 if (posn->symref)
359                         printf("@%s %s\n", posn->symref, posn->name);
360                 else
361                         printf("%s %s\n", oid_to_hex(&posn->old_oid), posn->name);
362         }
363         printf("\n");
364         fflush(stdout);
365 }
366
367 struct rpc_state {
368         const char *service_name;
369         const char **argv;
370         struct strbuf *stdin_preamble;
371         char *service_url;
372         char *hdr_content_type;
373         char *hdr_accept;
374         char *buf;
375         size_t alloc;
376         size_t len;
377         size_t pos;
378         int in;
379         int out;
380         struct strbuf result;
381         unsigned gzip_request : 1;
382         unsigned initial_buffer : 1;
383 };
384
385 static size_t rpc_out(void *ptr, size_t eltsize,
386                 size_t nmemb, void *buffer_)
387 {
388         size_t max = eltsize * nmemb;
389         struct rpc_state *rpc = buffer_;
390         size_t avail = rpc->len - rpc->pos;
391
392         if (!avail) {
393                 rpc->initial_buffer = 0;
394                 avail = packet_read(rpc->out, NULL, NULL, rpc->buf, rpc->alloc, 0);
395                 if (!avail)
396                         return 0;
397                 rpc->pos = 0;
398                 rpc->len = avail;
399         }
400
401         if (max < avail)
402                 avail = max;
403         memcpy(ptr, rpc->buf + rpc->pos, avail);
404         rpc->pos += avail;
405         return avail;
406 }
407
408 #ifndef NO_CURL_IOCTL
409 static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
410 {
411         struct rpc_state *rpc = clientp;
412
413         switch (cmd) {
414         case CURLIOCMD_NOP:
415                 return CURLIOE_OK;
416
417         case CURLIOCMD_RESTARTREAD:
418                 if (rpc->initial_buffer) {
419                         rpc->pos = 0;
420                         return CURLIOE_OK;
421                 }
422                 error("unable to rewind rpc post data - try increasing http.postBuffer");
423                 return CURLIOE_FAILRESTART;
424
425         default:
426                 return CURLIOE_UNKNOWNCMD;
427         }
428 }
429 #endif
430
431 static size_t rpc_in(char *ptr, size_t eltsize,
432                 size_t nmemb, void *buffer_)
433 {
434         size_t size = eltsize * nmemb;
435         struct rpc_state *rpc = buffer_;
436         write_or_die(rpc->in, ptr, size);
437         return size;
438 }
439
440 static int run_slot(struct active_request_slot *slot,
441                     struct slot_results *results)
442 {
443         int err;
444         struct slot_results results_buf;
445
446         if (!results)
447                 results = &results_buf;
448
449         err = run_one_slot(slot, results);
450
451         if (err != HTTP_OK && err != HTTP_REAUTH) {
452                 error("RPC failed; result=%d, HTTP code = %ld",
453                       results->curl_result, results->http_code);
454         }
455
456         return err;
457 }
458
459 static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
460 {
461         struct active_request_slot *slot;
462         struct curl_slist *headers = NULL;
463         struct strbuf buf = STRBUF_INIT;
464         int err;
465
466         slot = get_active_slot();
467
468         headers = curl_slist_append(headers, rpc->hdr_content_type);
469         headers = curl_slist_append(headers, rpc->hdr_accept);
470
471         curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
472         curl_easy_setopt(slot->curl, CURLOPT_POST, 1);
473         curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
474         curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL);
475         curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000");
476         curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4);
477         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
478         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
479         curl_easy_setopt(slot->curl, CURLOPT_FILE, &buf);
480
481         err = run_slot(slot, results);
482
483         curl_slist_free_all(headers);
484         strbuf_release(&buf);
485         return err;
486 }
487
488 static int post_rpc(struct rpc_state *rpc)
489 {
490         struct active_request_slot *slot;
491         struct curl_slist *headers = NULL;
492         int use_gzip = rpc->gzip_request;
493         char *gzip_body = NULL;
494         size_t gzip_size = 0;
495         int err, large_request = 0;
496         int needs_100_continue = 0;
497
498         /* Try to load the entire request, if we can fit it into the
499          * allocated buffer space we can use HTTP/1.0 and avoid the
500          * chunked encoding mess.
501          */
502         while (1) {
503                 size_t left = rpc->alloc - rpc->len;
504                 char *buf = rpc->buf + rpc->len;
505                 int n;
506
507                 if (left < LARGE_PACKET_MAX) {
508                         large_request = 1;
509                         use_gzip = 0;
510                         break;
511                 }
512
513                 n = packet_read(rpc->out, NULL, NULL, buf, left, 0);
514                 if (!n)
515                         break;
516                 rpc->len += n;
517         }
518
519         if (large_request) {
520                 struct slot_results results;
521
522                 do {
523                         err = probe_rpc(rpc, &results);
524                         if (err == HTTP_REAUTH)
525                                 credential_fill(&http_auth);
526                 } while (err == HTTP_REAUTH);
527                 if (err != HTTP_OK)
528                         return -1;
529
530                 if (results.auth_avail & CURLAUTH_GSSNEGOTIATE)
531                         needs_100_continue = 1;
532         }
533
534         headers = curl_slist_append(headers, rpc->hdr_content_type);
535         headers = curl_slist_append(headers, rpc->hdr_accept);
536         headers = curl_slist_append(headers, needs_100_continue ?
537                 "Expect: 100-continue" : "Expect:");
538
539 retry:
540         slot = get_active_slot();
541
542         curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
543         curl_easy_setopt(slot->curl, CURLOPT_POST, 1);
544         curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
545         curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip");
546
547         if (large_request) {
548                 /* The request body is large and the size cannot be predicted.
549                  * We must use chunked encoding to send it.
550                  */
551                 headers = curl_slist_append(headers, "Transfer-Encoding: chunked");
552                 rpc->initial_buffer = 1;
553                 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, rpc_out);
554                 curl_easy_setopt(slot->curl, CURLOPT_INFILE, rpc);
555 #ifndef NO_CURL_IOCTL
556                 curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, rpc_ioctl);
557                 curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, rpc);
558 #endif
559                 if (options.verbosity > 1) {
560                         fprintf(stderr, "POST %s (chunked)\n", rpc->service_name);
561                         fflush(stderr);
562                 }
563
564         } else if (gzip_body) {
565                 /*
566                  * If we are looping to retry authentication, then the previous
567                  * run will have set up the headers and gzip buffer already,
568                  * and we just need to send it.
569                  */
570                 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body);
571                 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size);
572
573         } else if (use_gzip && 1024 < rpc->len) {
574                 /* The client backend isn't giving us compressed data so
575                  * we can try to deflate it ourselves, this may save on.
576                  * the transfer time.
577                  */
578                 git_zstream stream;
579                 int ret;
580
581                 git_deflate_init_gzip(&stream, Z_BEST_COMPRESSION);
582                 gzip_size = git_deflate_bound(&stream, rpc->len);
583                 gzip_body = xmalloc(gzip_size);
584
585                 stream.next_in = (unsigned char *)rpc->buf;
586                 stream.avail_in = rpc->len;
587                 stream.next_out = (unsigned char *)gzip_body;
588                 stream.avail_out = gzip_size;
589
590                 ret = git_deflate(&stream, Z_FINISH);
591                 if (ret != Z_STREAM_END)
592                         die("cannot deflate request; zlib deflate error %d", ret);
593
594                 ret = git_deflate_end_gently(&stream);
595                 if (ret != Z_OK)
596                         die("cannot deflate request; zlib end error %d", ret);
597
598                 gzip_size = stream.total_out;
599
600                 headers = curl_slist_append(headers, "Content-Encoding: gzip");
601                 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body);
602                 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size);
603
604                 if (options.verbosity > 1) {
605                         fprintf(stderr, "POST %s (gzip %lu to %lu bytes)\n",
606                                 rpc->service_name,
607                                 (unsigned long)rpc->len, (unsigned long)gzip_size);
608                         fflush(stderr);
609                 }
610         } else {
611                 /* We know the complete request size in advance, use the
612                  * more normal Content-Length approach.
613                  */
614                 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, rpc->buf);
615                 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, rpc->len);
616                 if (options.verbosity > 1) {
617                         fprintf(stderr, "POST %s (%lu bytes)\n",
618                                 rpc->service_name, (unsigned long)rpc->len);
619                         fflush(stderr);
620                 }
621         }
622
623         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
624         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, rpc_in);
625         curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc);
626
627         err = run_slot(slot, NULL);
628         if (err == HTTP_REAUTH && !large_request) {
629                 credential_fill(&http_auth);
630                 goto retry;
631         }
632         if (err != HTTP_OK)
633                 err = -1;
634
635         curl_slist_free_all(headers);
636         free(gzip_body);
637         return err;
638 }
639
640 static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
641 {
642         const char *svc = rpc->service_name;
643         struct strbuf buf = STRBUF_INIT;
644         struct strbuf *preamble = rpc->stdin_preamble;
645         struct child_process client = CHILD_PROCESS_INIT;
646         int err = 0;
647
648         client.in = -1;
649         client.out = -1;
650         client.git_cmd = 1;
651         client.argv = rpc->argv;
652         if (start_command(&client))
653                 exit(1);
654         if (preamble)
655                 write_or_die(client.in, preamble->buf, preamble->len);
656         if (heads)
657                 write_or_die(client.in, heads->buf, heads->len);
658
659         rpc->alloc = http_post_buffer;
660         rpc->buf = xmalloc(rpc->alloc);
661         rpc->in = client.in;
662         rpc->out = client.out;
663         strbuf_init(&rpc->result, 0);
664
665         strbuf_addf(&buf, "%s%s", url.buf, svc);
666         rpc->service_url = strbuf_detach(&buf, NULL);
667
668         strbuf_addf(&buf, "Content-Type: application/x-%s-request", svc);
669         rpc->hdr_content_type = strbuf_detach(&buf, NULL);
670
671         strbuf_addf(&buf, "Accept: application/x-%s-result", svc);
672         rpc->hdr_accept = strbuf_detach(&buf, NULL);
673
674         while (!err) {
675                 int n = packet_read(rpc->out, NULL, NULL, rpc->buf, rpc->alloc, 0);
676                 if (!n)
677                         break;
678                 rpc->pos = 0;
679                 rpc->len = n;
680                 err |= post_rpc(rpc);
681         }
682
683         close(client.in);
684         client.in = -1;
685         if (!err) {
686                 strbuf_read(&rpc->result, client.out, 0);
687         } else {
688                 char buf[4096];
689                 for (;;)
690                         if (xread(client.out, buf, sizeof(buf)) <= 0)
691                                 break;
692         }
693
694         close(client.out);
695         client.out = -1;
696
697         err |= finish_command(&client);
698         free(rpc->service_url);
699         free(rpc->hdr_content_type);
700         free(rpc->hdr_accept);
701         free(rpc->buf);
702         strbuf_release(&buf);
703         return err;
704 }
705
706 static int fetch_dumb(int nr_heads, struct ref **to_fetch)
707 {
708         struct walker *walker;
709         char **targets = xmalloc(nr_heads * sizeof(char*));
710         int ret, i;
711
712         if (options.depth || options.deepen_since)
713                 die("dumb http transport does not support shallow capabilities");
714         for (i = 0; i < nr_heads; i++)
715                 targets[i] = xstrdup(oid_to_hex(&to_fetch[i]->old_oid));
716
717         walker = get_http_walker(url.buf);
718         walker->get_all = 1;
719         walker->get_tree = 1;
720         walker->get_history = 1;
721         walker->get_verbosely = options.verbosity >= 3;
722         walker->get_recover = 0;
723         ret = walker_fetch(walker, nr_heads, targets, NULL, NULL);
724         walker_free(walker);
725
726         for (i = 0; i < nr_heads; i++)
727                 free(targets[i]);
728         free(targets);
729
730         return ret ? error("fetch failed.") : 0;
731 }
732
733 static int fetch_git(struct discovery *heads,
734         int nr_heads, struct ref **to_fetch)
735 {
736         struct rpc_state rpc;
737         struct strbuf preamble = STRBUF_INIT;
738         int i, err;
739         struct argv_array args = ARGV_ARRAY_INIT;
740
741         argv_array_pushl(&args, "fetch-pack", "--stateless-rpc",
742                          "--stdin", "--lock-pack", NULL);
743         if (options.followtags)
744                 argv_array_push(&args, "--include-tag");
745         if (options.thin)
746                 argv_array_push(&args, "--thin");
747         if (options.verbosity >= 3)
748                 argv_array_pushl(&args, "-v", "-v", NULL);
749         if (options.check_self_contained_and_connected)
750                 argv_array_push(&args, "--check-self-contained-and-connected");
751         if (options.cloning)
752                 argv_array_push(&args, "--cloning");
753         if (options.update_shallow)
754                 argv_array_push(&args, "--update-shallow");
755         if (!options.progress)
756                 argv_array_push(&args, "--no-progress");
757         if (options.depth)
758                 argv_array_pushf(&args, "--depth=%lu", options.depth);
759         if (options.deepen_since)
760                 argv_array_pushf(&args, "--shallow-since=%s", options.deepen_since);
761         for (i = 0; i < options.deepen_not.nr; i++)
762                 argv_array_pushf(&args, "--shallow-exclude=%s",
763                                  options.deepen_not.items[i].string);
764         argv_array_push(&args, url.buf);
765
766         for (i = 0; i < nr_heads; i++) {
767                 struct ref *ref = to_fetch[i];
768                 if (!*ref->name)
769                         die("cannot fetch by sha1 over smart http");
770                 packet_buf_write(&preamble, "%s %s\n",
771                                  oid_to_hex(&ref->old_oid), ref->name);
772         }
773         packet_buf_flush(&preamble);
774
775         memset(&rpc, 0, sizeof(rpc));
776         rpc.service_name = "git-upload-pack",
777         rpc.argv = args.argv;
778         rpc.stdin_preamble = &preamble;
779         rpc.gzip_request = 1;
780
781         err = rpc_service(&rpc, heads);
782         if (rpc.result.len)
783                 write_or_die(1, rpc.result.buf, rpc.result.len);
784         strbuf_release(&rpc.result);
785         strbuf_release(&preamble);
786         argv_array_clear(&args);
787         return err;
788 }
789
790 static int fetch(int nr_heads, struct ref **to_fetch)
791 {
792         struct discovery *d = discover_refs("git-upload-pack", 0);
793         if (d->proto_git)
794                 return fetch_git(d, nr_heads, to_fetch);
795         else
796                 return fetch_dumb(nr_heads, to_fetch);
797 }
798
799 static void parse_fetch(struct strbuf *buf)
800 {
801         struct ref **to_fetch = NULL;
802         struct ref *list_head = NULL;
803         struct ref **list = &list_head;
804         int alloc_heads = 0, nr_heads = 0;
805
806         do {
807                 const char *p;
808                 if (skip_prefix(buf->buf, "fetch ", &p)) {
809                         const char *name;
810                         struct ref *ref;
811                         struct object_id old_oid;
812
813                         if (get_oid_hex(p, &old_oid))
814                                 die("protocol error: expected sha/ref, got %s'", p);
815                         if (p[GIT_SHA1_HEXSZ] == ' ')
816                                 name = p + GIT_SHA1_HEXSZ + 1;
817                         else if (!p[GIT_SHA1_HEXSZ])
818                                 name = "";
819                         else
820                                 die("protocol error: expected sha/ref, got %s'", p);
821
822                         ref = alloc_ref(name);
823                         oidcpy(&ref->old_oid, &old_oid);
824
825                         *list = ref;
826                         list = &ref->next;
827
828                         ALLOC_GROW(to_fetch, nr_heads + 1, alloc_heads);
829                         to_fetch[nr_heads++] = ref;
830                 }
831                 else
832                         die("http transport does not support %s", buf->buf);
833
834                 strbuf_reset(buf);
835                 if (strbuf_getline_lf(buf, stdin) == EOF)
836                         return;
837                 if (!*buf->buf)
838                         break;
839         } while (1);
840
841         if (fetch(nr_heads, to_fetch))
842                 exit(128); /* error already reported */
843         free_refs(list_head);
844         free(to_fetch);
845
846         printf("\n");
847         fflush(stdout);
848         strbuf_reset(buf);
849 }
850
851 static int push_dav(int nr_spec, char **specs)
852 {
853         const char **argv = xmalloc((10 + nr_spec) * sizeof(char*));
854         int argc = 0, i;
855
856         argv[argc++] = "http-push";
857         argv[argc++] = "--helper-status";
858         if (options.dry_run)
859                 argv[argc++] = "--dry-run";
860         if (options.verbosity > 1)
861                 argv[argc++] = "--verbose";
862         argv[argc++] = url.buf;
863         for (i = 0; i < nr_spec; i++)
864                 argv[argc++] = specs[i];
865         argv[argc++] = NULL;
866
867         if (run_command_v_opt(argv, RUN_GIT_CMD))
868                 die("git-%s failed", argv[0]);
869         free(argv);
870         return 0;
871 }
872
873 static int push_git(struct discovery *heads, int nr_spec, char **specs)
874 {
875         struct rpc_state rpc;
876         int i, err;
877         struct argv_array args;
878         struct string_list_item *cas_option;
879         struct strbuf preamble = STRBUF_INIT;
880
881         argv_array_init(&args);
882         argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status",
883                          NULL);
884
885         if (options.thin)
886                 argv_array_push(&args, "--thin");
887         if (options.dry_run)
888                 argv_array_push(&args, "--dry-run");
889         if (options.push_cert == SEND_PACK_PUSH_CERT_ALWAYS)
890                 argv_array_push(&args, "--signed=yes");
891         else if (options.push_cert == SEND_PACK_PUSH_CERT_IF_ASKED)
892                 argv_array_push(&args, "--signed=if-asked");
893         if (options.verbosity == 0)
894                 argv_array_push(&args, "--quiet");
895         else if (options.verbosity > 1)
896                 argv_array_push(&args, "--verbose");
897         argv_array_push(&args, options.progress ? "--progress" : "--no-progress");
898         for_each_string_list_item(cas_option, &cas_options)
899                 argv_array_push(&args, cas_option->string);
900         argv_array_push(&args, url.buf);
901
902         argv_array_push(&args, "--stdin");
903         for (i = 0; i < nr_spec; i++)
904                 packet_buf_write(&preamble, "%s\n", specs[i]);
905         packet_buf_flush(&preamble);
906
907         memset(&rpc, 0, sizeof(rpc));
908         rpc.service_name = "git-receive-pack",
909         rpc.argv = args.argv;
910         rpc.stdin_preamble = &preamble;
911
912         err = rpc_service(&rpc, heads);
913         if (rpc.result.len)
914                 write_or_die(1, rpc.result.buf, rpc.result.len);
915         strbuf_release(&rpc.result);
916         strbuf_release(&preamble);
917         argv_array_clear(&args);
918         return err;
919 }
920
921 static int push(int nr_spec, char **specs)
922 {
923         struct discovery *heads = discover_refs("git-receive-pack", 1);
924         int ret;
925
926         if (heads->proto_git)
927                 ret = push_git(heads, nr_spec, specs);
928         else
929                 ret = push_dav(nr_spec, specs);
930         free_discovery(heads);
931         return ret;
932 }
933
934 static void parse_push(struct strbuf *buf)
935 {
936         char **specs = NULL;
937         int alloc_spec = 0, nr_spec = 0, i, ret;
938
939         do {
940                 if (starts_with(buf->buf, "push ")) {
941                         ALLOC_GROW(specs, nr_spec + 1, alloc_spec);
942                         specs[nr_spec++] = xstrdup(buf->buf + 5);
943                 }
944                 else
945                         die("http transport does not support %s", buf->buf);
946
947                 strbuf_reset(buf);
948                 if (strbuf_getline_lf(buf, stdin) == EOF)
949                         goto free_specs;
950                 if (!*buf->buf)
951                         break;
952         } while (1);
953
954         ret = push(nr_spec, specs);
955         printf("\n");
956         fflush(stdout);
957
958         if (ret)
959                 exit(128); /* error already reported */
960
961  free_specs:
962         for (i = 0; i < nr_spec; i++)
963                 free(specs[i]);
964         free(specs);
965 }
966
967 int main(int argc, const char **argv)
968 {
969         struct strbuf buf = STRBUF_INIT;
970         int nongit;
971
972         git_setup_gettext();
973
974         git_extract_argv0_path(argv[0]);
975         setup_git_directory_gently(&nongit);
976         if (argc < 2) {
977                 error("remote-curl: usage: git remote-curl <remote> [<url>]");
978                 return 1;
979         }
980
981         options.verbosity = 1;
982         options.progress = !!isatty(2);
983         options.thin = 1;
984         string_list_init(&options.deepen_not, 1);
985
986         remote = remote_get(argv[1]);
987
988         if (argc > 2) {
989                 end_url_with_slash(&url, argv[2]);
990         } else {
991                 end_url_with_slash(&url, remote->url[0]);
992         }
993
994         http_init(remote, url.buf, 0);
995
996         do {
997                 const char *arg;
998
999                 if (strbuf_getline_lf(&buf, stdin) == EOF) {
1000                         if (ferror(stdin))
1001                                 error("remote-curl: error reading command stream from git");
1002                         return 1;
1003                 }
1004                 if (buf.len == 0)
1005                         break;
1006                 if (starts_with(buf.buf, "fetch ")) {
1007                         if (nongit)
1008                                 die("remote-curl: fetch attempted without a local repo");
1009                         parse_fetch(&buf);
1010
1011                 } else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {
1012                         int for_push = !!strstr(buf.buf + 4, "for-push");
1013                         output_refs(get_refs(for_push));
1014
1015                 } else if (starts_with(buf.buf, "push ")) {
1016                         parse_push(&buf);
1017
1018                 } else if (skip_prefix(buf.buf, "option ", &arg)) {
1019                         char *value = strchr(arg, ' ');
1020                         int result;
1021
1022                         if (value)
1023                                 *value++ = '\0';
1024                         else
1025                                 value = "true";
1026
1027                         result = set_option(arg, value);
1028                         if (!result)
1029                                 printf("ok\n");
1030                         else if (result < 0)
1031                                 printf("error invalid value\n");
1032                         else
1033                                 printf("unsupported\n");
1034                         fflush(stdout);
1035
1036                 } else if (!strcmp(buf.buf, "capabilities")) {
1037                         printf("fetch\n");
1038                         printf("option\n");
1039                         printf("push\n");
1040                         printf("check-connectivity\n");
1041                         printf("\n");
1042                         fflush(stdout);
1043                 } else {
1044                         error("remote-curl: unknown command '%s' from git", buf.buf);
1045                         return 1;
1046                 }
1047                 strbuf_reset(&buf);
1048         } while (1);
1049
1050         http_cleanup();
1051
1052         return 0;
1053 }