Isolate shared HTTP request functionality
[git.git] / http-push.c
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
13 static const char http_push_usage[] =
14 "git-http-push [--complete] [--force] [--verbose] <url> <ref> [<ref>...]\n";
15
16 #ifndef XML_STATUS_OK
17 enum 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
40 static int pushing = 0;
41 static int aborted = 0;
42 static char remote_dir_exists[256];
43
44 static struct curl_slist *no_pragma_header;
45 static struct curl_slist *default_headers;
46
47 static int push_verbosely = 0;
48 static int push_all = 0;
49 static int force_all = 0;
50
51 struct repo
52 {
53         char *url;
54         struct packed_git *packs;
55 };
56
57 static struct repo *remote = NULL;
58
59 enum 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
70 struct 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
93 static struct transfer_request *request_queue_head = NULL;
94
95 struct 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
111 struct 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
121 static void finish_request(struct transfer_request *request);
122
123 static 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
131 static 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
163 static 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
196 static 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
279 static 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
304 static 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
344 static 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
417 static 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
434 void 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
466 static 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
493 static 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
579 static 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
592 static 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
660 static 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
671 static inline int hex(int v)
672 {
673         if (v < 10) return '0' + v;
674         else return 'A' + v - 10;
675 }
676
677 static 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
705 int 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
737 static void
738 start_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
756 static void
757 end_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
776 static void
777 activelock_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
799 static void
800 start_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
825 static void
826 end_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
840 static 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
968 static 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
1009 static 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
1074 static 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
1095 static 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
1152 static 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
1207 int 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 */
1412 int 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