afdcd8b8d381753620c83f157666b4e7617ea19a
   1#include "cache.h"
   2#include "commit.h"
   3#include "pack.h"
   4#include "fetch.h"
   5#include "tag.h"
   6#include "blob.h"
   7#include "http.h"
   8
   9#ifdef USE_CURL_MULTI
  10
  11#include <expat.h>
  12
  13static const char http_push_usage[] =
  14"git-http-push [--complete] [--force] [--verbose] <url> <ref> [<ref>...]\n";
  15
  16#ifndef XML_STATUS_OK
  17enum XML_Status {
  18  XML_STATUS_OK = 1,
  19  XML_STATUS_ERROR = 0
  20};
  21#define XML_STATUS_OK    1
  22#define XML_STATUS_ERROR 0
  23#endif
  24
  25#define RANGE_HEADER_SIZE 30
  26
  27/* DAV method names and request body templates */
  28#define DAV_LOCK "LOCK"
  29#define DAV_MKCOL "MKCOL"
  30#define DAV_MOVE "MOVE"
  31#define DAV_PROPFIND "PROPFIND"
  32#define DAV_PUT "PUT"
  33#define DAV_UNLOCK "UNLOCK"
  34#define PROPFIND_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>"
  35#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>"
  36
  37#define LOCK_TIME 600
  38#define LOCK_REFRESH 30
  39
  40static int pushing = 0;
  41static int aborted = 0;
  42static char remote_dir_exists[256];
  43
  44static struct curl_slist *no_pragma_header;
  45static struct curl_slist *default_headers;
  46
  47static int push_verbosely = 0;
  48static int push_all = 0;
  49static int force_all = 0;
  50
  51struct repo
  52{
  53        char *url;
  54        struct packed_git *packs;
  55};
  56
  57static struct repo *remote = NULL;
  58
  59enum transfer_state {
  60        NEED_CHECK,
  61        RUN_HEAD,
  62        NEED_PUSH,
  63        RUN_MKCOL,
  64        RUN_PUT,
  65        RUN_MOVE,
  66        ABORTED,
  67        COMPLETE,
  68};
  69
  70struct transfer_request
  71{
  72        unsigned char sha1[20];
  73        char *url;
  74        char *dest;
  75        struct active_lock *lock;
  76        struct curl_slist *headers;
  77        struct buffer buffer;
  78        char filename[PATH_MAX];
  79        char tmpfile[PATH_MAX];
  80        enum transfer_state state;
  81        CURLcode curl_result;
  82        char errorstr[CURL_ERROR_SIZE];
  83        long http_code;
  84        unsigned char real_sha1[20];
  85        SHA_CTX c;
  86        z_stream stream;
  87        int zret;
  88        int rename;
  89        struct active_request_slot *slot;
  90        struct transfer_request *next;
  91};
  92
  93static struct transfer_request *request_queue_head = NULL;
  94
  95struct active_lock
  96{
  97        int ctx_activelock;
  98        int ctx_owner;
  99        int ctx_owner_href;
 100        int ctx_timeout;
 101        int ctx_locktoken;
 102        int ctx_locktoken_href;
 103        char *url;
 104        char *owner;
 105        char *token;
 106        time_t start_time;
 107        long timeout;
 108        int refreshing;
 109};
 110
 111struct lockprop
 112{
 113        int supported_lock;
 114        int lock_entry;
 115        int lock_scope;
 116        int lock_type;
 117        int lock_exclusive;
 118        int lock_exclusive_write;
 119};
 120
 121static void finish_request(struct transfer_request *request);
 122
 123static void process_response(void *callback_data)
 124{
 125        struct transfer_request *request =
 126                (struct transfer_request *)callback_data;
 127
 128        finish_request(request);
 129}
 130
 131static void start_check(struct transfer_request *request)
 132{
 133        char *hex = sha1_to_hex(request->sha1);
 134        struct active_request_slot *slot;
 135        char *posn;
 136
 137        request->url = xmalloc(strlen(remote->url) + 55);
 138        strcpy(request->url, remote->url);
 139        posn = request->url + strlen(remote->url);
 140        strcpy(posn, "objects/");
 141        posn += 8;
 142        memcpy(posn, hex, 2);
 143        posn += 2;
 144        *(posn++) = '/';
 145        strcpy(posn, hex + 2);
 146
 147        slot = get_active_slot();
 148        slot->callback_func = process_response;
 149        slot->callback_data = request;
 150        curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
 151        curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
 152        curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
 153
 154        if (start_active_slot(slot)) {
 155                request->slot = slot;
 156                request->state = RUN_HEAD;
 157        } else {
 158                request->state = ABORTED;
 159                free(request->url);
 160        }
 161}
 162
 163static void start_mkcol(struct transfer_request *request)
 164{
 165        char *hex = sha1_to_hex(request->sha1);
 166        struct active_request_slot *slot;
 167        char *posn;
 168
 169        request->url = xmalloc(strlen(remote->url) + 13);
 170        strcpy(request->url, remote->url);
 171        posn = request->url + strlen(remote->url);
 172        strcpy(posn, "objects/");
 173        posn += 8;
 174        memcpy(posn, hex, 2);
 175        posn += 2;
 176        strcpy(posn, "/");
 177
 178        slot = get_active_slot();
 179        slot->callback_func = process_response;
 180        slot->callback_data = request;
 181        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); /* undo PUT setup */
 182        curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
 183        curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
 184        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MKCOL);
 185        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
 186
 187        if (start_active_slot(slot)) {
 188                request->slot = slot;
 189                request->state = RUN_MKCOL;
 190        } else {
 191                request->state = ABORTED;
 192                free(request->url);
 193        }
 194}
 195
 196static void start_put(struct transfer_request *request)
 197{
 198        char *hex = sha1_to_hex(request->sha1);
 199        struct active_request_slot *slot;
 200        char *posn;
 201        char type[20];
 202        char hdr[50];
 203        void *unpacked;
 204        unsigned long len;
 205        int hdrlen;
 206        ssize_t size;
 207        z_stream stream;
 208
 209        unpacked = read_sha1_file(request->sha1, type, &len);
 210        hdrlen = sprintf(hdr, "%s %lu", type, len) + 1;
 211
 212        /* Set it up */
 213        memset(&stream, 0, sizeof(stream));
 214        deflateInit(&stream, Z_BEST_COMPRESSION);
 215        size = deflateBound(&stream, len + hdrlen);
 216        request->buffer.buffer = xmalloc(size);
 217
 218        /* Compress it */
 219        stream.next_out = request->buffer.buffer;
 220        stream.avail_out = size;
 221
 222        /* First header.. */
 223        stream.next_in = (void *)hdr;
 224        stream.avail_in = hdrlen;
 225        while (deflate(&stream, 0) == Z_OK)
 226                /* nothing */;
 227
 228        /* Then the data itself.. */
 229        stream.next_in = unpacked;
 230        stream.avail_in = len;
 231        while (deflate(&stream, Z_FINISH) == Z_OK)
 232                /* nothing */;
 233        deflateEnd(&stream);
 234        free(unpacked);
 235
 236        request->buffer.size = stream.total_out;
 237        request->buffer.posn = 0;
 238
 239        if (request->url != NULL)
 240                free(request->url);
 241        request->url = xmalloc(strlen(remote->url) + 
 242                               strlen(request->lock->token) + 51);
 243        strcpy(request->url, remote->url);
 244        posn = request->url + strlen(remote->url);
 245        strcpy(posn, "objects/");
 246        posn += 8;
 247        memcpy(posn, hex, 2);
 248        posn += 2;
 249        *(posn++) = '/';
 250        strcpy(posn, hex + 2);
 251        request->dest = xmalloc(strlen(request->url) + 14);
 252        sprintf(request->dest, "Destination: %s", request->url);
 253        posn += 38;
 254        *(posn++) = '.';
 255        strcpy(posn, request->lock->token);
 256
 257        slot = get_active_slot();
 258        slot->callback_func = process_response;
 259        slot->callback_data = request;
 260        curl_easy_setopt(slot->curl, CURLOPT_INFILE, &request->buffer);
 261        curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, request->buffer.size);
 262        curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
 263        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
 264        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
 265        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
 266        curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
 267        curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
 268        curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
 269
 270        if (start_active_slot(slot)) {
 271                request->slot = slot;
 272                request->state = RUN_PUT;
 273        } else {
 274                request->state = ABORTED;
 275                free(request->url);
 276        }
 277}
 278
 279static void start_move(struct transfer_request *request)
 280{
 281        struct active_request_slot *slot;
 282        struct curl_slist *dav_headers = NULL;
 283
 284        slot = get_active_slot();
 285        slot->callback_func = process_response;
 286        slot->callback_data = request;
 287        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); /* undo PUT setup */
 288        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MOVE);
 289        dav_headers = curl_slist_append(dav_headers, request->dest);
 290        dav_headers = curl_slist_append(dav_headers, "Overwrite: T");
 291        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
 292        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
 293        curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
 294
 295        if (start_active_slot(slot)) {
 296                request->slot = slot;
 297                request->state = RUN_MOVE;
 298        } else {
 299                request->state = ABORTED;
 300                free(request->url);
 301        }
 302}
 303
 304static int refresh_lock(struct active_lock *lock)
 305{
 306        struct active_request_slot *slot;
 307        char *if_header;
 308        char timeout_header[25];
 309        struct curl_slist *dav_headers = NULL;
 310        int rc = 0;
 311
 312        lock->refreshing = 1;
 313
 314        if_header = xmalloc(strlen(lock->token) + 25);
 315        sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
 316        sprintf(timeout_header, "Timeout: Second-%ld", lock->timeout);
 317        dav_headers = curl_slist_append(dav_headers, if_header);
 318        dav_headers = curl_slist_append(dav_headers, timeout_header);
 319
 320        slot = get_active_slot();
 321        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
 322        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
 323        curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
 324        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
 325        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
 326
 327        if (start_active_slot(slot)) {
 328                run_active_slot(slot);
 329                if (slot->curl_result != CURLE_OK) {
 330                        fprintf(stderr, "Got HTTP error %ld\n", slot->http_code);
 331                } else {
 332                        lock->start_time = time(NULL);
 333                        rc = 1;
 334                }
 335        }
 336
 337        lock->refreshing = 0;
 338        curl_slist_free_all(dav_headers);
 339        free(if_header);
 340
 341        return rc;
 342}
 343
 344static void finish_request(struct transfer_request *request)
 345{
 346        time_t current_time = time(NULL);
 347        int time_remaining;
 348
 349        request->curl_result =  request->slot->curl_result;
 350        request->http_code = request->slot->http_code;
 351        request->slot = NULL;
 352
 353        /* Refresh the lock if it is close to timing out */
 354        time_remaining = request->lock->start_time + request->lock->timeout
 355                - current_time;
 356        if (time_remaining < LOCK_REFRESH && !request->lock->refreshing) {
 357                if (!refresh_lock(request->lock)) {
 358                        fprintf(stderr, "Unable to refresh remote lock\n");
 359                        aborted = 1;
 360                }
 361        }
 362
 363        if (request->headers != NULL)
 364                curl_slist_free_all(request->headers);
 365        if (request->state == RUN_HEAD) {
 366                if (request->http_code == 404) {
 367                        request->state = NEED_PUSH;
 368                } else if (request->curl_result == CURLE_OK) {
 369                        remote_dir_exists[request->sha1[0]] = 1;
 370                        request->state = COMPLETE;
 371                } else {
 372                        fprintf(stderr, "HEAD %s failed, aborting (%d/%ld)\n",
 373                                sha1_to_hex(request->sha1),
 374                                request->curl_result, request->http_code);
 375                        request->state = ABORTED;
 376                        aborted = 1;
 377                }
 378        } else if (request->state == RUN_MKCOL) {
 379                if (request->curl_result == CURLE_OK ||
 380                    request->http_code == 405) {
 381                        remote_dir_exists[request->sha1[0]] = 1;
 382                        start_put(request);
 383                } else {
 384                        fprintf(stderr, "MKCOL %s failed, aborting (%d/%ld)\n",
 385                                sha1_to_hex(request->sha1),
 386                                request->curl_result, request->http_code);
 387                        request->state = ABORTED;
 388                        aborted = 1;
 389                }
 390        } else if (request->state == RUN_PUT) {
 391                if (request->curl_result == CURLE_OK) {
 392                        start_move(request);
 393                } else {
 394                        fprintf(stderr, "PUT %s failed, aborting (%d/%ld)\n",
 395                                sha1_to_hex(request->sha1),
 396                                request->curl_result, request->http_code);
 397                        request->state = ABORTED;
 398                        aborted = 1;
 399                }
 400        } else if (request->state == RUN_MOVE) {
 401                if (request->curl_result == CURLE_OK) {
 402                        if (push_verbosely)
 403                                fprintf(stderr,
 404                                        "sent %s\n",
 405                                        sha1_to_hex(request->sha1));
 406                        request->state = COMPLETE;
 407                } else {
 408                        fprintf(stderr, "MOVE %s failed, aborting (%d/%ld)\n",
 409                                sha1_to_hex(request->sha1),
 410                                request->curl_result, request->http_code);
 411                        request->state = ABORTED;
 412                        aborted = 1;
 413                }
 414        }
 415}
 416
 417static void release_request(struct transfer_request *request)
 418{
 419        struct transfer_request *entry = request_queue_head;
 420
 421        if (request == request_queue_head) {
 422                request_queue_head = request->next;
 423        } else {
 424                while (entry->next != NULL && entry->next != request)
 425                        entry = entry->next;
 426                if (entry->next == request)
 427                        entry->next = entry->next->next;
 428        }
 429
 430        free(request->url);
 431        free(request);
 432}
 433
 434void fill_active_slots(void)
 435{
 436        struct transfer_request *request = request_queue_head;
 437        struct active_request_slot *slot = active_queue_head;
 438        int num_transfers;
 439
 440        if (aborted)
 441                return;
 442
 443        while (active_requests < max_requests && request != NULL) {
 444                if (!pushing && request->state == NEED_CHECK) {
 445                        start_check(request);
 446                        curl_multi_perform(curlm, &num_transfers);
 447                } else if (pushing && request->state == NEED_PUSH) {
 448                        if (remote_dir_exists[request->sha1[0]])
 449                                start_put(request);
 450                        else
 451                                start_mkcol(request);
 452                        curl_multi_perform(curlm, &num_transfers);
 453                }
 454                request = request->next;
 455        }
 456
 457        while (slot != NULL) {
 458                if (!slot->in_use && slot->curl != NULL) {
 459                        curl_easy_cleanup(slot->curl);
 460                        slot->curl = NULL;
 461                }
 462                slot = slot->next;
 463        }                               
 464}
 465
 466static void add_request(unsigned char *sha1, struct active_lock *lock)
 467{
 468        struct transfer_request *request = request_queue_head;
 469        struct packed_git *target;
 470        
 471        while (request != NULL && memcmp(request->sha1, sha1, 20))
 472                request = request->next;
 473        if (request != NULL)
 474                return;
 475
 476        target = find_sha1_pack(sha1, remote->packs);
 477        if (target)
 478                return;
 479
 480        request = xmalloc(sizeof(*request));
 481        memcpy(request->sha1, sha1, 20);
 482        request->url = NULL;
 483        request->lock = lock;
 484        request->headers = NULL;
 485        request->state = NEED_CHECK;
 486        request->next = request_queue_head;
 487        request_queue_head = request;
 488
 489        fill_active_slots();
 490        step_active_slots();
 491}
 492
 493static int fetch_index(unsigned char *sha1)
 494{
 495        char *hex = sha1_to_hex(sha1);
 496        char *filename;
 497        char *url;
 498        char tmpfile[PATH_MAX];
 499        long prev_posn = 0;
 500        char range[RANGE_HEADER_SIZE];
 501        struct curl_slist *range_header = NULL;
 502
 503        FILE *indexfile;
 504        struct active_request_slot *slot;
 505
 506        /* Don't use the index if the pack isn't there */
 507        url = xmalloc(strlen(remote->url) + 65);
 508        sprintf(url, "%s/objects/pack/pack-%s.pack", remote->url, hex);
 509        slot = get_active_slot();
 510        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
 511        curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
 512        if (start_active_slot(slot)) {
 513                run_active_slot(slot);
 514                if (slot->curl_result != CURLE_OK) {
 515                        free(url);
 516                        return error("Unable to verify pack %s is available",
 517                                     hex);
 518                }
 519        } else {
 520                return error("Unable to start request");
 521        }
 522
 523        if (has_pack_index(sha1))
 524                return 0;
 525
 526        if (push_verbosely)
 527                fprintf(stderr, "Getting index for pack %s\n", hex);
 528        
 529        sprintf(url, "%s/objects/pack/pack-%s.idx", remote->url, hex);
 530        
 531        filename = sha1_pack_index_name(sha1);
 532        snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
 533        indexfile = fopen(tmpfile, "a");
 534        if (!indexfile)
 535                return error("Unable to open local file %s for pack index",
 536                             filename);
 537
 538        slot = get_active_slot();
 539        curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
 540        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
 541        curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
 542        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
 543        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
 544        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
 545        slot->local = indexfile;
 546
 547        /* If there is data present from a previous transfer attempt,
 548           resume where it left off */
 549        prev_posn = ftell(indexfile);
 550        if (prev_posn>0) {
 551                if (push_verbosely)
 552                        fprintf(stderr,
 553                                "Resuming fetch of index for pack %s at byte %ld\n",
 554                                hex, prev_posn);
 555                sprintf(range, "Range: bytes=%ld-", prev_posn);
 556                range_header = curl_slist_append(range_header, range);
 557                curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
 558        }
 559
 560        if (start_active_slot(slot)) {
 561                run_active_slot(slot);
 562                if (slot->curl_result != CURLE_OK) {
 563                        free(url);
 564                        fclose(indexfile);
 565                        return error("Unable to get pack index %s\n%s", url,
 566                                     curl_errorstr);
 567                }
 568        } else {
 569                free(url);
 570                return error("Unable to start request");
 571        }
 572
 573        free(url);
 574        fclose(indexfile);
 575
 576        return move_temp_to_file(tmpfile, filename);
 577}
 578
 579static int setup_index(unsigned char *sha1)
 580{
 581        struct packed_git *new_pack;
 582
 583        if (fetch_index(sha1))
 584                return -1;
 585
 586        new_pack = parse_pack_index(sha1);
 587        new_pack->next = remote->packs;
 588        remote->packs = new_pack;
 589        return 0;
 590}
 591
 592static int fetch_indices(void)
 593{
 594        unsigned char sha1[20];
 595        char *url;
 596        struct buffer buffer;
 597        char *data;
 598        int i = 0;
 599
 600        struct active_request_slot *slot;
 601
 602        data = xmalloc(4096);
 603        memset(data, 0, 4096);
 604        buffer.size = 4096;
 605        buffer.posn = 0;
 606        buffer.buffer = data;
 607
 608        if (push_verbosely)
 609                fprintf(stderr, "Getting pack list\n");
 610        
 611        url = xmalloc(strlen(remote->url) + 21);
 612        sprintf(url, "%s/objects/info/packs", remote->url);
 613
 614        slot = get_active_slot();
 615        curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
 616        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
 617        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
 618        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
 619        if (start_active_slot(slot)) {
 620                run_active_slot(slot);
 621                if (slot->curl_result != CURLE_OK) {
 622                        free(buffer.buffer);
 623                        free(url);
 624                        if (slot->http_code == 404)
 625                                return 0;
 626                        else
 627                                return error("%s", curl_errorstr);
 628                }
 629        } else {
 630                free(buffer.buffer);
 631                free(url);
 632                return error("Unable to start request");
 633        }
 634        free(url);
 635
 636        data = buffer.buffer;
 637        while (i < buffer.posn) {
 638                switch (data[i]) {
 639                case 'P':
 640                        i++;
 641                        if (i + 52 < buffer.posn &&
 642                            !strncmp(data + i, " pack-", 6) &&
 643                            !strncmp(data + i + 46, ".pack\n", 6)) {
 644                                get_sha1_hex(data + i + 6, sha1);
 645                                setup_index(sha1);
 646                                i += 51;
 647                                break;
 648                        }
 649                default:
 650                        while (data[i] != '\n')
 651                                i++;
 652                }
 653                i++;
 654        }
 655
 656        free(buffer.buffer);
 657        return 0;
 658}
 659
 660static inline int needs_quote(int ch)
 661{
 662        switch (ch) {
 663        case '/': case '-': case '.':
 664        case 'A'...'Z': case 'a'...'z': case '0'...'9':
 665                return 0;
 666        default:
 667                return 1;
 668        }
 669}
 670
 671static inline int hex(int v)
 672{
 673        if (v < 10) return '0' + v;
 674        else return 'A' + v - 10;
 675}
 676
 677static char *quote_ref_url(const char *base, const char *ref)
 678{
 679        const char *cp;
 680        char *dp, *qref;
 681        int len, baselen, ch;
 682
 683        baselen = strlen(base);
 684        len = baselen + 12; /* "refs/heads/" + NUL */
 685        for (cp = ref; (ch = *cp) != 0; cp++, len++)
 686                if (needs_quote(ch))
 687                        len += 2; /* extra two hex plus replacement % */
 688        qref = xmalloc(len);
 689        memcpy(qref, base, baselen);
 690        memcpy(qref + baselen, "refs/heads/", 11);
 691        for (cp = ref, dp = qref + baselen + 11; (ch = *cp) != 0; cp++) {
 692                if (needs_quote(ch)) {
 693                        *dp++ = '%';
 694                        *dp++ = hex((ch >> 4) & 0xF);
 695                        *dp++ = hex(ch & 0xF);
 696                }
 697                else
 698                        *dp++ = ch;
 699        }
 700        *dp = 0;
 701
 702        return qref;
 703}
 704
 705int fetch_ref(char *ref, unsigned char *sha1)
 706{
 707        char *url;
 708        char hex[42];
 709        struct buffer buffer;
 710        char *base = remote->url;
 711        struct active_request_slot *slot;
 712        buffer.size = 41;
 713        buffer.posn = 0;
 714        buffer.buffer = hex;
 715        hex[41] = '\0';
 716        
 717        url = quote_ref_url(base, ref);
 718        slot = get_active_slot();
 719        curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
 720        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
 721        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
 722        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
 723        if (start_active_slot(slot)) {
 724                run_active_slot(slot);
 725                if (slot->curl_result != CURLE_OK)
 726                        return error("Couldn't get %s for %s\n%s",
 727                                     url, ref, curl_errorstr);
 728        } else {
 729                return error("Unable to start request");
 730        }
 731
 732        hex[40] = '\0';
 733        get_sha1_hex(hex, sha1);
 734        return 0;
 735}
 736
 737static void
 738start_activelock_element(void *userData, const char *name, const char **atts)
 739{
 740        struct active_lock *lock = (struct active_lock *)userData;
 741
 742        if (lock->ctx_activelock && !strcmp(name, "D:timeout"))
 743                lock->ctx_timeout = 1;
 744        else if (lock->ctx_owner && strstr(name, "href"))
 745                lock->ctx_owner_href = 1;
 746        else if (lock->ctx_activelock && strstr(name, "owner"))
 747                lock->ctx_owner = 1;
 748        else if (lock->ctx_locktoken && !strcmp(name, "D:href"))
 749                lock->ctx_locktoken_href = 1;
 750        else if (lock->ctx_activelock && !strcmp(name, "D:locktoken"))
 751                lock->ctx_locktoken = 1;
 752        else if (!strcmp(name, "D:activelock"))
 753                lock->ctx_activelock = 1;
 754}
 755
 756static void
 757end_activelock_element(void *userData, const char *name)
 758{
 759        struct active_lock *lock = (struct active_lock *)userData;
 760
 761        if (lock->ctx_timeout && !strcmp(name, "D:timeout")) {
 762                lock->ctx_timeout = 0;
 763        } else if (lock->ctx_owner_href && strstr(name, "href")) {
 764                lock->ctx_owner_href = 0;
 765        } else if (lock->ctx_owner && strstr(name, "owner")) {
 766                lock->ctx_owner = 0;
 767        } else if (lock->ctx_locktoken_href && !strcmp(name, "D:href")) {
 768                lock->ctx_locktoken_href = 0;
 769        } else if (lock->ctx_locktoken && !strcmp(name, "D:locktoken")) {
 770                lock->ctx_locktoken = 0;
 771        } else if (lock->ctx_activelock && !strcmp(name, "D:activelock")) {
 772                lock->ctx_activelock = 0;
 773        }
 774}
 775
 776static void
 777activelock_cdata(void *userData, const XML_Char *s, int len)
 778{
 779        struct active_lock *lock = (struct active_lock *)userData;
 780        char *this = malloc(len+1);
 781        strncpy(this, s, len);
 782
 783        if (lock->ctx_owner_href) {
 784                lock->owner = malloc(len+1);
 785                strcpy(lock->owner, this);
 786        } else if (lock->ctx_locktoken_href) {
 787                if (!strncmp(this, "opaquelocktoken:", 16)) {
 788                        lock->token = malloc(len-15);
 789                        strcpy(lock->token, this+16);
 790                }
 791        } else if (lock->ctx_timeout) {
 792                if (!strncmp(this, "Second-", 7))
 793                        lock->timeout = strtol(this+7, NULL, 10);
 794        }
 795
 796        free(this);
 797}
 798
 799static void
 800start_lockprop_element(void *userData, const char *name, const char **atts)
 801{
 802        struct lockprop *prop = (struct lockprop *)userData;
 803
 804        if (prop->lock_type && !strcmp(name, "D:write")) {
 805                if (prop->lock_exclusive) {
 806                        prop->lock_exclusive_write = 1;
 807                }
 808        } else if (prop->lock_scope && !strcmp(name, "D:exclusive")) {
 809                prop->lock_exclusive = 1;
 810        } else if (prop->lock_entry) {
 811                if (!strcmp(name, "D:lockscope")) {
 812                        prop->lock_scope = 1;
 813                } else if (!strcmp(name, "D:locktype")) {
 814                        prop->lock_type = 1;
 815                }
 816        } else if (prop->supported_lock) {
 817                if (!strcmp(name, "D:lockentry")) {
 818                        prop->lock_entry = 1;
 819                }
 820        } else if (!strcmp(name, "D:supportedlock")) {
 821                prop->supported_lock = 1;
 822        }
 823}
 824
 825static void
 826end_lockprop_element(void *userData, const char *name)
 827{
 828        struct lockprop *prop = (struct lockprop *)userData;
 829
 830        if (!strcmp(name, "D:lockentry")) {
 831                prop->lock_entry = 0;
 832                prop->lock_scope = 0;
 833                prop->lock_type = 0;
 834                prop->lock_exclusive = 0;
 835        } else if (!strcmp(name, "D:supportedlock")) {
 836                prop->supported_lock = 0;
 837        }
 838}
 839
 840static struct active_lock *lock_remote(char *file, long timeout)
 841{
 842        struct active_request_slot *slot;
 843        struct buffer out_buffer;
 844        struct buffer in_buffer;
 845        char *out_data;
 846        char *in_data;
 847        char *url;
 848        char *ep;
 849        char timeout_header[25];
 850        struct active_lock *new_lock;
 851        XML_Parser parser = XML_ParserCreate(NULL);
 852        enum XML_Status result;
 853        struct curl_slist *dav_headers = NULL;
 854
 855        url = xmalloc(strlen(remote->url) + strlen(file) + 1);
 856        sprintf(url, "%s%s", remote->url, file);
 857
 858        /* Make sure leading directories exist for the remote ref */
 859        ep = strchr(url + strlen(remote->url) + 11, '/');
 860        while (ep) {
 861                *ep = 0;
 862                slot = get_active_slot();
 863                curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
 864                curl_easy_setopt(slot->curl, CURLOPT_URL, url);
 865                curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MKCOL);
 866                curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
 867                if (start_active_slot(slot)) {
 868                        run_active_slot(slot);
 869                        if (slot->curl_result != CURLE_OK &&
 870                            slot->http_code != 405) {
 871                                fprintf(stderr,
 872                                        "Unable to create branch path %s\n",
 873                                        url);
 874                                free(url);
 875                                return NULL;
 876                        }
 877                } else {
 878                        fprintf(stderr, "Unable to start request\n");
 879                        free(url);
 880                        return NULL;
 881                }
 882                *ep = '/';
 883                ep = strchr(ep + 1, '/');
 884        }
 885
 886        out_buffer.size = strlen(LOCK_REQUEST) + strlen(git_default_email) - 2;
 887        out_data = xmalloc(out_buffer.size + 1);
 888        snprintf(out_data, out_buffer.size + 1, LOCK_REQUEST, git_default_email);
 889        out_buffer.posn = 0;
 890        out_buffer.buffer = out_data;
 891
 892        in_buffer.size = 4096;
 893        in_data = xmalloc(in_buffer.size);
 894        in_buffer.posn = 0;
 895        in_buffer.buffer = in_data;
 896
 897        new_lock = xcalloc(1, sizeof(*new_lock));
 898        new_lock->owner = NULL;
 899        new_lock->token = NULL;
 900        new_lock->timeout = -1;
 901        new_lock->refreshing = 0;
 902
 903        sprintf(timeout_header, "Timeout: Second-%ld", timeout);
 904        dav_headers = curl_slist_append(dav_headers, timeout_header);
 905        dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
 906
 907        slot = get_active_slot();
 908        curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
 909        curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
 910        curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
 911        curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
 912        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
 913        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
 914        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
 915        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
 916        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
 917
 918        if (start_active_slot(slot)) {
 919                run_active_slot(slot);
 920                if (slot->curl_result != CURLE_OK) {
 921                        fprintf(stderr, "Got HTTP error %ld\n", slot->http_code);
 922                        free(new_lock);
 923                        free(url);
 924                        free(out_data);
 925                        free(in_data);
 926                        return NULL;
 927                }
 928        } else {
 929                free(new_lock);
 930                free(url);
 931                free(out_data);
 932                free(in_data);
 933                fprintf(stderr, "Unable to start request\n");
 934                return NULL;
 935        }
 936
 937        free(out_data);
 938
 939        XML_SetUserData(parser, new_lock);
 940        XML_SetElementHandler(parser, start_activelock_element,
 941                                      end_activelock_element);
 942        XML_SetCharacterDataHandler(parser, activelock_cdata);
 943        result = XML_Parse(parser, in_buffer.buffer, in_buffer.posn, 1);
 944        free(in_data);
 945        if (result != XML_STATUS_OK) {
 946                fprintf(stderr, "%s", XML_ErrorString(
 947                                XML_GetErrorCode(parser)));
 948                free(url);
 949                free(new_lock);
 950                return NULL;
 951        }
 952
 953        if (new_lock->token == NULL || new_lock->timeout <= 0) {
 954                if (new_lock->token != NULL)
 955                        free(new_lock->token);
 956                if (new_lock->owner != NULL)
 957                        free(new_lock->owner);
 958                free(url);
 959                free(new_lock);
 960                return NULL;
 961        }
 962
 963        new_lock->url = url;
 964        new_lock->start_time = time(NULL);
 965        return new_lock;
 966}
 967
 968static int unlock_remote(struct active_lock *lock)
 969{
 970        struct active_request_slot *slot;
 971        char *lock_token_header;
 972        struct curl_slist *dav_headers = NULL;
 973        int rc = 0;
 974
 975        lock_token_header = xmalloc(strlen(lock->token) + 31);
 976        sprintf(lock_token_header, "Lock-Token: <opaquelocktoken:%s>",
 977                lock->token);
 978        dav_headers = curl_slist_append(dav_headers, lock_token_header);
 979
 980        slot = get_active_slot();
 981        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
 982        curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
 983        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_UNLOCK);
 984        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
 985
 986        if (start_active_slot(slot)) {
 987                run_active_slot(slot);
 988                if (slot->curl_result == CURLE_OK)
 989                        rc = 1;
 990                else
 991                        fprintf(stderr, "Got HTTP error %ld\n",
 992                                slot->http_code);
 993        } else {
 994                fprintf(stderr, "Unable to start request\n");
 995        }
 996
 997        curl_slist_free_all(dav_headers);
 998        free(lock_token_header);
 999
1000        if (lock->owner != NULL)
1001                free(lock->owner);
1002        free(lock->url);
1003        free(lock->token);
1004        free(lock);
1005
1006        return rc;
1007}
1008
1009static int check_locking(void)
1010{
1011        struct active_request_slot *slot;
1012        struct buffer in_buffer;
1013        struct buffer out_buffer;
1014        char *in_data;
1015        char *out_data;
1016        XML_Parser parser = XML_ParserCreate(NULL);
1017        enum XML_Status result;
1018        struct lockprop supported_lock;
1019        struct curl_slist *dav_headers = NULL;
1020
1021        out_buffer.size = strlen(PROPFIND_REQUEST) + strlen(remote->url) - 2;
1022        out_data = xmalloc(out_buffer.size + 1);
1023        snprintf(out_data, out_buffer.size + 1, PROPFIND_REQUEST, remote->url);
1024        out_buffer.posn = 0;
1025        out_buffer.buffer = out_data;
1026
1027        in_buffer.size = 4096;
1028        in_data = xmalloc(in_buffer.size);
1029        in_buffer.posn = 0;
1030        in_buffer.buffer = in_data;
1031
1032        dav_headers = curl_slist_append(dav_headers, "Depth: 0");
1033        dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1034        
1035        slot = get_active_slot();
1036        curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1037        curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1038        curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1039        curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1040        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1041        curl_easy_setopt(slot->curl, CURLOPT_URL, remote->url);
1042        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1043        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
1044        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1045
1046        if (start_active_slot(slot)) {
1047                run_active_slot(slot);
1048                free(out_data);
1049                if (slot->curl_result != CURLE_OK) {
1050                        free(in_buffer.buffer);
1051                        return -1;
1052                }
1053
1054                XML_SetUserData(parser, &supported_lock);
1055                XML_SetElementHandler(parser, start_lockprop_element,
1056                                      end_lockprop_element);
1057                result = XML_Parse(parser, in_buffer.buffer, in_buffer.posn, 1);
1058                free(in_buffer.buffer);
1059                if (result != XML_STATUS_OK)
1060                        return error("%s", XML_ErrorString(
1061                                             XML_GetErrorCode(parser)));
1062        } else {
1063                free(out_data);
1064                free(in_buffer.buffer);
1065                return error("Unable to start request");
1066        }
1067
1068        if (supported_lock.lock_exclusive_write)
1069                return 0;
1070        else
1071                return 1;
1072}
1073
1074static int is_ancestor(unsigned char *sha1, struct commit *commit)
1075{
1076        struct commit_list *parents;
1077
1078        if (parse_commit(commit))
1079                return 0;
1080        parents = commit->parents;
1081        for (; parents; parents = parents->next) {
1082                if (!memcmp(sha1, parents->item->object.sha1, 20)) {
1083                        return 1;
1084                } else if (parents->item->object.type == commit_type) {
1085                        if (is_ancestor(
1086                                    sha1,
1087                                    (struct commit *)&parents->item->object
1088                                    ))
1089                                return 1;
1090                }
1091        }
1092        return 0;
1093}
1094
1095static void get_delta(unsigned char *sha1, struct object *obj,
1096                      struct active_lock *lock)
1097{
1098        struct commit *commit;
1099        struct commit_list *parents;
1100        struct tree *tree;
1101        struct tree_entry_list *entry;
1102
1103        if (sha1 && !memcmp(sha1, obj->sha1, 20))
1104                return;
1105
1106        if (aborted)
1107                return;
1108
1109        if (obj->type == commit_type) {
1110                if (push_verbosely)
1111                        fprintf(stderr, "walk %s\n", sha1_to_hex(obj->sha1));
1112                add_request(obj->sha1, lock);
1113                commit = (struct commit *)obj;
1114                if (parse_commit(commit)) {
1115                        fprintf(stderr, "Error parsing commit %s\n",
1116                                sha1_to_hex(obj->sha1));
1117                        aborted = 1;
1118                        return;
1119                }
1120                parents = commit->parents;
1121                for (; parents; parents = parents->next)
1122                        if (sha1 == NULL ||
1123                            memcmp(sha1, parents->item->object.sha1, 20))
1124                                get_delta(sha1, &parents->item->object,
1125                                          lock);
1126                get_delta(sha1, &commit->tree->object, lock);
1127        } else if (obj->type == tree_type) {
1128                if (push_verbosely)
1129                        fprintf(stderr, "walk %s\n", sha1_to_hex(obj->sha1));
1130                add_request(obj->sha1, lock);
1131                tree = (struct tree *)obj;
1132                if (parse_tree(tree)) {
1133                        fprintf(stderr, "Error parsing tree %s\n",
1134                                sha1_to_hex(obj->sha1));
1135                        aborted = 1;
1136                        return;
1137                }
1138                entry = tree->entries;
1139                tree->entries = NULL;
1140                while (entry) {
1141                        struct tree_entry_list *next = entry->next;
1142                        get_delta(sha1, entry->item.any, lock);
1143                        free(entry->name);
1144                        free(entry);
1145                        entry = next;
1146                }
1147        } else if (obj->type == blob_type || obj->type == tag_type) {
1148                add_request(obj->sha1, lock);
1149        }
1150}
1151
1152static int update_remote(unsigned char *sha1, struct active_lock *lock)
1153{
1154        struct active_request_slot *slot;
1155        char *out_data;
1156        char *if_header;
1157        struct buffer out_buffer;
1158        struct curl_slist *dav_headers = NULL;
1159        int i;
1160
1161        if_header = xmalloc(strlen(lock->token) + 25);
1162        sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
1163        dav_headers = curl_slist_append(dav_headers, if_header);
1164
1165        out_buffer.size = 41;
1166        out_data = xmalloc(out_buffer.size + 1);
1167        i = snprintf(out_data, out_buffer.size + 1, "%s\n", sha1_to_hex(sha1));
1168        if (i != out_buffer.size) {
1169                fprintf(stderr, "Unable to initialize PUT request body\n");
1170                return 0;
1171        }
1172        out_buffer.posn = 0;
1173        out_buffer.buffer = out_data;
1174
1175        slot = get_active_slot();
1176        curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1177        curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1178        curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1179        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
1180        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
1181        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1182        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1183        curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
1184        curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
1185
1186        if (start_active_slot(slot)) {
1187                run_active_slot(slot);
1188                free(out_data);
1189                free(if_header);
1190                if (slot->curl_result != CURLE_OK) {
1191                        fprintf(stderr,
1192                                "PUT error: curl result=%d, HTTP code=%ld\n",
1193                                slot->curl_result, slot->http_code);
1194                        /* We should attempt recovery? */
1195                        return 0;
1196                }
1197        } else {
1198                free(out_data);
1199                free(if_header);
1200                fprintf(stderr, "Unable to start PUT request\n");
1201                return 0;
1202        }
1203
1204        return 1;
1205}
1206
1207int main(int argc, char **argv)
1208{
1209        struct transfer_request *request;
1210        struct transfer_request *next_request;
1211        int nr_refspec = 0;
1212        char **refspec = NULL;
1213        int do_remote_update;
1214        int new_branch;
1215        int force_this;
1216        char *local_ref;
1217        unsigned char local_sha1[20];
1218        struct object *local_object = NULL;
1219        char *remote_ref = NULL;
1220        unsigned char remote_sha1[20];
1221        struct active_lock *remote_lock;
1222        char *remote_path = NULL;
1223        int rc = 0;
1224        int i;
1225
1226        setup_ident();
1227
1228        remote = xmalloc(sizeof(*remote));
1229        remote->url = NULL;
1230        remote->packs = NULL;
1231
1232        argv++;
1233        for (i = 1; i < argc; i++, argv++) {
1234                char *arg = *argv;
1235
1236                if (*arg == '-') {
1237                        if (!strcmp(arg, "--complete")) {
1238                                push_all = 1;
1239                                continue;
1240                        }
1241                        if (!strcmp(arg, "--force")) {
1242                                force_all = 1;
1243                                continue;
1244                        }
1245                        if (!strcmp(arg, "--verbose")) {
1246                                push_verbosely = 1;
1247                                continue;
1248                        }
1249                        usage(http_push_usage);
1250                }
1251                if (!remote->url) {
1252                        remote->url = arg;
1253                        continue;
1254                }
1255                refspec = argv;
1256                nr_refspec = argc - i;
1257                break;
1258        }
1259
1260        memset(remote_dir_exists, 0, 256);
1261
1262        http_init();
1263
1264        no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
1265        default_headers = curl_slist_append(default_headers, "Range:");
1266        default_headers = curl_slist_append(default_headers, "Destination:");
1267        default_headers = curl_slist_append(default_headers, "If:");
1268        default_headers = curl_slist_append(default_headers,
1269                                            "Pragma: no-cache");
1270
1271        /* Verify DAV compliance/lock support */
1272        if (check_locking() != 0) {
1273                fprintf(stderr, "Error: no DAV locking support on remote repo %s\n", remote->url);
1274                rc = 1;
1275                goto cleanup;
1276        }
1277
1278        /* Process each refspec */
1279        for (i = 0; i < nr_refspec; i++) {
1280                char *ep;
1281                force_this = 0;
1282                do_remote_update = 0;
1283                new_branch = 0;
1284                local_ref = refspec[i];
1285                if (*local_ref == '+') {
1286                        force_this = 1;
1287                        local_ref++;
1288                }
1289                ep = strchr(local_ref, ':');
1290                if (ep) {
1291                        remote_ref = ep + 1;
1292                        *ep = 0;
1293                }
1294                else
1295                        remote_ref = local_ref;
1296
1297                /* Lock remote branch ref */
1298                if (remote_path)
1299                        free(remote_path);
1300                remote_path = xmalloc(strlen(remote_ref) + 12);
1301                sprintf(remote_path, "refs/heads/%s", remote_ref);
1302                remote_lock = lock_remote(remote_path, LOCK_TIME);
1303                if (remote_lock == NULL) {
1304                        fprintf(stderr, "Unable to lock remote branch %s\n",
1305                                remote_ref);
1306                        rc = 1;
1307                        continue;
1308                }
1309
1310                /* Resolve local and remote refs */
1311                if (fetch_ref(remote_ref, remote_sha1) != 0) {
1312                        fprintf(stderr,
1313                                "Remote branch %s does not exist on %s\n",
1314                                remote_ref, remote->url);
1315                        new_branch = 1;
1316                }
1317                if (get_sha1(local_ref, local_sha1) != 0) {
1318                        fprintf(stderr, "Error resolving local branch %s\n",
1319                                local_ref);
1320                        rc = 1;
1321                        goto unlock;
1322                }
1323        
1324                /* Find relationship between local and remote */
1325                local_object = parse_object(local_sha1);
1326                if (!local_object) {
1327                        fprintf(stderr, "Unable to parse local object %s\n",
1328                                sha1_to_hex(local_sha1));
1329                        rc = 1;
1330                        goto unlock;
1331                } else if (new_branch) {
1332                        do_remote_update = 1;
1333                } else {
1334                        if (!memcmp(local_sha1, remote_sha1, 20)) {
1335                                fprintf(stderr,
1336                                        "* %s: same as branch '%s' of %s\n",
1337                                        local_ref, remote_ref, remote->url);
1338                        } else if (is_ancestor(remote_sha1,
1339                                               (struct commit *)local_object)) {
1340                                fprintf(stderr,
1341                                        "Remote %s will fast-forward to local %s\n",
1342                                        remote_ref, local_ref);
1343                                do_remote_update = 1;
1344                        } else if (force_all || force_this) {
1345                                fprintf(stderr,
1346                                        "* %s on %s does not fast forward to local branch '%s', overwriting\n",
1347                                        remote_ref, remote->url, local_ref);
1348                                do_remote_update = 1;
1349                        } else {
1350                                fprintf(stderr,
1351                                        "* %s on %s does not fast forward to local branch '%s'\n",
1352                                        remote_ref, remote->url, local_ref);
1353                                rc = 1;
1354                                goto unlock;
1355                        }
1356                }
1357
1358                /* Generate and check list of required objects */
1359                pushing = 0;
1360                if (do_remote_update || push_all)
1361                        fetch_indices();
1362                get_delta(push_all ? NULL : remote_sha1,
1363                          local_object, remote_lock);
1364                finish_all_active_slots();
1365
1366                /* Push missing objects to remote, this would be a
1367                   convenient time to pack them first if appropriate. */
1368                pushing = 1;
1369                fill_active_slots();
1370                finish_all_active_slots();
1371
1372                /* Update the remote branch if all went well */
1373                if (do_remote_update) {
1374                        if (!aborted && update_remote(local_sha1,
1375                                                      remote_lock)) {
1376                                fprintf(stderr, "%s remote branch %s\n",
1377                                        new_branch ? "Created" : "Updated",
1378                                        remote_ref);
1379                        } else {
1380                                fprintf(stderr,
1381                                        "Unable to %s remote branch %s\n",
1382                                        new_branch ? "create" : "update",
1383                                        remote_ref);
1384                                rc = 1;
1385                                goto unlock;
1386                        }
1387                }
1388
1389        unlock:
1390                unlock_remote(remote_lock);
1391                free(remote_path);
1392        }
1393
1394 cleanup:
1395        free(remote);
1396
1397        curl_slist_free_all(no_pragma_header);
1398        curl_slist_free_all(default_headers);
1399
1400        http_cleanup();
1401
1402        request = request_queue_head;
1403        while (request != NULL) {
1404                next_request = request->next;
1405                release_request(request);
1406                request = next_request;
1407        }
1408
1409        return rc;
1410}
1411#else /* ifdef USE_CURL_MULTI */
1412int main(int argc, char **argv)
1413{
1414        fprintf(stderr, "http-push requires curl 7.9.8 or higher.\n");
1415        return 1;
1416}
1417#endif