Changeset 782 for git/branches/dmik/remote-curl.c
- Timestamp:
- Jun 23, 2014, 9:45:51 PM (11 years ago)
- Location:
- git/branches/dmik
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
git/branches/dmik ¶
- Property svn:mergeinfo changed
/git/vendor/2.0.0 (added) merged: 777 /git/vendor/current merged: 772,774,776
- Property svn:mergeinfo changed
-
TabularUnified git/branches/dmik/remote-curl.c ¶
r626 r782 7 7 #include "run-command.h" 8 8 #include "pkt-line.h" 9 #include "string-list.h" 9 10 #include "sideband.h" 11 #include "argv-array.h" 12 #include "credential.h" 13 #include "sha1-array.h" 10 14 11 15 static struct remote *remote; 12 static const char *url; /* always ends with a trailing slash */ 16 /* always ends with a trailing slash */ 17 static struct strbuf url = STRBUF_INIT; 13 18 14 19 struct options { … … 16 21 unsigned long depth; 17 22 unsigned progress : 1, 23 check_self_contained_and_connected : 1, 24 cloning : 1, 25 update_shallow : 1, 18 26 followtags : 1, 19 27 dry_run : 1, … … 21 29 }; 22 30 static struct options options; 31 static struct string_list cas_options = STRING_LIST_INIT_DUP; 23 32 24 33 static int set_option(const char *name, const char *value) … … 67 76 return 0; 68 77 } 69 else { 78 else if (!strcmp(name, "check-connectivity")) { 79 if (!strcmp(value, "true")) 80 options.check_self_contained_and_connected = 1; 81 else if (!strcmp(value, "false")) 82 options.check_self_contained_and_connected = 0; 83 else 84 return -1; 85 return 0; 86 } 87 else if (!strcmp(name, "cas")) { 88 struct strbuf val = STRBUF_INIT; 89 strbuf_addf(&val, "--" CAS_OPT_NAME "=%s", value); 90 string_list_append(&cas_options, val.buf); 91 strbuf_release(&val); 92 return 0; 93 } else if (!strcmp(name, "cloning")) { 94 if (!strcmp(value, "true")) 95 options.cloning = 1; 96 else if (!strcmp(value, "false")) 97 options.cloning = 0; 98 else 99 return -1; 100 return 0; 101 } else if (!strcmp(name, "update-shallow")) { 102 if (!strcmp(value, "true")) 103 options.update_shallow = 1; 104 else if (!strcmp(value, "false")) 105 options.update_shallow = 0; 106 else 107 return -1; 108 return 0; 109 } else { 70 110 return 1 /* unsupported */; 71 111 } … … 77 117 char *buf; 78 118 size_t len; 119 struct ref *refs; 120 struct sha1_array shallow; 79 121 unsigned proto_git : 1; 80 122 }; 81 123 static struct discovery *last_discovery; 82 124 83 static void free_discovery(struct discovery *d)84 {85 if (d) {86 if (d == last_discovery)87 last_discovery = NULL;88 free(d->buf_alloc);89 free(d);90 }91 }92 93 static struct discovery* discover_refs(const char *service)94 {95 struct strbuf buffer = STRBUF_INIT;96 struct discovery *last = last_discovery;97 char *refs_url;98 int http_ret, is_http = 0, proto_git_candidate = 1;99 100 if (last && !strcmp(service, last->service))101 return last;102 free_discovery(last);103 104 strbuf_addf(&buffer, "%sinfo/refs", url);105 if (!prefixcmp(url, "http://") || !prefixcmp(url, "https://")) {106 is_http = 1;107 if (!strchr(url, '?'))108 strbuf_addch(&buffer, '?');109 else110 strbuf_addch(&buffer, '&');111 strbuf_addf(&buffer, "service=%s", service);112 }113 refs_url = strbuf_detach(&buffer, NULL);114 115 http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);116 117 /* try again with "plain" url (no ? or & appended) */118 if (http_ret != HTTP_OK && http_ret != HTTP_NOAUTH) {119 free(refs_url);120 strbuf_reset(&buffer);121 122 proto_git_candidate = 0;123 strbuf_addf(&buffer, "%sinfo/refs", url);124 refs_url = strbuf_detach(&buffer, NULL);125 126 http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);127 }128 129 switch (http_ret) {130 case HTTP_OK:131 break;132 case HTTP_MISSING_TARGET:133 die("%s not found: did you run git update-server-info on the"134 " server?", refs_url);135 case HTTP_NOAUTH:136 die("Authentication failed");137 default:138 http_error(refs_url, http_ret);139 die("HTTP request failed");140 }141 142 last= xcalloc(1, sizeof(*last_discovery));143 last->service = service;144 last->buf_alloc = strbuf_detach(&buffer, &last->len);145 last->buf = last->buf_alloc;146 147 if (is_http && proto_git_candidate148 && 5 <= last->len && last->buf[4] == '#') {149 /* smart HTTP response; validate that the service150 * pkt-line matches our request.151 */152 struct strbuf exp = STRBUF_INIT;153 154 if (packet_get_line(&buffer, &last->buf, &last->len) <= 0)155 die("%s has invalid packet header", refs_url);156 if (buffer.len && buffer.buf[buffer.len - 1] == '\n')157 strbuf_setlen(&buffer, buffer.len - 1);158 159 strbuf_addf(&exp, "# service=%s", service);160 if (strbuf_cmp(&exp, &buffer))161 die("invalid server response; got '%s'", buffer.buf);162 strbuf_release(&exp);163 164 /* The header can include additional metadata lines, up165 * until a packet flush marker. Ignore these now, but166 * in the future we might start to scan them.167 */168 strbuf_reset(&buffer);169 while (packet_get_line(&buffer, &last->buf, &last->len) > 0)170 strbuf_reset(&buffer);171 172 last->proto_git = 1;173 }174 175 free(refs_url);176 strbuf_release(&buffer);177 last_discovery = last;178 return last;179 }180 181 static int write_discovery(int in, int out, void *data)182 {183 struct discovery *heads = data;184 int err = 0;185 if (write_in_full(out, heads->buf, heads->len) != heads->len)186 err = 1;187 close(out);188 return err;189 }190 191 125 static struct ref *parse_git_refs(struct discovery *heads, int for_push) 192 126 { 193 127 struct ref *list = NULL; 194 struct async async; 195 196 memset(&async, 0, sizeof(async)); 197 async.proc = write_discovery; 198 async.data = heads; 199 async.out = -1; 200 201 if (start_async(&async)) 202 die("cannot start thread to parse advertised refs"); 203 get_remote_heads(async.out, &list, 204 for_push ? REF_NORMAL : 0, NULL); 205 close(async.out); 206 if (finish_async(&async)) 207 die("ref parsing thread failed"); 128 get_remote_heads(-1, heads->buf, heads->len, &list, 129 for_push ? REF_NORMAL : 0, NULL, &heads->shallow); 208 130 return list; 209 131 } … … 230 152 if (data[i] == '\n') { 231 153 if (mid - start != 40) 232 die("%sinfo/refs not valid: is this a git repository?", url); 154 die("%sinfo/refs not valid: is this a git repository?", 155 url.buf); 233 156 data[i] = 0; 234 157 ref_name = mid + 1; … … 249 172 250 173 ref = alloc_ref("HEAD"); 251 if (!http_fetch_ref(url , ref) &&174 if (!http_fetch_ref(url.buf, ref) && 252 175 !resolve_remote_symref(ref, refs)) { 253 176 ref->next = refs; … … 260 183 } 261 184 185 static void free_discovery(struct discovery *d) 186 { 187 if (d) { 188 if (d == last_discovery) 189 last_discovery = NULL; 190 free(d->shallow.sha1); 191 free(d->buf_alloc); 192 free_refs(d->refs); 193 free(d); 194 } 195 } 196 197 static int show_http_message(struct strbuf *type, struct strbuf *msg) 198 { 199 const char *p, *eol; 200 201 /* 202 * We only show text/plain parts, as other types are likely 203 * to be ugly to look at on the user's terminal. 204 * 205 * TODO should handle "; charset=XXX", and re-encode into 206 * logoutputencoding 207 */ 208 if (strcasecmp(type->buf, "text/plain")) 209 return -1; 210 211 strbuf_trim(msg); 212 if (!msg->len) 213 return -1; 214 215 p = msg->buf; 216 do { 217 eol = strchrnul(p, '\n'); 218 fprintf(stderr, "remote: %.*s\n", (int)(eol - p), p); 219 p = eol + 1; 220 } while(*eol); 221 return 0; 222 } 223 224 static struct discovery* discover_refs(const char *service, int for_push) 225 { 226 struct strbuf exp = STRBUF_INIT; 227 struct strbuf type = STRBUF_INIT; 228 struct strbuf buffer = STRBUF_INIT; 229 struct strbuf refs_url = STRBUF_INIT; 230 struct strbuf effective_url = STRBUF_INIT; 231 struct discovery *last = last_discovery; 232 int http_ret, maybe_smart = 0; 233 struct http_get_options options; 234 235 if (last && !strcmp(service, last->service)) 236 return last; 237 free_discovery(last); 238 239 strbuf_addf(&refs_url, "%sinfo/refs", url.buf); 240 if ((starts_with(url.buf, "http://") || starts_with(url.buf, "https://")) && 241 git_env_bool("GIT_SMART_HTTP", 1)) { 242 maybe_smart = 1; 243 if (!strchr(url.buf, '?')) 244 strbuf_addch(&refs_url, '?'); 245 else 246 strbuf_addch(&refs_url, '&'); 247 strbuf_addf(&refs_url, "service=%s", service); 248 } 249 250 memset(&options, 0, sizeof(options)); 251 options.content_type = &type; 252 options.effective_url = &effective_url; 253 options.base_url = &url; 254 options.no_cache = 1; 255 options.keep_error = 1; 256 257 http_ret = http_get_strbuf(refs_url.buf, &buffer, &options); 258 switch (http_ret) { 259 case HTTP_OK: 260 break; 261 case HTTP_MISSING_TARGET: 262 show_http_message(&type, &buffer); 263 die("repository '%s' not found", url.buf); 264 case HTTP_NOAUTH: 265 show_http_message(&type, &buffer); 266 die("Authentication failed for '%s'", url.buf); 267 default: 268 show_http_message(&type, &buffer); 269 die("unable to access '%s': %s", url.buf, curl_errorstr); 270 } 271 272 last= xcalloc(1, sizeof(*last_discovery)); 273 last->service = service; 274 last->buf_alloc = strbuf_detach(&buffer, &last->len); 275 last->buf = last->buf_alloc; 276 277 strbuf_addf(&exp, "application/x-%s-advertisement", service); 278 if (maybe_smart && 279 (5 <= last->len && last->buf[4] == '#') && 280 !strbuf_cmp(&exp, &type)) { 281 char *line; 282 283 /* 284 * smart HTTP response; validate that the service 285 * pkt-line matches our request. 286 */ 287 line = packet_read_line_buf(&last->buf, &last->len, NULL); 288 289 strbuf_reset(&exp); 290 strbuf_addf(&exp, "# service=%s", service); 291 if (strcmp(line, exp.buf)) 292 die("invalid server response; got '%s'", line); 293 strbuf_release(&exp); 294 295 /* The header can include additional metadata lines, up 296 * until a packet flush marker. Ignore these now, but 297 * in the future we might start to scan them. 298 */ 299 while (packet_read_line_buf(&last->buf, &last->len, NULL)) 300 ; 301 302 last->proto_git = 1; 303 } 304 305 if (last->proto_git) 306 last->refs = parse_git_refs(last, for_push); 307 else 308 last->refs = parse_info_refs(last); 309 310 strbuf_release(&refs_url); 311 strbuf_release(&exp); 312 strbuf_release(&type); 313 strbuf_release(&effective_url); 314 strbuf_release(&buffer); 315 last_discovery = last; 316 return last; 317 } 318 262 319 static struct ref *get_refs(int for_push) 263 320 { … … 265 322 266 323 if (for_push) 267 heads = discover_refs("git-receive-pack" );324 heads = discover_refs("git-receive-pack", for_push); 268 325 else 269 heads = discover_refs("git-upload-pack"); 270 271 if (heads->proto_git) 272 return parse_git_refs(heads, for_push); 273 return parse_info_refs(heads); 326 heads = discover_refs("git-upload-pack", for_push); 327 328 return heads->refs; 274 329 } 275 330 … … 285 340 printf("\n"); 286 341 fflush(stdout); 287 free_refs(refs);288 342 } 289 343 … … 291 345 const char *service_name; 292 346 const char **argv; 347 struct strbuf *stdin_preamble; 293 348 char *service_url; 294 349 char *hdr_content_type; … … 314 369 if (!avail) { 315 370 rpc->initial_buffer = 0; 316 avail = packet_read _line(rpc->out, rpc->buf, rpc->alloc);371 avail = packet_read(rpc->out, NULL, NULL, rpc->buf, rpc->alloc, 0); 317 372 if (!avail) 318 373 return 0; … … 360 415 } 361 416 362 static int run_slot(struct active_request_slot *slot) 363 { 364 int err = 0; 365 struct slot_results results; 366 367 slot->results = &results; 368 slot->curl_result = curl_easy_perform(slot->curl); 369 finish_active_slot(slot); 370 371 if (results.curl_result != CURLE_OK) { 372 err |= error("RPC failed; result=%d, HTTP code = %ld", 373 results.curl_result, results.http_code); 417 static int run_slot(struct active_request_slot *slot, 418 struct slot_results *results) 419 { 420 int err; 421 struct slot_results results_buf; 422 423 if (!results) 424 results = &results_buf; 425 426 err = run_one_slot(slot, results); 427 428 if (err != HTTP_OK && err != HTTP_REAUTH) { 429 error("RPC failed; result=%d, HTTP code = %ld", 430 results->curl_result, results->http_code); 374 431 } 375 432 … … 377 434 } 378 435 379 static int probe_rpc(struct rpc_state *rpc )436 static int probe_rpc(struct rpc_state *rpc, struct slot_results *results) 380 437 { 381 438 struct active_request_slot *slot; … … 392 449 curl_easy_setopt(slot->curl, CURLOPT_POST, 1); 393 450 curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url); 394 curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");451 curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL); 395 452 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000"); 396 453 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4); … … 399 456 curl_easy_setopt(slot->curl, CURLOPT_FILE, &buf); 400 457 401 err = run_slot(slot );458 err = run_slot(slot, results); 402 459 403 460 curl_slist_free_all(headers); … … 412 469 int use_gzip = rpc->gzip_request; 413 470 char *gzip_body = NULL; 471 size_t gzip_size = 0; 414 472 int err, large_request = 0; 473 int needs_100_continue = 0; 415 474 416 475 /* Try to load the entire request, if we can fit it into the … … 429 488 } 430 489 431 n = packet_read _line(rpc->out, buf, left);490 n = packet_read(rpc->out, NULL, NULL, buf, left, 0); 432 491 if (!n) 433 492 break; … … 436 495 437 496 if (large_request) { 438 err = probe_rpc(rpc); 439 if (err) 440 return err; 441 } 442 497 struct slot_results results; 498 499 do { 500 err = probe_rpc(rpc, &results); 501 if (err == HTTP_REAUTH) 502 credential_fill(&http_auth); 503 } while (err == HTTP_REAUTH); 504 if (err != HTTP_OK) 505 return -1; 506 507 if (results.auth_avail & CURLAUTH_GSSNEGOTIATE) 508 needs_100_continue = 1; 509 } 510 511 headers = curl_slist_append(headers, rpc->hdr_content_type); 512 headers = curl_slist_append(headers, rpc->hdr_accept); 513 headers = curl_slist_append(headers, needs_100_continue ? 514 "Expect: 100-continue" : "Expect:"); 515 516 retry: 443 517 slot = get_active_slot(); 444 518 … … 446 520 curl_easy_setopt(slot->curl, CURLOPT_POST, 1); 447 521 curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url); 448 curl_easy_setopt(slot->curl, CURLOPT_ENCODING, ""); 449 450 headers = curl_slist_append(headers, rpc->hdr_content_type); 451 headers = curl_slist_append(headers, rpc->hdr_accept); 452 headers = curl_slist_append(headers, "Expect:"); 522 curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip"); 453 523 454 524 if (large_request) { … … 469 539 } 470 540 541 } else if (gzip_body) { 542 /* 543 * If we are looping to retry authentication, then the previous 544 * run will have set up the headers and gzip buffer already, 545 * and we just need to send it. 546 */ 547 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body); 548 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size); 549 471 550 } else if (use_gzip && 1024 < rpc->len) { 472 551 /* The client backend isn't giving us compressed data so … … 474 553 * the transfer time. 475 554 */ 476 size_t size;477 555 git_zstream stream; 478 556 int ret; … … 480 558 memset(&stream, 0, sizeof(stream)); 481 559 git_deflate_init_gzip(&stream, Z_BEST_COMPRESSION); 482 size = git_deflate_bound(&stream, rpc->len);483 gzip_body = xmalloc( size);560 gzip_size = git_deflate_bound(&stream, rpc->len); 561 gzip_body = xmalloc(gzip_size); 484 562 485 563 stream.next_in = (unsigned char *)rpc->buf; 486 564 stream.avail_in = rpc->len; 487 565 stream.next_out = (unsigned char *)gzip_body; 488 stream.avail_out = size;566 stream.avail_out = gzip_size; 489 567 490 568 ret = git_deflate(&stream, Z_FINISH); … … 496 574 die("cannot deflate request; zlib end error %d", ret); 497 575 498 size = stream.total_out;576 gzip_size = stream.total_out; 499 577 500 578 headers = curl_slist_append(headers, "Content-Encoding: gzip"); 501 579 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, gzip_body); 502 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, size);580 curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, gzip_size); 503 581 504 582 if (options.verbosity > 1) { 505 583 fprintf(stderr, "POST %s (gzip %lu to %lu bytes)\n", 506 584 rpc->service_name, 507 (unsigned long)rpc->len, (unsigned long) size);585 (unsigned long)rpc->len, (unsigned long)gzip_size); 508 586 fflush(stderr); 509 587 } … … 525 603 curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc); 526 604 527 err = run_slot(slot); 605 err = run_slot(slot, NULL); 606 if (err == HTTP_REAUTH && !large_request) { 607 credential_fill(&http_auth); 608 goto retry; 609 } 610 if (err != HTTP_OK) 611 err = -1; 528 612 529 613 curl_slist_free_all(headers); … … 536 620 const char *svc = rpc->service_name; 537 621 struct strbuf buf = STRBUF_INIT; 622 struct strbuf *preamble = rpc->stdin_preamble; 538 623 struct child_process client; 539 624 int err = 0; … … 546 631 if (start_command(&client)) 547 632 exit(1); 633 if (preamble) 634 write_or_die(client.in, preamble->buf, preamble->len); 548 635 if (heads) 549 636 write_or_die(client.in, heads->buf, heads->len); … … 555 642 strbuf_init(&rpc->result, 0); 556 643 557 strbuf_addf(&buf, "%s%s", url , svc);644 strbuf_addf(&buf, "%s%s", url.buf, svc); 558 645 rpc->service_url = strbuf_detach(&buf, NULL); 559 646 … … 565 652 566 653 while (!err) { 567 int n = packet_read _line(rpc->out, rpc->buf, rpc->alloc);654 int n = packet_read(rpc->out, NULL, NULL, rpc->buf, rpc->alloc, 0); 568 655 if (!n) 569 656 break; … … 607 694 targets[i] = xstrdup(sha1_to_hex(to_fetch[i]->old_sha1)); 608 695 609 walker = get_http_walker(url );696 walker = get_http_walker(url.buf); 610 697 walker->get_all = 1; 611 698 walker->get_tree = 1; … … 627 714 { 628 715 struct rpc_state rpc; 716 struct strbuf preamble = STRBUF_INIT; 629 717 char *depth_arg = NULL; 630 const char **argv;631 718 int argc = 0, i, err; 632 633 argv = xmalloc((15 + nr_heads) * sizeof(char*)); 719 const char *argv[17]; 720 634 721 argv[argc++] = "fetch-pack"; 635 722 argv[argc++] = "--stateless-rpc"; 723 argv[argc++] = "--stdin"; 636 724 argv[argc++] = "--lock-pack"; 637 725 if (options.followtags) … … 643 731 argv[argc++] = "-v"; 644 732 } 733 if (options.check_self_contained_and_connected) 734 argv[argc++] = "--check-self-contained-and-connected"; 735 if (options.cloning) 736 argv[argc++] = "--cloning"; 737 if (options.update_shallow) 738 argv[argc++] = "--update-shallow"; 645 739 if (!options.progress) 646 740 argv[argc++] = "--no-progress"; … … 651 745 argv[argc++] = depth_arg; 652 746 } 653 argv[argc++] = url; 747 argv[argc++] = url.buf; 748 argv[argc++] = NULL; 749 654 750 for (i = 0; i < nr_heads; i++) { 655 751 struct ref *ref = to_fetch[i]; 656 752 if (!ref->name || !*ref->name) 657 753 die("cannot fetch by sha1 over smart http"); 658 argv[argc++] = ref->name; 659 } 660 argv[argc++] = NULL; 754 packet_buf_write(&preamble, "%s %s\n", 755 sha1_to_hex(ref->old_sha1), ref->name); 756 } 757 packet_buf_flush(&preamble); 661 758 662 759 memset(&rpc, 0, sizeof(rpc)); 663 760 rpc.service_name = "git-upload-pack", 664 761 rpc.argv = argv; 762 rpc.stdin_preamble = &preamble; 665 763 rpc.gzip_request = 1; 666 764 667 765 err = rpc_service(&rpc, heads); 668 766 if (rpc.result.len) 669 safe_write(1, rpc.result.buf, rpc.result.len);767 write_or_die(1, rpc.result.buf, rpc.result.len); 670 768 strbuf_release(&rpc.result); 671 free(argv);769 strbuf_release(&preamble); 672 770 free(depth_arg); 673 771 return err; … … 676 774 static int fetch(int nr_heads, struct ref **to_fetch) 677 775 { 678 struct discovery *d = discover_refs("git-upload-pack" );776 struct discovery *d = discover_refs("git-upload-pack", 0); 679 777 if (d->proto_git) 680 778 return fetch_git(d, nr_heads, to_fetch); … … 691 789 692 790 do { 693 if ( !prefixcmp(buf->buf, "fetch ")) {791 if (starts_with(buf->buf, "fetch ")) { 694 792 char *p = buf->buf + strlen("fetch "); 695 793 char *name; … … 746 844 if (options.verbosity > 1) 747 845 argv[argc++] = "--verbose"; 748 argv[argc++] = url ;846 argv[argc++] = url.buf; 749 847 for (i = 0; i < nr_spec; i++) 750 848 argv[argc++] = specs[i]; … … 760 858 { 761 859 struct rpc_state rpc; 762 const char **argv; 763 int argc = 0, i, err; 764 765 argv = xmalloc((10 + nr_spec) * sizeof(char*)); 766 argv[argc++] = "send-pack"; 767 argv[argc++] = "--stateless-rpc"; 768 argv[argc++] = "--helper-status"; 860 int i, err; 861 struct argv_array args; 862 struct string_list_item *cas_option; 863 864 argv_array_init(&args); 865 argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status", 866 NULL); 867 769 868 if (options.thin) 770 argv [argc++] = "--thin";869 argv_array_push(&args, "--thin"); 771 870 if (options.dry_run) 772 argv [argc++] = "--dry-run";871 argv_array_push(&args, "--dry-run"); 773 872 if (options.verbosity == 0) 774 argv [argc++] = "--quiet";873 argv_array_push(&args, "--quiet"); 775 874 else if (options.verbosity > 1) 776 argv[argc++] = "--verbose"; 777 argv[argc++] = url; 875 argv_array_push(&args, "--verbose"); 876 argv_array_push(&args, options.progress ? "--progress" : "--no-progress"); 877 for_each_string_list_item(cas_option, &cas_options) 878 argv_array_push(&args, cas_option->string); 879 argv_array_push(&args, url.buf); 778 880 for (i = 0; i < nr_spec; i++) 779 argv[argc++] = specs[i]; 780 argv[argc++] = NULL; 881 argv_array_push(&args, specs[i]); 781 882 782 883 memset(&rpc, 0, sizeof(rpc)); 783 884 rpc.service_name = "git-receive-pack", 784 rpc.argv = arg v;885 rpc.argv = args.argv; 785 886 786 887 err = rpc_service(&rpc, heads); 787 888 if (rpc.result.len) 788 safe_write(1, rpc.result.buf, rpc.result.len);889 write_or_die(1, rpc.result.buf, rpc.result.len); 789 890 strbuf_release(&rpc.result); 790 free(argv);891 argv_array_clear(&args); 791 892 return err; 792 893 } … … 794 895 static int push(int nr_spec, char **specs) 795 896 { 796 struct discovery *heads = discover_refs("git-receive-pack" );897 struct discovery *heads = discover_refs("git-receive-pack", 1); 797 898 int ret; 798 899 … … 811 912 812 913 do { 813 if ( !prefixcmp(buf->buf, "push ")) {914 if (starts_with(buf->buf, "push ")) { 814 915 ALLOC_GROW(specs, nr_spec + 1, alloc_spec); 815 916 specs[nr_spec++] = xstrdup(buf->buf + 5); … … 857 958 858 959 if (argc > 2) { 859 end_url_with_slash(& buf, argv[2]);960 end_url_with_slash(&url, argv[2]); 860 961 } else { 861 end_url_with_slash(&buf, remote->url[0]); 862 } 863 864 url = strbuf_detach(&buf, NULL); 865 866 http_init(remote, url, 0); 962 end_url_with_slash(&url, remote->url[0]); 963 } 964 965 http_init(remote, url.buf, 0); 867 966 868 967 do { … … 876 975 if (buf.len == 0) 877 976 break; 878 if ( !prefixcmp(buf.buf, "fetch ")) {977 if (starts_with(buf.buf, "fetch ")) { 879 978 if (nongit) 880 979 die("Fetch attempted without a local repo"); 881 980 parse_fetch(&buf); 882 981 883 } else if (!strcmp(buf.buf, "list") || !prefixcmp(buf.buf, "list ")) {982 } else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) { 884 983 int for_push = !!strstr(buf.buf + 4, "for-push"); 885 984 output_refs(get_refs(for_push)); 886 985 887 } else if ( !prefixcmp(buf.buf, "push ")) {986 } else if (starts_with(buf.buf, "push ")) { 888 987 parse_push(&buf); 889 988 890 } else if ( !prefixcmp(buf.buf, "option ")) {989 } else if (starts_with(buf.buf, "option ")) { 891 990 char *name = buf.buf + strlen("option "); 892 991 char *value = strchr(name, ' '); … … 911 1010 printf("option\n"); 912 1011 printf("push\n"); 1012 printf("check-connectivity\n"); 913 1013 printf("\n"); 914 1014 fflush(stdout);
Note:
See TracChangeset
for help on using the changeset viewer.