Git fork
at reftables-rust 2009 lines 52 kB view raw
1#define USE_THE_REPOSITORY_VARIABLE 2 3#include "git-compat-util.h" 4#include "environment.h" 5#include "hex.h" 6#include "repository.h" 7#include "commit.h" 8#include "tag.h" 9#include "blob.h" 10#include "http.h" 11#include "diff.h" 12#include "revision.h" 13#include "remote.h" 14#include "list-objects.h" 15#include "setup.h" 16#include "sigchain.h" 17#include "strvec.h" 18#include "tree.h" 19#include "tree-walk.h" 20#include "url.h" 21#include "packfile.h" 22#include "object-file.h" 23#include "odb.h" 24#include "commit-reach.h" 25 26#ifdef EXPAT_NEEDS_XMLPARSE_H 27#include <xmlparse.h> 28#else 29#include <expat.h> 30#endif 31 32static const char http_push_usage[] = 33"git http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n"; 34 35#ifndef XML_STATUS_OK 36enum XML_Status { 37 XML_STATUS_OK = 1, 38 XML_STATUS_ERROR = 0 39}; 40#define XML_STATUS_OK 1 41#define XML_STATUS_ERROR 0 42#endif 43 44#define PREV_BUF_SIZE 4096 45 46/* DAV methods */ 47#define DAV_LOCK "LOCK" 48#define DAV_MKCOL "MKCOL" 49#define DAV_MOVE "MOVE" 50#define DAV_PROPFIND "PROPFIND" 51#define DAV_PUT "PUT" 52#define DAV_UNLOCK "UNLOCK" 53#define DAV_DELETE "DELETE" 54 55/* DAV lock flags */ 56#define DAV_PROP_LOCKWR (1u << 0) 57#define DAV_PROP_LOCKEX (1u << 1) 58#define DAV_LOCK_OK (1u << 2) 59 60/* DAV XML properties */ 61#define DAV_CTX_LOCKENTRY ".multistatus.response.propstat.prop.supportedlock.lockentry" 62#define DAV_CTX_LOCKTYPE_WRITE ".multistatus.response.propstat.prop.supportedlock.lockentry.locktype.write" 63#define DAV_CTX_LOCKTYPE_EXCLUSIVE ".multistatus.response.propstat.prop.supportedlock.lockentry.lockscope.exclusive" 64#define DAV_ACTIVELOCK_OWNER ".prop.lockdiscovery.activelock.owner.href" 65#define DAV_ACTIVELOCK_TIMEOUT ".prop.lockdiscovery.activelock.timeout" 66#define DAV_ACTIVELOCK_TOKEN ".prop.lockdiscovery.activelock.locktoken.href" 67#define DAV_PROPFIND_RESP ".multistatus.response" 68#define DAV_PROPFIND_NAME ".multistatus.response.href" 69#define DAV_PROPFIND_COLLECTION ".multistatus.response.propstat.prop.resourcetype.collection" 70 71/* DAV request body templates */ 72#define PROPFIND_SUPPORTEDLOCK_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:prop xmlns:R=\"%s\">\n<D:supportedlock/>\n</D:prop>\n</D:propfind>" 73#define PROPFIND_ALL_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:allprop/>\n</D:propfind>" 74#define LOCK_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:lockinfo xmlns:D=\"DAV:\">\n<D:lockscope><D:exclusive/></D:lockscope>\n<D:locktype><D:write/></D:locktype>\n<D:owner>\n<D:href>mailto:%s</D:href>\n</D:owner>\n</D:lockinfo>" 75 76#define LOCK_TIME 600 77#define LOCK_REFRESH 30 78 79/* Remember to update object flag allocation in object.h */ 80#define LOCAL (1u<<11) 81#define REMOTE (1u<<12) 82#define FETCHING (1u<<13) 83#define PUSHING (1u<<14) 84 85/* We allow "recursive" symbolic refs. Only within reason, though */ 86#define MAXDEPTH 5 87 88static int pushing; 89static int aborted; 90static signed char remote_dir_exists[256]; 91 92static int push_verbosely; 93static int push_all = MATCH_REFS_NONE; 94static int force_all; 95static int dry_run; 96static int helper_status; 97 98static struct object_list *objects; 99 100struct repo { 101 char *url; 102 char *path; 103 int path_len; 104 int has_info_refs; 105 int can_update_info_refs; 106 int has_info_packs; 107 struct packed_git *packs; 108 struct remote_lock *locks; 109}; 110 111static struct repo *repo; 112 113enum transfer_state { 114 NEED_FETCH, 115 RUN_FETCH_LOOSE, 116 RUN_FETCH_PACKED, 117 NEED_PUSH, 118 RUN_MKCOL, 119 RUN_PUT, 120 RUN_MOVE, 121 ABORTED, 122 COMPLETE 123}; 124 125struct transfer_request { 126 struct object *obj; 127 struct packed_git *target; 128 char *url; 129 char *dest; 130 struct remote_lock *lock; 131 struct curl_slist *headers; 132 struct buffer buffer; 133 enum transfer_state state; 134 CURLcode curl_result; 135 char errorstr[CURL_ERROR_SIZE]; 136 long http_code; 137 void *userData; 138 struct active_request_slot *slot; 139 struct transfer_request *next; 140}; 141 142static struct transfer_request *request_queue_head; 143 144struct xml_ctx { 145 char *name; 146 int len; 147 char *cdata; 148 void (*userFunc)(struct xml_ctx *ctx, int tag_closed); 149 void *userData; 150}; 151 152struct remote_lock { 153 char *url; 154 char *owner; 155 char *token; 156 char tmpfile_suffix[GIT_MAX_HEXSZ + 1]; 157 time_t start_time; 158 long timeout; 159 int refreshing; 160 struct remote_lock *next; 161}; 162 163/* Flags that control remote_ls processing */ 164#define PROCESS_FILES (1u << 0) 165#define PROCESS_DIRS (1u << 1) 166#define RECURSIVE (1u << 2) 167 168/* Flags that remote_ls passes to callback functions */ 169#define IS_DIR (1u << 0) 170 171struct remote_ls_ctx { 172 char *path; 173 void (*userFunc)(struct remote_ls_ctx *ls); 174 void *userData; 175 int flags; 176 char *dentry_name; 177 int dentry_flags; 178 struct remote_ls_ctx *parent; 179}; 180 181/* get_dav_token_headers options */ 182enum dav_header_flag { 183 DAV_HEADER_IF = (1u << 0), 184 DAV_HEADER_LOCK = (1u << 1), 185 DAV_HEADER_TIMEOUT = (1u << 2) 186}; 187 188static char *xml_entities(const char *s) 189{ 190 struct strbuf buf = STRBUF_INIT; 191 strbuf_addstr_xml_quoted(&buf, s); 192 return strbuf_detach(&buf, NULL); 193} 194 195static void curl_setup_http_get(CURL *curl, const char *url, 196 const char *custom_req) 197{ 198 curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); 199 curl_easy_setopt(curl, CURLOPT_URL, url); 200 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req); 201 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_null); 202} 203 204static void curl_setup_http(CURL *curl, const char *url, 205 const char *custom_req, struct buffer *buffer, 206 curl_write_callback write_fn) 207{ 208 curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); 209 curl_easy_setopt(curl, CURLOPT_URL, url); 210 curl_easy_setopt(curl, CURLOPT_INFILE, buffer); 211 curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, 212 cast_size_t_to_curl_off_t(buffer->buf.len)); 213 curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer); 214 curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, seek_buffer); 215 curl_easy_setopt(curl, CURLOPT_SEEKDATA, buffer); 216 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn); 217 curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); 218 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req); 219 curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); 220} 221 222static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options) 223{ 224 struct strbuf buf = STRBUF_INIT; 225 struct curl_slist *dav_headers = http_copy_default_headers(); 226 227 if (options & DAV_HEADER_IF) { 228 strbuf_addf(&buf, "If: (<%s>)", lock->token); 229 dav_headers = curl_slist_append(dav_headers, buf.buf); 230 strbuf_reset(&buf); 231 } 232 if (options & DAV_HEADER_LOCK) { 233 strbuf_addf(&buf, "Lock-Token: <%s>", lock->token); 234 dav_headers = curl_slist_append(dav_headers, buf.buf); 235 strbuf_reset(&buf); 236 } 237 if (options & DAV_HEADER_TIMEOUT) { 238 strbuf_addf(&buf, "Timeout: Second-%ld", lock->timeout); 239 dav_headers = curl_slist_append(dav_headers, buf.buf); 240 strbuf_reset(&buf); 241 } 242 strbuf_release(&buf); 243 244 return dav_headers; 245} 246 247static void finish_request(struct transfer_request *request); 248static void release_request(struct transfer_request *request); 249 250static void process_response(void *callback_data) 251{ 252 struct transfer_request *request = 253 (struct transfer_request *)callback_data; 254 255 finish_request(request); 256} 257 258static void start_fetch_loose(struct transfer_request *request) 259{ 260 struct active_request_slot *slot; 261 struct http_object_request *obj_req; 262 263 obj_req = new_http_object_request(repo->url, &request->obj->oid); 264 if (!obj_req) { 265 request->state = ABORTED; 266 return; 267 } 268 269 slot = obj_req->slot; 270 slot->callback_func = process_response; 271 slot->callback_data = request; 272 request->slot = slot; 273 request->userData = obj_req; 274 275 /* Try to get the request started, abort the request on error */ 276 request->state = RUN_FETCH_LOOSE; 277 if (!start_active_slot(slot)) { 278 fprintf(stderr, "Unable to start GET request\n"); 279 repo->can_update_info_refs = 0; 280 release_http_object_request(&obj_req); 281 release_request(request); 282 } 283} 284 285static void start_mkcol(struct transfer_request *request) 286{ 287 char *hex = oid_to_hex(&request->obj->oid); 288 struct active_request_slot *slot; 289 290 request->url = get_remote_object_url(repo->url, hex, 1); 291 292 slot = get_active_slot(); 293 slot->callback_func = process_response; 294 slot->callback_data = request; 295 curl_setup_http_get(slot->curl, request->url, DAV_MKCOL); 296 curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr); 297 298 if (start_active_slot(slot)) { 299 request->slot = slot; 300 request->state = RUN_MKCOL; 301 } else { 302 request->state = ABORTED; 303 FREE_AND_NULL(request->url); 304 } 305} 306 307static void start_fetch_packed(struct transfer_request *request) 308{ 309 struct packed_git *target; 310 311 struct transfer_request *check_request = request_queue_head; 312 struct http_pack_request *preq; 313 314 target = find_oid_pack(&request->obj->oid, repo->packs); 315 if (!target) { 316 fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", oid_to_hex(&request->obj->oid)); 317 repo->can_update_info_refs = 0; 318 release_request(request); 319 return; 320 } 321 close_pack_index(target); 322 request->target = target; 323 324 fprintf(stderr, "Fetching pack %s\n", 325 hash_to_hex(target->hash)); 326 fprintf(stderr, " which contains %s\n", oid_to_hex(&request->obj->oid)); 327 328 preq = new_http_pack_request(target->hash, repo->url); 329 if (!preq) { 330 repo->can_update_info_refs = 0; 331 return; 332 } 333 334 /* Make sure there isn't another open request for this pack */ 335 while (check_request) { 336 if (check_request->state == RUN_FETCH_PACKED && 337 !strcmp(check_request->url, preq->url)) { 338 release_http_pack_request(preq); 339 release_request(request); 340 return; 341 } 342 check_request = check_request->next; 343 } 344 345 preq->slot->callback_func = process_response; 346 preq->slot->callback_data = request; 347 request->slot = preq->slot; 348 request->userData = preq; 349 350 /* Try to get the request started, abort the request on error */ 351 request->state = RUN_FETCH_PACKED; 352 if (!start_active_slot(preq->slot)) { 353 fprintf(stderr, "Unable to start GET request\n"); 354 release_http_pack_request(preq); 355 repo->can_update_info_refs = 0; 356 release_request(request); 357 } 358} 359 360static void start_put(struct transfer_request *request) 361{ 362 char *hex = oid_to_hex(&request->obj->oid); 363 struct active_request_slot *slot; 364 struct strbuf buf = STRBUF_INIT; 365 enum object_type type; 366 char hdr[50]; 367 void *unpacked; 368 unsigned long len; 369 int hdrlen; 370 ssize_t size; 371 git_zstream stream; 372 373 unpacked = odb_read_object(the_repository->objects, &request->obj->oid, 374 &type, &len); 375 hdrlen = format_object_header(hdr, sizeof(hdr), type, len); 376 377 /* Set it up */ 378 git_deflate_init(&stream, zlib_compression_level); 379 size = git_deflate_bound(&stream, len + hdrlen); 380 strbuf_grow(&request->buffer.buf, size); 381 request->buffer.posn = 0; 382 383 /* Compress it */ 384 stream.next_out = (unsigned char *)request->buffer.buf.buf; 385 stream.avail_out = size; 386 387 /* First header.. */ 388 stream.next_in = (void *)hdr; 389 stream.avail_in = hdrlen; 390 while (git_deflate(&stream, 0) == Z_OK) 391 ; /* nothing */ 392 393 /* Then the data itself.. */ 394 stream.next_in = unpacked; 395 stream.avail_in = len; 396 while (git_deflate(&stream, Z_FINISH) == Z_OK) 397 ; /* nothing */ 398 git_deflate_end(&stream); 399 free(unpacked); 400 401 request->buffer.buf.len = stream.total_out; 402 403 strbuf_addstr(&buf, "Destination: "); 404 append_remote_object_url(&buf, repo->url, hex, 0); 405 request->dest = strbuf_detach(&buf, NULL); 406 407 append_remote_object_url(&buf, repo->url, hex, 0); 408 strbuf_add(&buf, request->lock->tmpfile_suffix, the_hash_algo->hexsz + 1); 409 request->url = strbuf_detach(&buf, NULL); 410 411 slot = get_active_slot(); 412 slot->callback_func = process_response; 413 slot->callback_data = request; 414 curl_setup_http(slot->curl, request->url, DAV_PUT, 415 &request->buffer, fwrite_null); 416 417 if (start_active_slot(slot)) { 418 request->slot = slot; 419 request->state = RUN_PUT; 420 } else { 421 request->state = ABORTED; 422 FREE_AND_NULL(request->url); 423 } 424} 425 426static void start_move(struct transfer_request *request) 427{ 428 struct active_request_slot *slot; 429 struct curl_slist *dav_headers = http_copy_default_headers(); 430 431 slot = get_active_slot(); 432 slot->callback_func = process_response; 433 slot->callback_data = request; 434 curl_setup_http_get(slot->curl, request->url, DAV_MOVE); 435 dav_headers = curl_slist_append(dav_headers, request->dest); 436 dav_headers = curl_slist_append(dav_headers, "Overwrite: T"); 437 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); 438 439 if (start_active_slot(slot)) { 440 request->slot = slot; 441 request->state = RUN_MOVE; 442 request->headers = dav_headers; 443 } else { 444 request->state = ABORTED; 445 FREE_AND_NULL(request->url); 446 curl_slist_free_all(dav_headers); 447 } 448} 449 450static int refresh_lock(struct remote_lock *lock) 451{ 452 struct active_request_slot *slot; 453 struct slot_results results; 454 struct curl_slist *dav_headers; 455 int rc = 0; 456 457 lock->refreshing = 1; 458 459 dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF | DAV_HEADER_TIMEOUT); 460 461 slot = get_active_slot(); 462 slot->results = &results; 463 curl_setup_http_get(slot->curl, lock->url, DAV_LOCK); 464 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); 465 466 if (start_active_slot(slot)) { 467 run_active_slot(slot); 468 if (results.curl_result != CURLE_OK) { 469 fprintf(stderr, "LOCK HTTP error %ld\n", 470 results.http_code); 471 } else { 472 lock->start_time = time(NULL); 473 rc = 1; 474 } 475 } 476 477 lock->refreshing = 0; 478 curl_slist_free_all(dav_headers); 479 480 return rc; 481} 482 483static void check_locks(void) 484{ 485 struct remote_lock *lock = repo->locks; 486 time_t current_time = time(NULL); 487 int time_remaining; 488 489 while (lock) { 490 time_remaining = lock->start_time + lock->timeout - 491 current_time; 492 if (!lock->refreshing && time_remaining < LOCK_REFRESH) { 493 if (!refresh_lock(lock)) { 494 fprintf(stderr, 495 "Unable to refresh lock for %s\n", 496 lock->url); 497 aborted = 1; 498 return; 499 } 500 } 501 lock = lock->next; 502 } 503} 504 505static void release_request(struct transfer_request *request) 506{ 507 struct transfer_request *entry = request_queue_head; 508 509 if (request == request_queue_head) { 510 request_queue_head = request->next; 511 } else { 512 while (entry && entry->next != request) 513 entry = entry->next; 514 if (entry) 515 entry->next = request->next; 516 } 517 518 free(request->url); 519 free(request->dest); 520 strbuf_release(&request->buffer.buf); 521 free(request); 522} 523 524static void finish_request(struct transfer_request *request) 525{ 526 struct http_pack_request *preq; 527 struct http_object_request *obj_req; 528 529 request->curl_result = request->slot->curl_result; 530 request->http_code = request->slot->http_code; 531 request->slot = NULL; 532 533 /* Keep locks active */ 534 check_locks(); 535 536 if (request->headers) 537 curl_slist_free_all(request->headers); 538 539 /* URL is reused for MOVE after PUT and used during FETCH */ 540 if (request->state != RUN_PUT && request->state != RUN_FETCH_PACKED) { 541 FREE_AND_NULL(request->url); 542 } 543 544 if (request->state == RUN_MKCOL) { 545 if (request->curl_result == CURLE_OK || 546 request->http_code == 405) { 547 remote_dir_exists[request->obj->oid.hash[0]] = 1; 548 start_put(request); 549 } else { 550 fprintf(stderr, "MKCOL %s failed, aborting (%d/%ld)\n", 551 oid_to_hex(&request->obj->oid), 552 request->curl_result, request->http_code); 553 request->state = ABORTED; 554 aborted = 1; 555 } 556 } else if (request->state == RUN_PUT) { 557 if (request->curl_result == CURLE_OK) { 558 start_move(request); 559 } else { 560 fprintf(stderr, "PUT %s failed, aborting (%d/%ld)\n", 561 oid_to_hex(&request->obj->oid), 562 request->curl_result, request->http_code); 563 request->state = ABORTED; 564 aborted = 1; 565 } 566 } else if (request->state == RUN_MOVE) { 567 if (request->curl_result == CURLE_OK) { 568 if (push_verbosely) 569 fprintf(stderr, " sent %s\n", 570 oid_to_hex(&request->obj->oid)); 571 request->obj->flags |= REMOTE; 572 release_request(request); 573 } else { 574 fprintf(stderr, "MOVE %s failed, aborting (%d/%ld)\n", 575 oid_to_hex(&request->obj->oid), 576 request->curl_result, request->http_code); 577 request->state = ABORTED; 578 aborted = 1; 579 } 580 } else if (request->state == RUN_FETCH_LOOSE) { 581 obj_req = (struct http_object_request *)request->userData; 582 583 if (finish_http_object_request(obj_req) == 0) 584 if (obj_req->rename == 0) 585 request->obj->flags |= (LOCAL | REMOTE); 586 587 release_http_object_request(&obj_req); 588 589 /* Try fetching packed if necessary */ 590 if (request->obj->flags & LOCAL) { 591 release_request(request); 592 } else 593 start_fetch_packed(request); 594 595 } else if (request->state == RUN_FETCH_PACKED) { 596 int fail = 1; 597 if (request->curl_result != CURLE_OK) { 598 fprintf(stderr, "Unable to get pack file %s\n%s", 599 request->url, curl_errorstr); 600 } else { 601 preq = (struct http_pack_request *)request->userData; 602 603 if (preq) { 604 if (finish_http_pack_request(preq) == 0) 605 fail = 0; 606 release_http_pack_request(preq); 607 } 608 } 609 if (fail) 610 repo->can_update_info_refs = 0; 611 else 612 http_install_packfile(request->target, &repo->packs); 613 release_request(request); 614 } 615} 616 617static int is_running_queue; 618static int fill_active_slot(void *data UNUSED) 619{ 620 struct transfer_request *request; 621 622 if (aborted || !is_running_queue) 623 return 0; 624 625 for (request = request_queue_head; request; request = request->next) { 626 if (request->state == NEED_FETCH) { 627 start_fetch_loose(request); 628 return 1; 629 } else if (pushing && request->state == NEED_PUSH) { 630 if (remote_dir_exists[request->obj->oid.hash[0]] == 1) { 631 start_put(request); 632 } else { 633 start_mkcol(request); 634 } 635 return 1; 636 } 637 } 638 return 0; 639} 640 641static void get_remote_object_list(unsigned char parent); 642 643static void add_fetch_request(struct object *obj) 644{ 645 struct transfer_request *request; 646 647 check_locks(); 648 649 /* 650 * Don't fetch the object if it's known to exist locally 651 * or is already in the request queue 652 */ 653 if (remote_dir_exists[obj->oid.hash[0]] == -1) 654 get_remote_object_list(obj->oid.hash[0]); 655 if (obj->flags & (LOCAL | FETCHING)) 656 return; 657 658 obj->flags |= FETCHING; 659 CALLOC_ARRAY(request, 1); 660 request->obj = obj; 661 request->state = NEED_FETCH; 662 strbuf_init(&request->buffer.buf, 0); 663 request->next = request_queue_head; 664 request_queue_head = request; 665 666 fill_active_slots(); 667 step_active_slots(); 668} 669 670static int add_send_request(struct object *obj, struct remote_lock *lock) 671{ 672 struct transfer_request *request; 673 struct packed_git *target; 674 675 /* Keep locks active */ 676 check_locks(); 677 678 /* 679 * Don't push the object if it's known to exist on the remote 680 * or is already in the request queue 681 */ 682 if (remote_dir_exists[obj->oid.hash[0]] == -1) 683 get_remote_object_list(obj->oid.hash[0]); 684 if (obj->flags & (REMOTE | PUSHING)) 685 return 0; 686 target = find_oid_pack(&obj->oid, repo->packs); 687 if (target) { 688 obj->flags |= REMOTE; 689 return 0; 690 } 691 692 obj->flags |= PUSHING; 693 CALLOC_ARRAY(request, 1); 694 request->obj = obj; 695 request->lock = lock; 696 request->state = NEED_PUSH; 697 strbuf_init(&request->buffer.buf, 0); 698 request->next = request_queue_head; 699 request_queue_head = request; 700 701 fill_active_slots(); 702 step_active_slots(); 703 704 return 1; 705} 706 707static int fetch_indices(void) 708{ 709 int ret; 710 711 if (push_verbosely) 712 fprintf(stderr, "Getting pack list\n"); 713 714 switch (http_get_info_packs(repo->url, &repo->packs)) { 715 case HTTP_OK: 716 case HTTP_MISSING_TARGET: 717 ret = 0; 718 break; 719 default: 720 ret = -1; 721 } 722 723 return ret; 724} 725 726static void one_remote_object(const struct object_id *oid) 727{ 728 struct object *obj; 729 730 obj = lookup_object(the_repository, oid); 731 if (!obj) 732 obj = parse_object(the_repository, oid); 733 734 /* Ignore remote objects that don't exist locally */ 735 if (!obj) 736 return; 737 738 obj->flags |= REMOTE; 739 if (!object_list_contains(objects, obj)) 740 object_list_insert(obj, &objects); 741} 742 743static void handle_lockprop_ctx(struct xml_ctx *ctx, int tag_closed) 744{ 745 int *lock_flags = (int *)ctx->userData; 746 747 if (tag_closed) { 748 if (!strcmp(ctx->name, DAV_CTX_LOCKENTRY)) { 749 if ((*lock_flags & DAV_PROP_LOCKEX) && 750 (*lock_flags & DAV_PROP_LOCKWR)) { 751 *lock_flags |= DAV_LOCK_OK; 752 } 753 *lock_flags &= DAV_LOCK_OK; 754 } else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_WRITE)) { 755 *lock_flags |= DAV_PROP_LOCKWR; 756 } else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_EXCLUSIVE)) { 757 *lock_flags |= DAV_PROP_LOCKEX; 758 } 759 } 760} 761 762static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed) 763{ 764 struct remote_lock *lock = (struct remote_lock *)ctx->userData; 765 struct git_hash_ctx hash_ctx; 766 unsigned char lock_token_hash[GIT_MAX_RAWSZ]; 767 768 if (tag_closed && ctx->cdata) { 769 if (!strcmp(ctx->name, DAV_ACTIVELOCK_OWNER)) { 770 lock->owner = xstrdup(ctx->cdata); 771 } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TIMEOUT)) { 772 const char *arg; 773 if (skip_prefix(ctx->cdata, "Second-", &arg)) 774 lock->timeout = strtol(arg, NULL, 10); 775 } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) { 776 lock->token = xstrdup(ctx->cdata); 777 778 the_hash_algo->init_fn(&hash_ctx); 779 git_hash_update(&hash_ctx, lock->token, strlen(lock->token)); 780 git_hash_final(lock_token_hash, &hash_ctx); 781 782 lock->tmpfile_suffix[0] = '_'; 783 memcpy(lock->tmpfile_suffix + 1, hash_to_hex(lock_token_hash), the_hash_algo->hexsz); 784 } 785 } 786} 787 788static void one_remote_ref(const char *refname); 789 790static void 791xml_start_tag(void *userData, const char *name, const char **atts UNUSED) 792{ 793 struct xml_ctx *ctx = (struct xml_ctx *)userData; 794 const char *c = strchr(name, ':'); 795 int old_namelen, new_len; 796 797 if (!c) 798 c = name; 799 else 800 c++; 801 802 old_namelen = strlen(ctx->name); 803 new_len = old_namelen + strlen(c) + 2; 804 805 if (new_len > ctx->len) { 806 ctx->name = xrealloc(ctx->name, new_len); 807 ctx->len = new_len; 808 } 809 xsnprintf(ctx->name + old_namelen, ctx->len - old_namelen, ".%s", c); 810 811 FREE_AND_NULL(ctx->cdata); 812 813 ctx->userFunc(ctx, 0); 814} 815 816static void 817xml_end_tag(void *userData, const char *name) 818{ 819 struct xml_ctx *ctx = (struct xml_ctx *)userData; 820 const char *c = strchr(name, ':'); 821 char *ep; 822 823 ctx->userFunc(ctx, 1); 824 825 if (!c) 826 c = name; 827 else 828 c++; 829 830 ep = ctx->name + strlen(ctx->name) - strlen(c) - 1; 831 *ep = 0; 832} 833 834static void 835xml_cdata(void *userData, const XML_Char *s, int len) 836{ 837 struct xml_ctx *ctx = (struct xml_ctx *)userData; 838 free(ctx->cdata); 839 ctx->cdata = xmemdupz(s, len); 840} 841 842static struct remote_lock *lock_remote(const char *path, long timeout) 843{ 844 struct active_request_slot *slot; 845 struct slot_results results; 846 struct buffer out_buffer = { STRBUF_INIT, 0 }; 847 struct strbuf in_buffer = STRBUF_INIT; 848 char *url; 849 char *ep; 850 char timeout_header[25]; 851 struct remote_lock *lock = NULL; 852 struct curl_slist *dav_headers = http_copy_default_headers(); 853 struct xml_ctx ctx; 854 char *escaped; 855 856 url = xstrfmt("%s%s", repo->url, path); 857 858 /* Make sure leading directories exist for the remote ref */ 859 ep = strchr(url + strlen(repo->url) + 1, '/'); 860 while (ep) { 861 char saved_character = ep[1]; 862 ep[1] = '\0'; 863 slot = get_active_slot(); 864 slot->results = &results; 865 curl_setup_http_get(slot->curl, url, DAV_MKCOL); 866 if (start_active_slot(slot)) { 867 run_active_slot(slot); 868 if (results.curl_result != CURLE_OK && 869 results.http_code != 405) { 870 fprintf(stderr, 871 "Unable to create branch path %s\n", 872 url); 873 free(url); 874 return NULL; 875 } 876 } else { 877 fprintf(stderr, "Unable to start MKCOL request\n"); 878 free(url); 879 return NULL; 880 } 881 ep[1] = saved_character; 882 ep = strchr(ep + 1, '/'); 883 } 884 885 escaped = xml_entities(ident_default_email()); 886 strbuf_addf(&out_buffer.buf, LOCK_REQUEST, escaped); 887 free(escaped); 888 889 xsnprintf(timeout_header, sizeof(timeout_header), "Timeout: Second-%ld", timeout); 890 dav_headers = curl_slist_append(dav_headers, timeout_header); 891 dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml"); 892 893 slot = get_active_slot(); 894 slot->results = &results; 895 curl_setup_http(slot->curl, url, DAV_LOCK, &out_buffer, fwrite_buffer); 896 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); 897 curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, &in_buffer); 898 899 CALLOC_ARRAY(lock, 1); 900 lock->timeout = -1; 901 902 if (start_active_slot(slot)) { 903 run_active_slot(slot); 904 if (results.curl_result == CURLE_OK) { 905 XML_Parser parser = XML_ParserCreate(NULL); 906 enum XML_Status result; 907 ctx.name = xcalloc(10, 1); 908 ctx.len = 0; 909 ctx.cdata = NULL; 910 ctx.userFunc = handle_new_lock_ctx; 911 ctx.userData = lock; 912 XML_SetUserData(parser, &ctx); 913 XML_SetElementHandler(parser, xml_start_tag, 914 xml_end_tag); 915 XML_SetCharacterDataHandler(parser, xml_cdata); 916 result = XML_Parse(parser, in_buffer.buf, 917 in_buffer.len, 1); 918 free(ctx.name); 919 free(ctx.cdata); 920 if (result != XML_STATUS_OK) { 921 fprintf(stderr, "XML error: %s\n", 922 XML_ErrorString( 923 XML_GetErrorCode(parser))); 924 lock->timeout = -1; 925 } 926 XML_ParserFree(parser); 927 } else { 928 fprintf(stderr, 929 "error: curl result=%d, HTTP code=%ld\n", 930 results.curl_result, results.http_code); 931 } 932 } else { 933 fprintf(stderr, "Unable to start LOCK request\n"); 934 } 935 936 curl_slist_free_all(dav_headers); 937 strbuf_release(&out_buffer.buf); 938 strbuf_release(&in_buffer); 939 940 if (lock->token == NULL || lock->timeout <= 0) { 941 free(lock->token); 942 free(lock->owner); 943 free(url); 944 FREE_AND_NULL(lock); 945 } else { 946 lock->url = url; 947 lock->start_time = time(NULL); 948 lock->next = repo->locks; 949 repo->locks = lock; 950 } 951 952 return lock; 953} 954 955static int unlock_remote(struct remote_lock *lock) 956{ 957 struct active_request_slot *slot; 958 struct slot_results results; 959 struct remote_lock *prev = repo->locks; 960 struct curl_slist *dav_headers; 961 int rc = 0; 962 963 dav_headers = get_dav_token_headers(lock, DAV_HEADER_LOCK); 964 965 slot = get_active_slot(); 966 slot->results = &results; 967 curl_setup_http_get(slot->curl, lock->url, DAV_UNLOCK); 968 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); 969 970 if (start_active_slot(slot)) { 971 run_active_slot(slot); 972 if (results.curl_result == CURLE_OK) 973 rc = 1; 974 else 975 fprintf(stderr, "UNLOCK HTTP error %ld\n", 976 results.http_code); 977 } else { 978 fprintf(stderr, "Unable to start UNLOCK request\n"); 979 } 980 981 curl_slist_free_all(dav_headers); 982 983 if (repo->locks == lock) { 984 repo->locks = lock->next; 985 } else { 986 while (prev && prev->next != lock) 987 prev = prev->next; 988 if (prev) 989 prev->next = lock->next; 990 } 991 992 free(lock->owner); 993 free(lock->url); 994 free(lock->token); 995 free(lock); 996 997 return rc; 998} 999 1000static void remove_locks(void) 1001{ 1002 struct remote_lock *lock = repo->locks; 1003 1004 fprintf(stderr, "Removing remote locks...\n"); 1005 while (lock) { 1006 struct remote_lock *next = lock->next; 1007 unlock_remote(lock); 1008 lock = next; 1009 } 1010} 1011 1012static void remove_locks_on_signal(int signo) 1013{ 1014 remove_locks(); 1015 sigchain_pop(signo); 1016 raise(signo); 1017} 1018 1019static void remote_ls(const char *path, int flags, 1020 void (*userFunc)(struct remote_ls_ctx *ls), 1021 void *userData); 1022 1023/* extract hex from sharded "xx/x{38}" filename */ 1024static int get_oid_hex_from_objpath(const char *path, struct object_id *oid) 1025{ 1026 memset(oid->hash, 0, GIT_MAX_RAWSZ); 1027 oid->algo = hash_algo_by_ptr(the_hash_algo); 1028 1029 if (strlen(path) != the_hash_algo->hexsz + 1) 1030 return -1; 1031 1032 if (hex_to_bytes(oid->hash, path, 1)) 1033 return -1; 1034 path += 2; 1035 path++; /* skip '/' */ 1036 1037 return hex_to_bytes(oid->hash + 1, path, the_hash_algo->rawsz - 1); 1038} 1039 1040static void process_ls_object(struct remote_ls_ctx *ls) 1041{ 1042 unsigned int *parent = (unsigned int *)ls->userData; 1043 const char *path = ls->dentry_name; 1044 struct object_id oid; 1045 1046 if (!strcmp(ls->path, ls->dentry_name) && (ls->flags & IS_DIR)) { 1047 remote_dir_exists[*parent] = 1; 1048 return; 1049 } 1050 1051 if (!skip_prefix(path, "objects/", &path) || 1052 get_oid_hex_from_objpath(path, &oid)) 1053 return; 1054 1055 one_remote_object(&oid); 1056} 1057 1058static void process_ls_ref(struct remote_ls_ctx *ls) 1059{ 1060 if (!strcmp(ls->path, ls->dentry_name) && (ls->dentry_flags & IS_DIR)) { 1061 fprintf(stderr, " %s\n", ls->dentry_name); 1062 return; 1063 } 1064 1065 if (!(ls->dentry_flags & IS_DIR)) 1066 one_remote_ref(ls->dentry_name); 1067} 1068 1069static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed) 1070{ 1071 struct remote_ls_ctx *ls = (struct remote_ls_ctx *)ctx->userData; 1072 1073 if (tag_closed) { 1074 if (!strcmp(ctx->name, DAV_PROPFIND_RESP) && ls->dentry_name) { 1075 if (ls->dentry_flags & IS_DIR) { 1076 1077 /* ensure collection names end with slash */ 1078 str_end_url_with_slash(ls->dentry_name, &ls->dentry_name); 1079 1080 if (ls->flags & PROCESS_DIRS) { 1081 ls->userFunc(ls); 1082 } 1083 if (strcmp(ls->dentry_name, ls->path) && 1084 ls->flags & RECURSIVE) { 1085 remote_ls(ls->dentry_name, 1086 ls->flags, 1087 ls->userFunc, 1088 ls->userData); 1089 } 1090 } else if (ls->flags & PROCESS_FILES) { 1091 ls->userFunc(ls); 1092 } 1093 } else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) { 1094 char *path = ctx->cdata; 1095 if (*ctx->cdata == 'h') { 1096 path = strstr(path, "//"); 1097 if (path) { 1098 path = strchr(path+2, '/'); 1099 } 1100 } 1101 if (path) { 1102 const char *url = repo->url; 1103 if (repo->path) 1104 url = repo->path; 1105 if (strncmp(path, url, repo->path_len)) 1106 error("Parsed path '%s' does not match url: '%s'", 1107 path, url); 1108 else { 1109 path += repo->path_len; 1110 ls->dentry_name = xstrdup(path); 1111 } 1112 } 1113 } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) { 1114 ls->dentry_flags |= IS_DIR; 1115 } 1116 } else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) { 1117 FREE_AND_NULL(ls->dentry_name); 1118 ls->dentry_flags = 0; 1119 } 1120} 1121 1122/* 1123 * NEEDSWORK: remote_ls() ignores info/refs on the remote side. But it 1124 * should _only_ heed the information from that file, instead of trying to 1125 * determine the refs from the remote file system (badly: it does not even 1126 * know about packed-refs). 1127 */ 1128static void remote_ls(const char *path, int flags, 1129 void (*userFunc)(struct remote_ls_ctx *ls), 1130 void *userData) 1131{ 1132 char *url = xstrfmt("%s%s", repo->url, path); 1133 struct active_request_slot *slot; 1134 struct slot_results results; 1135 struct strbuf in_buffer = STRBUF_INIT; 1136 struct buffer out_buffer = { STRBUF_INIT, 0 }; 1137 struct curl_slist *dav_headers = http_copy_default_headers(); 1138 struct xml_ctx ctx; 1139 struct remote_ls_ctx ls; 1140 1141 ls.flags = flags; 1142 ls.path = xstrdup(path); 1143 ls.dentry_name = NULL; 1144 ls.dentry_flags = 0; 1145 ls.userData = userData; 1146 ls.userFunc = userFunc; 1147 1148 strbuf_addstr(&out_buffer.buf, PROPFIND_ALL_REQUEST); 1149 1150 dav_headers = curl_slist_append(dav_headers, "Depth: 1"); 1151 dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml"); 1152 1153 slot = get_active_slot(); 1154 slot->results = &results; 1155 curl_setup_http(slot->curl, url, DAV_PROPFIND, 1156 &out_buffer, fwrite_buffer); 1157 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); 1158 curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, &in_buffer); 1159 1160 if (start_active_slot(slot)) { 1161 run_active_slot(slot); 1162 if (results.curl_result == CURLE_OK) { 1163 XML_Parser parser = XML_ParserCreate(NULL); 1164 enum XML_Status result; 1165 ctx.name = xcalloc(10, 1); 1166 ctx.len = 0; 1167 ctx.cdata = NULL; 1168 ctx.userFunc = handle_remote_ls_ctx; 1169 ctx.userData = &ls; 1170 XML_SetUserData(parser, &ctx); 1171 XML_SetElementHandler(parser, xml_start_tag, 1172 xml_end_tag); 1173 XML_SetCharacterDataHandler(parser, xml_cdata); 1174 result = XML_Parse(parser, in_buffer.buf, 1175 in_buffer.len, 1); 1176 free(ctx.name); 1177 free(ctx.cdata); 1178 1179 if (result != XML_STATUS_OK) { 1180 fprintf(stderr, "XML error: %s\n", 1181 XML_ErrorString( 1182 XML_GetErrorCode(parser))); 1183 } 1184 XML_ParserFree(parser); 1185 } 1186 } else { 1187 fprintf(stderr, "Unable to start PROPFIND request\n"); 1188 } 1189 1190 free(ls.path); 1191 free(ls.dentry_name); 1192 free(url); 1193 strbuf_release(&out_buffer.buf); 1194 strbuf_release(&in_buffer); 1195 curl_slist_free_all(dav_headers); 1196} 1197 1198static void get_remote_object_list(unsigned char parent) 1199{ 1200 char path[] = "objects/XX/"; 1201 static const char hex[] = "0123456789abcdef"; 1202 unsigned int val = parent; 1203 1204 path[8] = hex[val >> 4]; 1205 path[9] = hex[val & 0xf]; 1206 remote_dir_exists[val] = 0; 1207 remote_ls(path, (PROCESS_FILES | PROCESS_DIRS), 1208 process_ls_object, &val); 1209} 1210 1211static int locking_available(void) 1212{ 1213 struct active_request_slot *slot; 1214 struct slot_results results; 1215 struct strbuf in_buffer = STRBUF_INIT; 1216 struct buffer out_buffer = { STRBUF_INIT, 0 }; 1217 struct curl_slist *dav_headers = http_copy_default_headers(); 1218 struct xml_ctx ctx; 1219 int lock_flags = 0; 1220 char *escaped; 1221 1222 escaped = xml_entities(repo->url); 1223 strbuf_addf(&out_buffer.buf, PROPFIND_SUPPORTEDLOCK_REQUEST, escaped); 1224 free(escaped); 1225 1226 dav_headers = curl_slist_append(dav_headers, "Depth: 0"); 1227 dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml"); 1228 1229 slot = get_active_slot(); 1230 slot->results = &results; 1231 curl_setup_http(slot->curl, repo->url, DAV_PROPFIND, 1232 &out_buffer, fwrite_buffer); 1233 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); 1234 curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, &in_buffer); 1235 1236 if (start_active_slot(slot)) { 1237 run_active_slot(slot); 1238 if (results.curl_result == CURLE_OK) { 1239 XML_Parser parser = XML_ParserCreate(NULL); 1240 enum XML_Status result; 1241 ctx.name = xcalloc(10, 1); 1242 ctx.len = 0; 1243 ctx.cdata = NULL; 1244 ctx.userFunc = handle_lockprop_ctx; 1245 ctx.userData = &lock_flags; 1246 XML_SetUserData(parser, &ctx); 1247 XML_SetElementHandler(parser, xml_start_tag, 1248 xml_end_tag); 1249 result = XML_Parse(parser, in_buffer.buf, 1250 in_buffer.len, 1); 1251 free(ctx.name); 1252 1253 if (result != XML_STATUS_OK) { 1254 fprintf(stderr, "XML error: %s\n", 1255 XML_ErrorString( 1256 XML_GetErrorCode(parser))); 1257 lock_flags = 0; 1258 } 1259 XML_ParserFree(parser); 1260 if (!lock_flags) 1261 error("no DAV locking support on %s", 1262 repo->url); 1263 1264 } else { 1265 error("Cannot access URL %s, return code %d", 1266 repo->url, results.curl_result); 1267 lock_flags = 0; 1268 } 1269 } else { 1270 error("Unable to start PROPFIND request on %s", repo->url); 1271 } 1272 1273 strbuf_release(&out_buffer.buf); 1274 strbuf_release(&in_buffer); 1275 curl_slist_free_all(dav_headers); 1276 1277 return lock_flags; 1278} 1279 1280static struct object_list **add_one_object(struct object *obj, struct object_list **p) 1281{ 1282 struct object_list *entry = xmalloc(sizeof(struct object_list)); 1283 entry->item = obj; 1284 entry->next = *p; 1285 *p = entry; 1286 return &entry->next; 1287} 1288 1289static struct object_list **process_blob(struct blob *blob, 1290 struct object_list **p) 1291{ 1292 struct object *obj = &blob->object; 1293 1294 obj->flags |= LOCAL; 1295 1296 if (obj->flags & (UNINTERESTING | SEEN)) 1297 return p; 1298 1299 obj->flags |= SEEN; 1300 return add_one_object(obj, p); 1301} 1302 1303static struct object_list **process_tree(struct tree *tree, 1304 struct object_list **p) 1305{ 1306 struct object *obj = &tree->object; 1307 struct tree_desc desc; 1308 struct name_entry entry; 1309 1310 obj->flags |= LOCAL; 1311 1312 if (obj->flags & (UNINTERESTING | SEEN)) 1313 return p; 1314 if (parse_tree(tree) < 0) 1315 die("bad tree object %s", oid_to_hex(&obj->oid)); 1316 1317 obj->flags |= SEEN; 1318 p = add_one_object(obj, p); 1319 1320 init_tree_desc(&desc, &tree->object.oid, tree->buffer, tree->size); 1321 1322 while (tree_entry(&desc, &entry)) 1323 switch (object_type(entry.mode)) { 1324 case OBJ_TREE: 1325 p = process_tree(lookup_tree(the_repository, &entry.oid), 1326 p); 1327 break; 1328 case OBJ_BLOB: 1329 p = process_blob(lookup_blob(the_repository, &entry.oid), 1330 p); 1331 break; 1332 default: 1333 /* Subproject commit - not in this repository */ 1334 break; 1335 } 1336 1337 free_tree_buffer(tree); 1338 return p; 1339} 1340 1341static int get_delta(struct rev_info *revs, struct remote_lock *lock) 1342{ 1343 struct commit *commit; 1344 struct object_list **p = &objects; 1345 int count = 0; 1346 1347 while ((commit = get_revision(revs)) != NULL) { 1348 p = process_tree(repo_get_commit_tree(the_repository, commit), 1349 p); 1350 commit->object.flags |= LOCAL; 1351 if (!(commit->object.flags & UNINTERESTING)) 1352 count += add_send_request(&commit->object, lock); 1353 } 1354 1355 for (size_t i = 0; i < revs->pending.nr; i++) { 1356 struct object_array_entry *entry = revs->pending.objects + i; 1357 struct object *obj = entry->item; 1358 const char *name = entry->name; 1359 1360 if (obj->flags & (UNINTERESTING | SEEN)) 1361 continue; 1362 if (obj->type == OBJ_TAG) { 1363 obj->flags |= SEEN; 1364 p = add_one_object(obj, p); 1365 continue; 1366 } 1367 if (obj->type == OBJ_TREE) { 1368 p = process_tree((struct tree *)obj, p); 1369 continue; 1370 } 1371 if (obj->type == OBJ_BLOB) { 1372 p = process_blob((struct blob *)obj, p); 1373 continue; 1374 } 1375 die("unknown pending object %s (%s)", oid_to_hex(&obj->oid), name); 1376 } 1377 1378 while (objects) { 1379 struct object_list *next = objects->next; 1380 1381 if (!(objects->item->flags & UNINTERESTING)) 1382 count += add_send_request(objects->item, lock); 1383 1384 free(objects); 1385 objects = next; 1386 } 1387 1388 return count; 1389} 1390 1391static int update_remote(const struct object_id *oid, struct remote_lock *lock) 1392{ 1393 struct active_request_slot *slot; 1394 struct slot_results results; 1395 struct buffer out_buffer = { STRBUF_INIT, 0 }; 1396 struct curl_slist *dav_headers; 1397 1398 dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF); 1399 1400 strbuf_addf(&out_buffer.buf, "%s\n", oid_to_hex(oid)); 1401 1402 slot = get_active_slot(); 1403 slot->results = &results; 1404 curl_setup_http(slot->curl, lock->url, DAV_PUT, 1405 &out_buffer, fwrite_null); 1406 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); 1407 1408 if (start_active_slot(slot)) { 1409 run_active_slot(slot); 1410 strbuf_release(&out_buffer.buf); 1411 curl_slist_free_all(dav_headers); 1412 if (results.curl_result != CURLE_OK) { 1413 fprintf(stderr, 1414 "PUT error: curl result=%d, HTTP code=%ld\n", 1415 results.curl_result, results.http_code); 1416 /* We should attempt recovery? */ 1417 return 0; 1418 } 1419 } else { 1420 strbuf_release(&out_buffer.buf); 1421 curl_slist_free_all(dav_headers); 1422 fprintf(stderr, "Unable to start PUT request\n"); 1423 return 0; 1424 } 1425 1426 return 1; 1427} 1428 1429static struct ref *remote_refs; 1430 1431static void one_remote_ref(const char *refname) 1432{ 1433 struct ref *ref; 1434 struct object *obj; 1435 1436 ref = alloc_ref(refname); 1437 1438 if (http_fetch_ref(repo->url, ref) != 0) { 1439 fprintf(stderr, 1440 "Unable to fetch ref %s from %s\n", 1441 refname, repo->url); 1442 free(ref); 1443 return; 1444 } 1445 1446 /* 1447 * Fetch a copy of the object if it doesn't exist locally - it 1448 * may be required for updating server info later. 1449 */ 1450 if (repo->can_update_info_refs && 1451 !odb_has_object(the_repository->objects, &ref->old_oid, 1452 HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) { 1453 obj = lookup_unknown_object(the_repository, &ref->old_oid); 1454 fprintf(stderr, " fetch %s for %s\n", 1455 oid_to_hex(&ref->old_oid), refname); 1456 add_fetch_request(obj); 1457 } 1458 1459 ref->next = remote_refs; 1460 remote_refs = ref; 1461} 1462 1463static void get_dav_remote_heads(void) 1464{ 1465 remote_ls("refs/", (PROCESS_FILES | PROCESS_DIRS | RECURSIVE), process_ls_ref, NULL); 1466} 1467 1468static void add_remote_info_ref(struct remote_ls_ctx *ls) 1469{ 1470 struct strbuf *buf = (struct strbuf *)ls->userData; 1471 struct object *o; 1472 struct ref *ref; 1473 1474 ref = alloc_ref(ls->dentry_name); 1475 1476 if (http_fetch_ref(repo->url, ref) != 0) { 1477 fprintf(stderr, 1478 "Unable to fetch ref %s from %s\n", 1479 ls->dentry_name, repo->url); 1480 aborted = 1; 1481 free(ref); 1482 return; 1483 } 1484 1485 o = parse_object(the_repository, &ref->old_oid); 1486 if (!o) { 1487 fprintf(stderr, 1488 "Unable to parse object %s for remote ref %s\n", 1489 oid_to_hex(&ref->old_oid), ls->dentry_name); 1490 aborted = 1; 1491 free(ref); 1492 return; 1493 } 1494 1495 strbuf_addf(buf, "%s\t%s\n", 1496 oid_to_hex(&ref->old_oid), ls->dentry_name); 1497 1498 if (o->type == OBJ_TAG) { 1499 o = deref_tag(the_repository, o, ls->dentry_name, 0); 1500 if (o) 1501 strbuf_addf(buf, "%s\t%s^{}\n", 1502 oid_to_hex(&o->oid), ls->dentry_name); 1503 } 1504 free(ref); 1505} 1506 1507static void update_remote_info_refs(struct remote_lock *lock) 1508{ 1509 struct buffer buffer = { STRBUF_INIT, 0 }; 1510 struct active_request_slot *slot; 1511 struct slot_results results; 1512 struct curl_slist *dav_headers; 1513 1514 remote_ls("refs/", (PROCESS_FILES | RECURSIVE), 1515 add_remote_info_ref, &buffer.buf); 1516 if (!aborted) { 1517 dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF); 1518 1519 slot = get_active_slot(); 1520 slot->results = &results; 1521 curl_setup_http(slot->curl, lock->url, DAV_PUT, 1522 &buffer, fwrite_null); 1523 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers); 1524 1525 if (start_active_slot(slot)) { 1526 run_active_slot(slot); 1527 if (results.curl_result != CURLE_OK) { 1528 fprintf(stderr, 1529 "PUT error: curl result=%d, HTTP code=%ld\n", 1530 results.curl_result, results.http_code); 1531 } 1532 } 1533 curl_slist_free_all(dav_headers); 1534 } 1535 strbuf_release(&buffer.buf); 1536} 1537 1538static int remote_exists(const char *path) 1539{ 1540 char *url = xstrfmt("%s%s", repo->url, path); 1541 int ret; 1542 1543 1544 switch (http_get_strbuf(url, NULL, NULL)) { 1545 case HTTP_OK: 1546 ret = 1; 1547 break; 1548 case HTTP_MISSING_TARGET: 1549 ret = 0; 1550 break; 1551 case HTTP_ERROR: 1552 error("unable to access '%s': %s", url, curl_errorstr); 1553 /* fallthrough */ 1554 default: 1555 ret = -1; 1556 } 1557 free(url); 1558 return ret; 1559} 1560 1561static void fetch_symref(const char *path, char **symref, struct object_id *oid) 1562{ 1563 char *url = xstrfmt("%s%s", repo->url, path); 1564 struct strbuf buffer = STRBUF_INIT; 1565 const char *name; 1566 1567 if (http_get_strbuf(url, &buffer, NULL) != HTTP_OK) 1568 die("Couldn't get %s for remote symref\n%s", url, 1569 curl_errorstr); 1570 free(url); 1571 1572 FREE_AND_NULL(*symref); 1573 oidclr(oid, the_repository->hash_algo); 1574 1575 if (buffer.len == 0) 1576 return; 1577 1578 /* Cut off trailing newline. */ 1579 strbuf_rtrim(&buffer); 1580 1581 /* If it's a symref, set the refname; otherwise try for a sha1 */ 1582 if (skip_prefix(buffer.buf, "ref: ", &name)) { 1583 *symref = xmemdupz(name, buffer.len - (name - buffer.buf)); 1584 } else { 1585 get_oid_hex(buffer.buf, oid); 1586 } 1587 1588 strbuf_release(&buffer); 1589} 1590 1591static int verify_merge_base(struct object_id *head_oid, struct ref *remote) 1592{ 1593 struct commit *head = lookup_commit_or_die(head_oid, "HEAD"); 1594 struct commit *branch = lookup_commit_or_die(&remote->old_oid, 1595 remote->name); 1596 int ret = repo_in_merge_bases(the_repository, branch, head); 1597 1598 if (ret < 0) 1599 exit(128); 1600 return ret; 1601} 1602 1603static int delete_remote_branch(const char *pattern, int force) 1604{ 1605 struct ref *refs = remote_refs; 1606 struct ref *remote_ref = NULL; 1607 struct object_id head_oid; 1608 char *symref = NULL; 1609 int match; 1610 int patlen = strlen(pattern); 1611 int i; 1612 struct active_request_slot *slot; 1613 struct slot_results results; 1614 char *url; 1615 1616 /* Find the remote branch(es) matching the specified branch name */ 1617 for (match = 0; refs; refs = refs->next) { 1618 char *name = refs->name; 1619 int namelen = strlen(name); 1620 if (namelen < patlen || 1621 memcmp(name + namelen - patlen, pattern, patlen)) 1622 continue; 1623 if (namelen != patlen && name[namelen - patlen - 1] != '/') 1624 continue; 1625 match++; 1626 remote_ref = refs; 1627 } 1628 if (match == 0) 1629 return error("No remote branch matches %s", pattern); 1630 if (match != 1) 1631 return error("More than one remote branch matches %s", 1632 pattern); 1633 1634 /* 1635 * Remote HEAD must be a symref (not exactly foolproof; a remote 1636 * symlink to a symref will look like a symref) 1637 */ 1638 fetch_symref("HEAD", &symref, &head_oid); 1639 if (!symref) 1640 return error("Remote HEAD is not a symref"); 1641 1642 /* Remote branch must not be the remote HEAD */ 1643 for (i = 0; symref && i < MAXDEPTH; i++) { 1644 if (!strcmp(remote_ref->name, symref)) 1645 return error("Remote branch %s is the current HEAD", 1646 remote_ref->name); 1647 fetch_symref(symref, &symref, &head_oid); 1648 } 1649 1650 /* Run extra sanity checks if delete is not forced */ 1651 if (!force) { 1652 /* Remote HEAD must resolve to a known object */ 1653 if (symref) 1654 return error("Remote HEAD symrefs too deep"); 1655 if (is_null_oid(&head_oid)) 1656 return error("Unable to resolve remote HEAD"); 1657 if (!odb_has_object(the_repository->objects, &head_oid, 1658 HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) 1659 return error("Remote HEAD resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", oid_to_hex(&head_oid)); 1660 1661 /* Remote branch must resolve to a known object */ 1662 if (is_null_oid(&remote_ref->old_oid)) 1663 return error("Unable to resolve remote branch %s", 1664 remote_ref->name); 1665 if (!odb_has_object(the_repository->objects, &remote_ref->old_oid, 1666 HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) 1667 return error("Remote branch %s resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", remote_ref->name, oid_to_hex(&remote_ref->old_oid)); 1668 1669 /* Remote branch must be an ancestor of remote HEAD */ 1670 if (!verify_merge_base(&head_oid, remote_ref)) { 1671 return error("The branch '%s' is not an ancestor " 1672 "of your current HEAD.\n" 1673 "If you are sure you want to delete it," 1674 " run:\n\t'git http-push -D %s %s'", 1675 remote_ref->name, repo->url, pattern); 1676 } 1677 } 1678 1679 /* Send delete request */ 1680 fprintf(stderr, "Removing remote branch '%s'\n", remote_ref->name); 1681 if (dry_run) 1682 return 0; 1683 url = xstrfmt("%s%s", repo->url, remote_ref->name); 1684 slot = get_active_slot(); 1685 slot->results = &results; 1686 curl_setup_http_get(slot->curl, url, DAV_DELETE); 1687 if (start_active_slot(slot)) { 1688 run_active_slot(slot); 1689 free(url); 1690 if (results.curl_result != CURLE_OK) 1691 return error("DELETE request failed (%d/%ld)", 1692 results.curl_result, results.http_code); 1693 } else { 1694 free(url); 1695 return error("Unable to start DELETE request"); 1696 } 1697 1698 return 0; 1699} 1700 1701static void run_request_queue(void) 1702{ 1703 is_running_queue = 1; 1704 fill_active_slots(); 1705 add_fill_function(NULL, fill_active_slot); 1706 do { 1707 finish_all_active_slots(); 1708 fill_active_slots(); 1709 } while (request_queue_head && !aborted); 1710 1711 is_running_queue = 0; 1712} 1713 1714int cmd_main(int argc, const char **argv) 1715{ 1716 struct transfer_request *request; 1717 struct transfer_request *next_request; 1718 struct refspec rs = REFSPEC_INIT_PUSH; 1719 struct remote_lock *ref_lock = NULL; 1720 struct remote_lock *info_ref_lock = NULL; 1721 int delete_branch = 0; 1722 int force_delete = 0; 1723 int objects_to_send; 1724 int rc = 0; 1725 int i; 1726 int new_refs; 1727 struct ref *ref, *local_refs = NULL; 1728 1729 CALLOC_ARRAY(repo, 1); 1730 1731 argv++; 1732 for (i = 1; i < argc; i++, argv++) { 1733 const char *arg = *argv; 1734 1735 if (*arg == '-') { 1736 if (!strcmp(arg, "--all")) { 1737 push_all = MATCH_REFS_ALL; 1738 continue; 1739 } 1740 if (!strcmp(arg, "--force")) { 1741 force_all = 1; 1742 continue; 1743 } 1744 if (!strcmp(arg, "--dry-run")) { 1745 dry_run = 1; 1746 continue; 1747 } 1748 if (!strcmp(arg, "--helper-status")) { 1749 helper_status = 1; 1750 continue; 1751 } 1752 if (!strcmp(arg, "--verbose")) { 1753 push_verbosely = 1; 1754 http_is_verbose = 1; 1755 continue; 1756 } 1757 if (!strcmp(arg, "-d")) { 1758 delete_branch = 1; 1759 continue; 1760 } 1761 if (!strcmp(arg, "-D")) { 1762 delete_branch = 1; 1763 force_delete = 1; 1764 continue; 1765 } 1766 if (!strcmp(arg, "-h")) 1767 usage(http_push_usage); 1768 } 1769 if (!repo->url) { 1770 char *path = strstr(arg, "//"); 1771 str_end_url_with_slash(arg, &repo->url); 1772 repo->path_len = strlen(repo->url); 1773 if (path) { 1774 repo->path = strchr(path+2, '/'); 1775 if (repo->path) 1776 repo->path_len = strlen(repo->path); 1777 } 1778 continue; 1779 } 1780 refspec_appendn(&rs, argv, argc - i); 1781 break; 1782 } 1783 1784 if (!repo->url) 1785 usage(http_push_usage); 1786 1787 if (delete_branch && rs.nr != 1) 1788 die("You must specify only one branch name when deleting a remote branch"); 1789 1790 setup_git_directory(); 1791 1792 memset(remote_dir_exists, -1, 256); 1793 1794 http_init(NULL, repo->url, 1); 1795 1796 is_running_queue = 0; 1797 1798 /* Verify DAV compliance/lock support */ 1799 if (!locking_available()) { 1800 rc = 1; 1801 goto cleanup; 1802 } 1803 1804 sigchain_push_common(remove_locks_on_signal); 1805 1806 /* Check whether the remote has server info files */ 1807 repo->can_update_info_refs = 0; 1808 repo->has_info_refs = remote_exists("info/refs"); 1809 repo->has_info_packs = remote_exists("objects/info/packs"); 1810 if (repo->has_info_refs) { 1811 info_ref_lock = lock_remote("info/refs", LOCK_TIME); 1812 if (info_ref_lock) 1813 repo->can_update_info_refs = 1; 1814 else { 1815 error("cannot lock existing info/refs"); 1816 rc = 1; 1817 goto cleanup; 1818 } 1819 } 1820 if (repo->has_info_packs) 1821 fetch_indices(); 1822 1823 /* Get a list of all local and remote heads to validate refspecs */ 1824 local_refs = get_local_heads(); 1825 fprintf(stderr, "Fetching remote heads...\n"); 1826 get_dav_remote_heads(); 1827 run_request_queue(); 1828 1829 /* Remove a remote branch if -d or -D was specified */ 1830 if (delete_branch) { 1831 const char *branch = rs.items[i].src; 1832 if (delete_remote_branch(branch, force_delete) == -1) { 1833 fprintf(stderr, "Unable to delete remote branch %s\n", 1834 branch); 1835 if (helper_status) 1836 printf("error %s cannot remove\n", branch); 1837 } 1838 goto cleanup; 1839 } 1840 1841 /* match them up */ 1842 if (match_push_refs(local_refs, &remote_refs, &rs, push_all)) { 1843 rc = -1; 1844 goto cleanup; 1845 } 1846 if (!remote_refs) { 1847 fprintf(stderr, "No refs in common and none specified; doing nothing.\n"); 1848 if (helper_status) 1849 printf("error null no match\n"); 1850 rc = 0; 1851 goto cleanup; 1852 } 1853 1854 new_refs = 0; 1855 for (ref = remote_refs; ref; ref = ref->next) { 1856 struct rev_info revs; 1857 struct strvec commit_argv = STRVEC_INIT; 1858 1859 if (!ref->peer_ref) 1860 continue; 1861 1862 if (is_null_oid(&ref->peer_ref->new_oid)) { 1863 if (delete_remote_branch(ref->name, 1) == -1) { 1864 error("Could not remove %s", ref->name); 1865 if (helper_status) 1866 printf("error %s cannot remove\n", ref->name); 1867 rc = -4; 1868 } 1869 else if (helper_status) 1870 printf("ok %s\n", ref->name); 1871 new_refs++; 1872 continue; 1873 } 1874 1875 if (oideq(&ref->old_oid, &ref->peer_ref->new_oid)) { 1876 if (push_verbosely) 1877 /* stable plumbing output; do not modify or localize */ 1878 fprintf(stderr, "'%s': up-to-date\n", ref->name); 1879 if (helper_status) 1880 printf("ok %s up to date\n", ref->name); 1881 continue; 1882 } 1883 1884 if (!force_all && 1885 !is_null_oid(&ref->old_oid) && 1886 !ref->force) { 1887 if (!odb_has_object(the_repository->objects, &ref->old_oid, 1888 HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR) || 1889 !ref_newer(&ref->peer_ref->new_oid, 1890 &ref->old_oid)) { 1891 /* 1892 * We do not have the remote ref, or 1893 * we know that the remote ref is not 1894 * an ancestor of what we are trying to 1895 * push. Either way this can be losing 1896 * commits at the remote end and likely 1897 * we were not up to date to begin with. 1898 */ 1899 /* stable plumbing output; do not modify or localize */ 1900 error("remote '%s' is not an ancestor of\n" 1901 "local '%s'.\n" 1902 "Maybe you are not up-to-date and " 1903 "need to pull first?", 1904 ref->name, 1905 ref->peer_ref->name); 1906 if (helper_status) 1907 printf("error %s non-fast forward\n", ref->name); 1908 rc = -2; 1909 continue; 1910 } 1911 } 1912 oidcpy(&ref->new_oid, &ref->peer_ref->new_oid); 1913 new_refs++; 1914 1915 fprintf(stderr, "updating '%s'", ref->name); 1916 if (strcmp(ref->name, ref->peer_ref->name)) 1917 fprintf(stderr, " using '%s'", ref->peer_ref->name); 1918 fprintf(stderr, "\n from %s\n to %s\n", 1919 oid_to_hex(&ref->old_oid), oid_to_hex(&ref->new_oid)); 1920 if (dry_run) { 1921 if (helper_status) 1922 printf("ok %s\n", ref->name); 1923 continue; 1924 } 1925 1926 /* Lock remote branch ref */ 1927 ref_lock = lock_remote(ref->name, LOCK_TIME); 1928 if (!ref_lock) { 1929 fprintf(stderr, "Unable to lock remote branch %s\n", 1930 ref->name); 1931 if (helper_status) 1932 printf("error %s lock error\n", ref->name); 1933 rc = 1; 1934 continue; 1935 } 1936 1937 /* Set up revision info for this refspec */ 1938 strvec_push(&commit_argv, ""); /* ignored */ 1939 strvec_push(&commit_argv, "--objects"); 1940 strvec_push(&commit_argv, oid_to_hex(&ref->new_oid)); 1941 if (!push_all && !is_null_oid(&ref->old_oid)) 1942 strvec_pushf(&commit_argv, "^%s", 1943 oid_to_hex(&ref->old_oid)); 1944 repo_init_revisions(the_repository, &revs, setup_git_directory()); 1945 setup_revisions_from_strvec(&commit_argv, &revs, NULL); 1946 revs.edge_hint = 0; /* just in case */ 1947 1948 /* Generate a list of objects that need to be pushed */ 1949 pushing = 0; 1950 if (prepare_revision_walk(&revs)) 1951 die("revision walk setup failed"); 1952 mark_edges_uninteresting(&revs, NULL, 0); 1953 objects_to_send = get_delta(&revs, ref_lock); 1954 finish_all_active_slots(); 1955 1956 /* Push missing objects to remote, this would be a 1957 convenient time to pack them first if appropriate. */ 1958 pushing = 1; 1959 if (objects_to_send) 1960 fprintf(stderr, " sending %d objects\n", 1961 objects_to_send); 1962 1963 run_request_queue(); 1964 1965 /* Update the remote branch if all went well */ 1966 if (aborted || !update_remote(&ref->new_oid, ref_lock)) 1967 rc = 1; 1968 1969 if (!rc) 1970 fprintf(stderr, " done\n"); 1971 if (helper_status) 1972 printf("%s %s\n", !rc ? "ok" : "error", ref->name); 1973 unlock_remote(ref_lock); 1974 check_locks(); 1975 strvec_clear(&commit_argv); 1976 release_revisions(&revs); 1977 } 1978 1979 /* Update remote server info if appropriate */ 1980 if (repo->has_info_refs && new_refs) { 1981 if (info_ref_lock && repo->can_update_info_refs) { 1982 fprintf(stderr, "Updating remote server info\n"); 1983 if (!dry_run) 1984 update_remote_info_refs(info_ref_lock); 1985 } else { 1986 fprintf(stderr, "Unable to update server info\n"); 1987 } 1988 } 1989 1990 cleanup: 1991 if (info_ref_lock) 1992 unlock_remote(info_ref_lock); 1993 free(repo->url); 1994 free(repo); 1995 1996 http_cleanup(); 1997 1998 request = request_queue_head; 1999 while (request != NULL) { 2000 next_request = request->next; 2001 release_request(request); 2002 request = next_request; 2003 } 2004 2005 refspec_clear(&rs); 2006 free_refs(local_refs); 2007 2008 return rc; 2009}