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