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