HTTP slot reuse fixes
[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 #include "refs.h"
9 #include "revision.h"
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 #define DAV_PROPFIND_RESP ".multistatus.response"
48 #define DAV_PROPFIND_NAME ".multistatus.response.href"
49 #define DAV_PROPFIND_COLLECTION ".multistatus.response.propstat.prop.resourcetype.collection"
50
51 /* DAV request body templates */
52 #define PROPFIND_SUPPORTEDLOCK_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:prop xmlns:R=\"%s\">\n<D:supportedlock/>\n</D:prop>\n</D:propfind>"
53 #define PROPFIND_ALL_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:allprop/>\n</D:propfind>"
54 #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>"
55
56 #define LOCK_TIME 600
57 #define LOCK_REFRESH 30
58
59 /* bits #0-4 in revision.h */
60
61 #define LOCAL   (1u << 5)
62 #define REMOTE  (1u << 6)
63 #define PUSHING (1u << 7)
64
65 static int pushing = 0;
66 static int aborted = 0;
67 static char remote_dir_exists[256];
68
69 static struct curl_slist *no_pragma_header;
70 static struct curl_slist *default_headers;
71
72 static int push_verbosely = 0;
73 static int push_all = 0;
74 static int force_all = 0;
75
76 static struct object_list *objects = NULL;
77
78 struct repo
79 {
80         char *url;
81         int path_len;
82         struct packed_git *packs;
83 };
84
85 static struct repo *remote = NULL;
86 static struct remote_lock *remote_locks = NULL;
87
88 enum transfer_state {
89         NEED_PUSH,
90         RUN_MKCOL,
91         RUN_PUT,
92         RUN_MOVE,
93         ABORTED,
94         COMPLETE,
95 };
96
97 struct transfer_request
98 {
99         struct object *obj;
100         char *url;
101         char *dest;
102         struct remote_lock *lock;
103         struct curl_slist *headers;
104         struct buffer buffer;
105         char filename[PATH_MAX];
106         char tmpfile[PATH_MAX];
107         enum transfer_state state;
108         CURLcode curl_result;
109         char errorstr[CURL_ERROR_SIZE];
110         long http_code;
111         unsigned char real_sha1[20];
112         SHA_CTX c;
113         z_stream stream;
114         int zret;
115         int rename;
116         struct active_request_slot *slot;
117         struct transfer_request *next;
118 };
119
120 static struct transfer_request *request_queue_head = NULL;
121
122 struct xml_ctx
123 {
124         char *name;
125         int len;
126         char *cdata;
127         void (*userFunc)(struct xml_ctx *ctx, int tag_closed);
128         void *userData;
129 };
130
131 struct remote_lock
132 {
133         char *url;
134         char *owner;
135         char *token;
136         time_t start_time;
137         long timeout;
138         int active;
139         int refreshing;
140         struct remote_lock *next;
141 };
142
143 struct remote_dentry
144 {
145         char *base;
146         char *name;
147         int is_dir;
148 };
149
150 static void finish_request(struct transfer_request *request);
151
152 static void process_response(void *callback_data)
153 {
154         struct transfer_request *request =
155                 (struct transfer_request *)callback_data;
156
157         finish_request(request);
158 }
159
160 static void start_mkcol(struct transfer_request *request)
161 {
162         char *hex = sha1_to_hex(request->obj->sha1);
163         struct active_request_slot *slot;
164         char *posn;
165
166         request->url = xmalloc(strlen(remote->url) + 13);
167         strcpy(request->url, remote->url);
168         posn = request->url + strlen(remote->url);
169         strcpy(posn, "objects/");
170         posn += 8;
171         memcpy(posn, hex, 2);
172         posn += 2;
173         strcpy(posn, "/");
174
175         slot = get_active_slot();
176         slot->callback_func = process_response;
177         slot->callback_data = request;
178         curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); /* undo PUT setup */
179         curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
180         curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
181         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MKCOL);
182         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
183
184         if (start_active_slot(slot)) {
185                 request->slot = slot;
186                 request->state = RUN_MKCOL;
187         } else {
188                 request->state = ABORTED;
189                 free(request->url);
190                 request->url = NULL;
191         }
192 }
193
194 static void start_put(struct transfer_request *request)
195 {
196         char *hex = sha1_to_hex(request->obj->sha1);
197         struct active_request_slot *slot;
198         char *posn;
199         char type[20];
200         char hdr[50];
201         void *unpacked;
202         unsigned long len;
203         int hdrlen;
204         ssize_t size;
205         z_stream stream;
206
207         unpacked = read_sha1_file(request->obj->sha1, type, &len);
208         hdrlen = sprintf(hdr, "%s %lu", type, len) + 1;
209
210         /* Set it up */
211         memset(&stream, 0, sizeof(stream));
212         deflateInit(&stream, Z_BEST_COMPRESSION);
213         size = deflateBound(&stream, len + hdrlen);
214         request->buffer.buffer = xmalloc(size);
215
216         /* Compress it */
217         stream.next_out = request->buffer.buffer;
218         stream.avail_out = size;
219
220         /* First header.. */
221         stream.next_in = (void *)hdr;
222         stream.avail_in = hdrlen;
223         while (deflate(&stream, 0) == Z_OK)
224                 /* nothing */;
225
226         /* Then the data itself.. */
227         stream.next_in = unpacked;
228         stream.avail_in = len;
229         while (deflate(&stream, Z_FINISH) == Z_OK)
230                 /* nothing */;
231         deflateEnd(&stream);
232         free(unpacked);
233
234         request->buffer.size = stream.total_out;
235         request->buffer.posn = 0;
236
237         request->url = xmalloc(strlen(remote->url) + 
238                                strlen(request->lock->token) + 51);
239         strcpy(request->url, remote->url);
240         posn = request->url + strlen(remote->url);
241         strcpy(posn, "objects/");
242         posn += 8;
243         memcpy(posn, hex, 2);
244         posn += 2;
245         *(posn++) = '/';
246         strcpy(posn, hex + 2);
247         request->dest = xmalloc(strlen(request->url) + 14);
248         sprintf(request->dest, "Destination: %s", request->url);
249         posn += 38;
250         *(posn++) = '.';
251         strcpy(posn, request->lock->token);
252
253         slot = get_active_slot();
254         slot->callback_func = process_response;
255         slot->callback_data = request;
256         curl_easy_setopt(slot->curl, CURLOPT_INFILE, &request->buffer);
257         curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, request->buffer.size);
258         curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
259         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
260         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
261         curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
262         curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
263         curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
264         curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
265
266         if (start_active_slot(slot)) {
267                 request->slot = slot;
268                 request->state = RUN_PUT;
269         } else {
270                 request->state = ABORTED;
271                 free(request->url);
272                 request->url = NULL;
273         }
274 }
275
276 static void start_move(struct transfer_request *request)
277 {
278         struct active_request_slot *slot;
279         struct curl_slist *dav_headers = NULL;
280
281         slot = get_active_slot();
282         slot->callback_func = process_response;
283         slot->callback_data = request;
284         curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); /* undo PUT setup */
285         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MOVE);
286         dav_headers = curl_slist_append(dav_headers, request->dest);
287         dav_headers = curl_slist_append(dav_headers, "Overwrite: T");
288         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
289         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
290         curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
291
292         if (start_active_slot(slot)) {
293                 request->slot = slot;
294                 request->state = RUN_MOVE;
295         } else {
296                 request->state = ABORTED;
297                 free(request->url);
298                 request->url = NULL;
299         }
300 }
301
302 static int refresh_lock(struct remote_lock *check_lock)
303 {
304         struct active_request_slot *slot;
305         struct slot_results results;
306         char *if_header;
307         char timeout_header[25];
308         struct curl_slist *dav_headers = NULL;
309         struct remote_lock *lock;
310         int time_remaining;
311         time_t current_time;
312
313         /* Refresh all active locks if they're close to expiring */
314         for (lock = remote_locks; lock; lock = lock->next) {
315                 if (!lock->active)
316                         continue;
317
318                 current_time = time(NULL);
319                 time_remaining = lock->start_time + lock->timeout
320                         - current_time;
321                 if (time_remaining > LOCK_REFRESH)
322                         continue;
323
324                 lock->refreshing = 1;
325
326                 if_header = xmalloc(strlen(lock->token) + 25);
327                 sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
328                 sprintf(timeout_header, "Timeout: Second-%ld", lock->timeout);
329                 dav_headers = curl_slist_append(dav_headers, if_header);
330                 dav_headers = curl_slist_append(dav_headers, timeout_header);
331
332                 slot = get_active_slot();
333                 slot->results = &results;
334                 curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
335                 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
336                 curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
337                 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
338                 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
339
340                 if (start_active_slot(slot)) {
341                         run_active_slot(slot);
342                         if (results.curl_result != CURLE_OK) {
343                                 fprintf(stderr, "Got HTTP error %ld\n", results.http_code);
344                                 lock->active = 0;
345                         } else {
346                                 lock->active = 1;
347                                 lock->start_time = time(NULL);
348                         }
349                 }
350
351                 lock->refreshing = 0;
352                 curl_slist_free_all(dav_headers);
353                 free(if_header);
354         }
355
356         if (check_lock)
357                 return check_lock->active;
358         else
359                 return 0;
360 }
361
362 static void release_request(struct transfer_request *request)
363 {
364         struct transfer_request *entry = request_queue_head;
365
366         if (request == request_queue_head) {
367                 request_queue_head = request->next;
368         } else {
369                 while (entry->next != NULL && entry->next != request)
370                         entry = entry->next;
371                 if (entry->next == request)
372                         entry->next = entry->next->next;
373         }
374
375         if (request->url != NULL)
376                 free(request->url);
377         free(request);
378 }
379
380 static void finish_request(struct transfer_request *request)
381 {
382         request->curl_result =  request->slot->curl_result;
383         request->http_code = request->slot->http_code;
384         request->slot = NULL;
385
386         /* Keep locks active */
387         refresh_lock(request->lock);
388
389         if (request->headers != NULL)
390                 curl_slist_free_all(request->headers);
391
392         /* URL is reused for MOVE after PUT */
393         if (request->state != RUN_PUT) {
394                 free(request->url);
395                 request->url = NULL;
396         }
397
398         if (request->state == RUN_MKCOL) {
399                 if (request->curl_result == CURLE_OK ||
400                     request->http_code == 405) {
401                         remote_dir_exists[request->obj->sha1[0]] = 1;
402                         start_put(request);
403                 } else {
404                         fprintf(stderr, "MKCOL %s failed, aborting (%d/%ld)\n",
405                                 sha1_to_hex(request->obj->sha1),
406                                 request->curl_result, request->http_code);
407                         request->state = ABORTED;
408                         aborted = 1;
409                 }
410         } else if (request->state == RUN_PUT) {
411                 if (request->curl_result == CURLE_OK) {
412                         start_move(request);
413                 } else {
414                         fprintf(stderr, "PUT %s failed, aborting (%d/%ld)\n",
415                                 sha1_to_hex(request->obj->sha1),
416                                 request->curl_result, request->http_code);
417                         request->state = ABORTED;
418                         aborted = 1;
419                 }
420         } else if (request->state == RUN_MOVE) {
421                 if (request->curl_result == CURLE_OK) {
422                         fprintf(stderr, "    sent %s\n",
423                                 sha1_to_hex(request->obj->sha1));
424                         request->state = COMPLETE;
425                         request->obj->flags |= REMOTE;
426                         release_request(request);
427                 } else {
428                         fprintf(stderr, "MOVE %s failed, aborting (%d/%ld)\n",
429                                 sha1_to_hex(request->obj->sha1),
430                                 request->curl_result, request->http_code);
431                         request->state = ABORTED;
432                         aborted = 1;
433                 }
434         }
435 }
436
437 void fill_active_slots(void)
438 {
439         struct transfer_request *request = request_queue_head;
440         struct active_request_slot *slot = active_queue_head;
441         int num_transfers;
442
443         if (aborted)
444                 return;
445
446         while (active_requests < max_requests && request != NULL) {
447                 if (pushing && request->state == NEED_PUSH) {
448                         if (remote_dir_exists[request->obj->sha1[0]] == 1) {
449                                 start_put(request);
450                         } else {
451                                 start_mkcol(request);
452                         }
453                         curl_multi_perform(curlm, &num_transfers);
454                 }
455                 request = request->next;
456         }
457
458         while (slot != NULL) {
459                 if (!slot->in_use && slot->curl != NULL) {
460                         curl_easy_cleanup(slot->curl);
461                         slot->curl = NULL;
462                 }
463                 slot = slot->next;
464         }
465 }
466
467 static void get_remote_object_list(unsigned char parent);
468
469 static void add_request(struct object *obj, struct remote_lock *lock)
470 {
471         struct transfer_request *request = request_queue_head;
472         struct packed_git *target;
473
474         /*
475          * Don't push the object if it's known to exist on the remote
476          * or is already in the request queue
477          */
478         if (remote_dir_exists[obj->sha1[0]] == -1)
479                 get_remote_object_list(obj->sha1[0]);
480         if (obj->flags & (REMOTE | PUSHING))
481                 return;
482         target = find_sha1_pack(obj->sha1, remote->packs);
483         if (target) {
484                 obj->flags |= REMOTE;
485                 return;
486         }
487
488         obj->flags |= PUSHING;
489         request = xmalloc(sizeof(*request));
490         request->obj = obj;
491         request->url = NULL;
492         request->lock = lock;
493         request->headers = NULL;
494         request->state = NEED_PUSH;
495         request->next = request_queue_head;
496         request_queue_head = request;
497
498         fill_active_slots();
499         step_active_slots();
500 }
501
502 static int fetch_index(unsigned char *sha1)
503 {
504         char *hex = sha1_to_hex(sha1);
505         char *filename;
506         char *url;
507         char tmpfile[PATH_MAX];
508         long prev_posn = 0;
509         char range[RANGE_HEADER_SIZE];
510         struct curl_slist *range_header = NULL;
511
512         FILE *indexfile;
513         struct active_request_slot *slot;
514         struct slot_results results;
515
516         /* Don't use the index if the pack isn't there */
517         url = xmalloc(strlen(remote->url) + 65);
518         sprintf(url, "%s/objects/pack/pack-%s.pack", remote->url, hex);
519         slot = get_active_slot();
520         slot->results = &results;
521         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
522         curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
523         if (start_active_slot(slot)) {
524                 run_active_slot(slot);
525                 if (results.curl_result != CURLE_OK) {
526                         free(url);
527                         return error("Unable to verify pack %s is available",
528                                      hex);
529                 }
530         } else {
531                 return error("Unable to start request");
532         }
533
534         if (has_pack_index(sha1))
535                 return 0;
536
537         if (push_verbosely)
538                 fprintf(stderr, "Getting index for pack %s\n", hex);
539         
540         sprintf(url, "%s/objects/pack/pack-%s.idx", remote->url, hex);
541         
542         filename = sha1_pack_index_name(sha1);
543         snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
544         indexfile = fopen(tmpfile, "a");
545         if (!indexfile)
546                 return error("Unable to open local file %s for pack index",
547                              filename);
548
549         slot = get_active_slot();
550         slot->results = &results;
551         curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
552         curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
553         curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
554         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
555         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
556         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
557         slot->local = indexfile;
558
559         /* If there is data present from a previous transfer attempt,
560            resume where it left off */
561         prev_posn = ftell(indexfile);
562         if (prev_posn>0) {
563                 if (push_verbosely)
564                         fprintf(stderr,
565                                 "Resuming fetch of index for pack %s at byte %ld\n",
566                                 hex, prev_posn);
567                 sprintf(range, "Range: bytes=%ld-", prev_posn);
568                 range_header = curl_slist_append(range_header, range);
569                 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
570         }
571
572         if (start_active_slot(slot)) {
573                 run_active_slot(slot);
574                 if (results.curl_result != CURLE_OK) {
575                         free(url);
576                         fclose(indexfile);
577                         return error("Unable to get pack index %s\n%s", url,
578                                      curl_errorstr);
579                 }
580         } else {
581                 free(url);
582                 fclose(indexfile);
583                 return error("Unable to start request");
584         }
585
586         free(url);
587         fclose(indexfile);
588
589         return move_temp_to_file(tmpfile, filename);
590 }
591
592 static int setup_index(unsigned char *sha1)
593 {
594         struct packed_git *new_pack;
595
596         if (fetch_index(sha1))
597                 return -1;
598
599         new_pack = parse_pack_index(sha1);
600         new_pack->next = remote->packs;
601         remote->packs = new_pack;
602         return 0;
603 }
604
605 static int fetch_indices(void)
606 {
607         unsigned char sha1[20];
608         char *url;
609         struct buffer buffer;
610         char *data;
611         int i = 0;
612
613         struct active_request_slot *slot;
614         struct slot_results results;
615
616         data = xmalloc(4096);
617         memset(data, 0, 4096);
618         buffer.size = 4096;
619         buffer.posn = 0;
620         buffer.buffer = data;
621
622         if (push_verbosely)
623                 fprintf(stderr, "Getting pack list\n");
624         
625         url = xmalloc(strlen(remote->url) + 21);
626         sprintf(url, "%s/objects/info/packs", remote->url);
627
628         slot = get_active_slot();
629         slot->results = &results;
630         curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
631         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
632         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
633         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
634         if (start_active_slot(slot)) {
635                 run_active_slot(slot);
636                 if (results.curl_result != CURLE_OK) {
637                         free(buffer.buffer);
638                         free(url);
639                         if (results.http_code == 404)
640                                 return 0;
641                         else
642                                 return error("%s", curl_errorstr);
643                 }
644         } else {
645                 free(buffer.buffer);
646                 free(url);
647                 return error("Unable to start request");
648         }
649         free(url);
650
651         data = buffer.buffer;
652         while (i < buffer.posn) {
653                 switch (data[i]) {
654                 case 'P':
655                         i++;
656                         if (i + 52 < buffer.posn &&
657                             !strncmp(data + i, " pack-", 6) &&
658                             !strncmp(data + i + 46, ".pack\n", 6)) {
659                                 get_sha1_hex(data + i + 6, sha1);
660                                 setup_index(sha1);
661                                 i += 51;
662                                 break;
663                         }
664                 default:
665                         while (data[i] != '\n')
666                                 i++;
667                 }
668                 i++;
669         }
670
671         free(buffer.buffer);
672         return 0;
673 }
674
675 static inline int needs_quote(int ch)
676 {
677         switch (ch) {
678         case '/': case '-': case '.':
679         case 'A'...'Z': case 'a'...'z': case '0'...'9':
680                 return 0;
681         default:
682                 return 1;
683         }
684 }
685
686 static inline int hex(int v)
687 {
688         if (v < 10) return '0' + v;
689         else return 'A' + v - 10;
690 }
691
692 static char *quote_ref_url(const char *base, const char *ref)
693 {
694         const char *cp;
695         char *dp, *qref;
696         int len, baselen, ch;
697
698         baselen = strlen(base);
699         len = baselen + 1;
700         for (cp = ref; (ch = *cp) != 0; cp++, len++)
701                 if (needs_quote(ch))
702                         len += 2; /* extra two hex plus replacement % */
703         qref = xmalloc(len);
704         memcpy(qref, base, baselen);
705         for (cp = ref, dp = qref + baselen; (ch = *cp) != 0; cp++) {
706                 if (needs_quote(ch)) {
707                         *dp++ = '%';
708                         *dp++ = hex((ch >> 4) & 0xF);
709                         *dp++ = hex(ch & 0xF);
710                 }
711                 else
712                         *dp++ = ch;
713         }
714         *dp = 0;
715
716         return qref;
717 }
718
719 int fetch_ref(char *ref, unsigned char *sha1)
720 {
721         char *url;
722         char hex[42];
723         struct buffer buffer;
724         char *base = remote->url;
725         struct active_request_slot *slot;
726         struct slot_results results;
727         buffer.size = 41;
728         buffer.posn = 0;
729         buffer.buffer = hex;
730         hex[41] = '\0';
731
732         url = quote_ref_url(base, ref);
733         slot = get_active_slot();
734         slot->results = &results;
735         curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
736         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
737         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
738         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
739         if (start_active_slot(slot)) {
740                 run_active_slot(slot);
741                 if (results.curl_result != CURLE_OK)
742                         return error("Couldn't get %s for %s\n%s",
743                                      url, ref, curl_errorstr);
744         } else {
745                 return error("Unable to start request");
746         }
747
748         hex[40] = '\0';
749         get_sha1_hex(hex, sha1);
750         return 0;
751 }
752
753 static void one_remote_object(const char *hex)
754 {
755         unsigned char sha1[20];
756         struct object *obj;
757
758         if (get_sha1_hex(hex, sha1) != 0)
759                 return;
760
761         obj = lookup_object(sha1);
762         if (!obj)
763                 obj = parse_object(sha1);
764
765         /* Ignore remote objects that don't exist locally */
766         if (!obj)
767                 return;
768
769         obj->flags |= REMOTE;
770         if (!object_list_contains(objects, obj))
771                 add_object(obj, &objects, NULL, "");
772 }
773
774 static void handle_lockprop_ctx(struct xml_ctx *ctx, int tag_closed)
775 {
776         int *lock_flags = (int *)ctx->userData;
777
778         if (tag_closed) {
779                 if (!strcmp(ctx->name, DAV_CTX_LOCKENTRY)) {
780                         if ((*lock_flags & DAV_PROP_LOCKEX) &&
781                             (*lock_flags & DAV_PROP_LOCKWR)) {
782                                 *lock_flags |= DAV_LOCK_OK;
783                         }
784                         *lock_flags &= DAV_LOCK_OK;
785                 } else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_WRITE)) {
786                         *lock_flags |= DAV_PROP_LOCKWR;
787                 } else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_EXCLUSIVE)) {
788                         *lock_flags |= DAV_PROP_LOCKEX;
789                 }
790         }
791 }
792
793 static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
794 {
795         struct remote_lock *lock = (struct remote_lock *)ctx->userData;
796
797         if (tag_closed && ctx->cdata) {
798                 if (!strcmp(ctx->name, DAV_ACTIVELOCK_OWNER)) {
799                         lock->owner = xmalloc(strlen(ctx->cdata) + 1);
800                         strcpy(lock->owner, ctx->cdata);
801                 } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TIMEOUT)) {
802                         if (!strncmp(ctx->cdata, "Second-", 7))
803                                 lock->timeout =
804                                         strtol(ctx->cdata + 7, NULL, 10);
805                 } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
806                         if (!strncmp(ctx->cdata, "opaquelocktoken:", 16)) {
807                                 lock->token = xmalloc(strlen(ctx->cdata) - 15);
808                                 strcpy(lock->token, ctx->cdata + 16);
809                         }
810                 }
811         }
812 }
813
814 static void one_remote_ref(char *refname);
815 static void crawl_remote_refs(char *path);
816
817 static void handle_crawl_ref_ctx(struct xml_ctx *ctx, int tag_closed)
818 {
819         struct remote_dentry *dentry = (struct remote_dentry *)ctx->userData;
820
821
822         if (tag_closed) {
823                 if (!strcmp(ctx->name, DAV_PROPFIND_RESP) && dentry->name) {
824                         if (dentry->is_dir) {
825                                 if (strcmp(dentry->name, dentry->base)) {
826                                         crawl_remote_refs(dentry->name);
827                                 }
828                         } else {
829                                 one_remote_ref(dentry->name);
830                         }
831                 } else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
832                         dentry->name = xmalloc(strlen(ctx->cdata) -
833                                                remote->path_len + 1);
834                         strcpy(dentry->name,
835                                ctx->cdata + remote->path_len);
836                 } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
837                         dentry->is_dir = 1;
838                 }
839         } else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
840                 dentry->name = NULL;
841                 dentry->is_dir = 0;
842         }
843 }
844
845 static void handle_remote_object_list_ctx(struct xml_ctx *ctx, int tag_closed)
846 {
847         char *path;
848         char *obj_hex;
849
850         if (tag_closed) {
851                 if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
852                         path = ctx->cdata + remote->path_len;
853                         if (strlen(path) != 50)
854                                 return;
855                         path += 9;
856                         obj_hex = xmalloc(strlen(path));
857                         strncpy(obj_hex, path, 2);
858                         strcpy(obj_hex + 2, path + 3);
859                         one_remote_object(obj_hex);
860                         free(obj_hex);
861                 }
862         }
863 }
864
865 static void
866 xml_start_tag(void *userData, const char *name, const char **atts)
867 {
868         struct xml_ctx *ctx = (struct xml_ctx *)userData;
869         const char *c = index(name, ':');
870         int new_len;
871
872         if (c == NULL)
873                 c = name;
874         else
875                 c++;
876
877         new_len = strlen(ctx->name) + strlen(c) + 2;
878
879         if (new_len > ctx->len) {
880                 ctx->name = xrealloc(ctx->name, new_len);
881                 ctx->len = new_len;
882         }
883         strcat(ctx->name, ".");
884         strcat(ctx->name, c);
885
886         if (ctx->cdata) {
887                 free(ctx->cdata);
888                 ctx->cdata = NULL;
889         }
890
891         ctx->userFunc(ctx, 0);
892 }
893
894 static void
895 xml_end_tag(void *userData, const char *name)
896 {
897         struct xml_ctx *ctx = (struct xml_ctx *)userData;
898         const char *c = index(name, ':');
899         char *ep;
900
901         ctx->userFunc(ctx, 1);
902
903         if (c == NULL)
904                 c = name;
905         else
906                 c++;
907
908         ep = ctx->name + strlen(ctx->name) - strlen(c) - 1;
909         *ep = 0;
910 }
911
912 static void
913 xml_cdata(void *userData, const XML_Char *s, int len)
914 {
915         struct xml_ctx *ctx = (struct xml_ctx *)userData;
916         if (ctx->cdata)
917                 free(ctx->cdata);
918         ctx->cdata = xcalloc(len+1, 1);
919         strncpy(ctx->cdata, s, len);
920 }
921
922 static struct remote_lock *lock_remote(char *path, long timeout)
923 {
924         struct active_request_slot *slot;
925         struct slot_results results;
926         struct buffer out_buffer;
927         struct buffer in_buffer;
928         char *out_data;
929         char *in_data;
930         char *url;
931         char *ep;
932         char timeout_header[25];
933         struct remote_lock *lock = remote_locks;
934         XML_Parser parser = XML_ParserCreate(NULL);
935         enum XML_Status result;
936         struct curl_slist *dav_headers = NULL;
937         struct xml_ctx ctx;
938
939         url = xmalloc(strlen(remote->url) + strlen(path) + 1);
940         sprintf(url, "%s%s", remote->url, path);
941
942         /* Make sure the url is not already locked */
943         while (lock && strcmp(lock->url, url)) {
944                 lock = lock->next;
945         }
946         if (lock) {
947                 free(url);
948                 if (refresh_lock(lock))
949                         return lock;
950                 else
951                         return NULL;
952         }
953
954         /* Make sure leading directories exist for the remote ref */
955         ep = strchr(url + strlen(remote->url) + 11, '/');
956         while (ep) {
957                 *ep = 0;
958                 slot = get_active_slot();
959                 slot->results = &results;
960                 curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
961                 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
962                 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MKCOL);
963                 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
964                 if (start_active_slot(slot)) {
965                         run_active_slot(slot);
966                         if (results.curl_result != CURLE_OK &&
967                             results.http_code != 405) {
968                                 fprintf(stderr,
969                                         "Unable to create branch path %s\n",
970                                         url);
971                                 free(url);
972                                 return NULL;
973                         }
974                 } else {
975                         fprintf(stderr, "Unable to start request\n");
976                         free(url);
977                         return NULL;
978                 }
979                 *ep = '/';
980                 ep = strchr(ep + 1, '/');
981         }
982
983         out_buffer.size = strlen(LOCK_REQUEST) + strlen(git_default_email) - 2;
984         out_data = xmalloc(out_buffer.size + 1);
985         snprintf(out_data, out_buffer.size + 1, LOCK_REQUEST, git_default_email);
986         out_buffer.posn = 0;
987         out_buffer.buffer = out_data;
988
989         in_buffer.size = 4096;
990         in_data = xmalloc(in_buffer.size);
991         in_buffer.posn = 0;
992         in_buffer.buffer = in_data;
993
994         sprintf(timeout_header, "Timeout: Second-%ld", timeout);
995         dav_headers = curl_slist_append(dav_headers, timeout_header);
996         dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
997
998         slot = get_active_slot();
999         slot->results = &results;
1000         curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1001         curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1002         curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1003         curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1004         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1005         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1006         curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1007         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
1008         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1009
1010         lock = xcalloc(1, sizeof(*lock));
1011         lock->owner = NULL;
1012         lock->token = NULL;
1013         lock->timeout = -1;
1014         lock->refreshing = 0;
1015
1016         if (start_active_slot(slot)) {
1017                 run_active_slot(slot);
1018                 if (results.curl_result == CURLE_OK) {
1019                         ctx.name = xcalloc(10, 1);
1020                         ctx.len = 0;
1021                         ctx.cdata = NULL;
1022                         ctx.userFunc = handle_new_lock_ctx;
1023                         ctx.userData = lock;
1024                         XML_SetUserData(parser, &ctx);
1025                         XML_SetElementHandler(parser, xml_start_tag,
1026                                               xml_end_tag);
1027                         XML_SetCharacterDataHandler(parser, xml_cdata);
1028                         result = XML_Parse(parser, in_buffer.buffer,
1029                                            in_buffer.posn, 1);
1030                         free(ctx.name);
1031                         if (result != XML_STATUS_OK) {
1032                                 fprintf(stderr, "XML error: %s\n",
1033                                         XML_ErrorString(
1034                                                 XML_GetErrorCode(parser)));
1035                                 lock->timeout = -1;
1036                         }
1037                 }
1038         } else {
1039                 fprintf(stderr, "Unable to start request\n");
1040         }
1041
1042         curl_slist_free_all(dav_headers);
1043         free(out_data);
1044         free(in_data);
1045
1046         if (lock->token == NULL || lock->timeout <= 0) {
1047                 if (lock->token != NULL)
1048                         free(lock->token);
1049                 if (lock->owner != NULL)
1050                         free(lock->owner);
1051                 free(url);
1052                 free(lock);
1053                 lock = NULL;
1054         } else {
1055                 lock->url = url;
1056                 lock->active = 1;
1057                 lock->start_time = time(NULL);
1058                 lock->next = remote_locks;
1059                 remote_locks = lock;
1060         }
1061
1062         return lock;
1063 }
1064
1065 static int unlock_remote(struct remote_lock *lock)
1066 {
1067         struct active_request_slot *slot;
1068         struct slot_results results;
1069         char *lock_token_header;
1070         struct curl_slist *dav_headers = NULL;
1071         int rc = 0;
1072
1073         lock_token_header = xmalloc(strlen(lock->token) + 31);
1074         sprintf(lock_token_header, "Lock-Token: <opaquelocktoken:%s>",
1075                 lock->token);
1076         dav_headers = curl_slist_append(dav_headers, lock_token_header);
1077
1078         slot = get_active_slot();
1079         slot->results = &results;
1080         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
1081         curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
1082         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_UNLOCK);
1083         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1084
1085         if (start_active_slot(slot)) {
1086                 run_active_slot(slot);
1087                 if (results.curl_result == CURLE_OK)
1088                         rc = 1;
1089                 else
1090                         fprintf(stderr, "Got HTTP error %ld\n",
1091                                 results.http_code);
1092         } else {
1093                 fprintf(stderr, "Unable to start request\n");
1094         }
1095
1096         curl_slist_free_all(dav_headers);
1097         free(lock_token_header);
1098
1099         lock->active = 0;
1100
1101         return rc;
1102 }
1103
1104 static void crawl_remote_refs(char *path)
1105 {
1106         char *url;
1107         struct active_request_slot *slot;
1108         struct slot_results results;
1109         struct buffer in_buffer;
1110         struct buffer out_buffer;
1111         char *in_data;
1112         char *out_data;
1113         XML_Parser parser = XML_ParserCreate(NULL);
1114         enum XML_Status result;
1115         struct curl_slist *dav_headers = NULL;
1116         struct xml_ctx ctx;
1117         struct remote_dentry dentry;
1118
1119         fprintf(stderr, "  %s\n", path);
1120
1121         dentry.base = path;
1122         dentry.name = NULL;
1123         dentry.is_dir = 0;
1124
1125         url = xmalloc(strlen(remote->url) + strlen(path) + 1);
1126         sprintf(url, "%s%s", remote->url, path);
1127
1128         out_buffer.size = strlen(PROPFIND_ALL_REQUEST);
1129         out_data = xmalloc(out_buffer.size + 1);
1130         snprintf(out_data, out_buffer.size + 1, PROPFIND_ALL_REQUEST);
1131         out_buffer.posn = 0;
1132         out_buffer.buffer = out_data;
1133
1134         in_buffer.size = 4096;
1135         in_data = xmalloc(in_buffer.size);
1136         in_buffer.posn = 0;
1137         in_buffer.buffer = in_data;
1138
1139         dav_headers = curl_slist_append(dav_headers, "Depth: 1");
1140         dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1141
1142         slot = get_active_slot();
1143         slot->results = &results;
1144         curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1145         curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1146         curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1147         curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1148         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1149         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1150         curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1151         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
1152         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1153
1154         if (start_active_slot(slot)) {
1155                 run_active_slot(slot);
1156                 if (results.curl_result == CURLE_OK) {
1157                         ctx.name = xcalloc(10, 1);
1158                         ctx.len = 0;
1159                         ctx.cdata = NULL;
1160                         ctx.userFunc = handle_crawl_ref_ctx;
1161                         ctx.userData = &dentry;
1162                         XML_SetUserData(parser, &ctx);
1163                         XML_SetElementHandler(parser, xml_start_tag,
1164                                               xml_end_tag);
1165                         XML_SetCharacterDataHandler(parser, xml_cdata);
1166                         result = XML_Parse(parser, in_buffer.buffer,
1167                                            in_buffer.posn, 1);
1168                         free(ctx.name);
1169
1170                         if (result != XML_STATUS_OK) {
1171                                 fprintf(stderr, "XML error: %s\n",
1172                                         XML_ErrorString(
1173                                                 XML_GetErrorCode(parser)));
1174                         }
1175                 }
1176         } else {
1177                 fprintf(stderr, "Unable to start request\n");
1178         }
1179
1180         free(url);
1181         free(out_data);
1182         free(in_buffer.buffer);
1183         curl_slist_free_all(dav_headers);
1184 }
1185
1186 static void get_remote_object_list(unsigned char parent)
1187 {
1188         char *url;
1189         struct active_request_slot *slot;
1190         struct slot_results results;
1191         struct buffer in_buffer;
1192         struct buffer out_buffer;
1193         char *in_data;
1194         char *out_data;
1195         XML_Parser parser = XML_ParserCreate(NULL);
1196         enum XML_Status result;
1197         struct curl_slist *dav_headers = NULL;
1198         struct xml_ctx ctx;
1199         char path[] = "/objects/XX/";
1200         static const char hex[] = "0123456789abcdef";
1201         unsigned int val = parent;
1202
1203         path[9] = hex[val >> 4];
1204         path[10] = hex[val & 0xf];
1205         url = xmalloc(strlen(remote->url) + strlen(path) + 1);
1206         sprintf(url, "%s%s", remote->url, path);
1207
1208         out_buffer.size = strlen(PROPFIND_ALL_REQUEST);
1209         out_data = xmalloc(out_buffer.size + 1);
1210         snprintf(out_data, out_buffer.size + 1, PROPFIND_ALL_REQUEST);
1211         out_buffer.posn = 0;
1212         out_buffer.buffer = out_data;
1213
1214         in_buffer.size = 4096;
1215         in_data = xmalloc(in_buffer.size);
1216         in_buffer.posn = 0;
1217         in_buffer.buffer = in_data;
1218
1219         dav_headers = curl_slist_append(dav_headers, "Depth: 1");
1220         dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1221
1222         slot = get_active_slot();
1223         slot->results = &results;
1224         curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1225         curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1226         curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1227         curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1228         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1229         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1230         curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1231         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
1232         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1233
1234         if (start_active_slot(slot)) {
1235                 run_active_slot(slot);
1236                 if (results.curl_result == CURLE_OK) {
1237                         remote_dir_exists[parent] = 1;
1238                         ctx.name = xcalloc(10, 1);
1239                         ctx.len = 0;
1240                         ctx.cdata = NULL;
1241                         ctx.userFunc = handle_remote_object_list_ctx;
1242                         XML_SetUserData(parser, &ctx);
1243                         XML_SetElementHandler(parser, xml_start_tag,
1244                                               xml_end_tag);
1245                         XML_SetCharacterDataHandler(parser, xml_cdata);
1246                         result = XML_Parse(parser, in_buffer.buffer,
1247                                            in_buffer.posn, 1);
1248                         free(ctx.name);
1249
1250                         if (result != XML_STATUS_OK) {
1251                                 fprintf(stderr, "XML error: %s\n",
1252                                         XML_ErrorString(
1253                                                 XML_GetErrorCode(parser)));
1254                         }
1255                 } else {
1256                         remote_dir_exists[parent] = 0;
1257                 }
1258         } else {
1259                 fprintf(stderr, "Unable to start request\n");
1260         }
1261
1262         free(url);
1263         free(out_data);
1264         free(in_buffer.buffer);
1265         curl_slist_free_all(dav_headers);
1266 }
1267
1268 static int locking_available(void)
1269 {
1270         struct active_request_slot *slot;
1271         struct slot_results results;
1272         struct buffer in_buffer;
1273         struct buffer out_buffer;
1274         char *in_data;
1275         char *out_data;
1276         XML_Parser parser = XML_ParserCreate(NULL);
1277         enum XML_Status result;
1278         struct curl_slist *dav_headers = NULL;
1279         struct xml_ctx ctx;
1280         int lock_flags = 0;
1281
1282         out_buffer.size =
1283                 strlen(PROPFIND_SUPPORTEDLOCK_REQUEST) +
1284                 strlen(remote->url) - 2;
1285         out_data = xmalloc(out_buffer.size + 1);
1286         snprintf(out_data, out_buffer.size + 1,
1287                  PROPFIND_SUPPORTEDLOCK_REQUEST, remote->url);
1288         out_buffer.posn = 0;
1289         out_buffer.buffer = out_data;
1290
1291         in_buffer.size = 4096;
1292         in_data = xmalloc(in_buffer.size);
1293         in_buffer.posn = 0;
1294         in_buffer.buffer = in_data;
1295
1296         dav_headers = curl_slist_append(dav_headers, "Depth: 0");
1297         dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1298
1299         slot = get_active_slot();
1300         slot->results = &results;
1301         curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1302         curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1303         curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1304         curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1305         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1306         curl_easy_setopt(slot->curl, CURLOPT_URL, remote->url);
1307         curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1308         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
1309         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1310
1311         if (start_active_slot(slot)) {
1312                 run_active_slot(slot);
1313                 if (results.curl_result == CURLE_OK) {
1314                         ctx.name = xcalloc(10, 1);
1315                         ctx.len = 0;
1316                         ctx.cdata = NULL;
1317                         ctx.userFunc = handle_lockprop_ctx;
1318                         ctx.userData = &lock_flags;
1319                         XML_SetUserData(parser, &ctx);
1320                         XML_SetElementHandler(parser, xml_start_tag,
1321                                               xml_end_tag);
1322                         result = XML_Parse(parser, in_buffer.buffer,
1323                                            in_buffer.posn, 1);
1324                         free(ctx.name);
1325
1326                         if (result != XML_STATUS_OK) {
1327                                 fprintf(stderr, "XML error: %s\n",
1328                                         XML_ErrorString(
1329                                                 XML_GetErrorCode(parser)));
1330                                 lock_flags = 0;
1331                         }
1332                 }
1333         } else {
1334                 fprintf(stderr, "Unable to start request\n");
1335         }
1336
1337         free(out_data);
1338         free(in_buffer.buffer);
1339         curl_slist_free_all(dav_headers);
1340
1341         return lock_flags;
1342 }
1343
1344 static struct object_list **process_blob(struct blob *blob,
1345                                          struct object_list **p,
1346                                          struct name_path *path,
1347                                          const char *name)
1348 {
1349         struct object *obj = &blob->object;
1350
1351         obj->flags |= LOCAL;
1352
1353         if (obj->flags & (UNINTERESTING | SEEN))
1354                 return p;
1355
1356         obj->flags |= SEEN;
1357         return add_object(obj, p, path, name);
1358 }
1359
1360 static struct object_list **process_tree(struct tree *tree,
1361                                          struct object_list **p,
1362                                          struct name_path *path,
1363                                          const char *name)
1364 {
1365         struct object *obj = &tree->object;
1366         struct tree_entry_list *entry;
1367         struct name_path me;
1368
1369         obj->flags |= LOCAL;
1370
1371         if (obj->flags & (UNINTERESTING | SEEN))
1372                 return p;
1373         if (parse_tree(tree) < 0)
1374                 die("bad tree object %s", sha1_to_hex(obj->sha1));
1375
1376         obj->flags |= SEEN;
1377         p = add_object(obj, p, NULL, name);
1378         me.up = path;
1379         me.elem = name;
1380         me.elem_len = strlen(name);
1381         entry = tree->entries;
1382         tree->entries = NULL;
1383         while (entry) {
1384                 struct tree_entry_list *next = entry->next;
1385                 if (entry->directory)
1386                         p = process_tree(entry->item.tree, p, &me, entry->name);
1387                 else
1388                         p = process_blob(entry->item.blob, p, &me, entry->name);
1389                 free(entry);
1390                 entry = next;
1391         }
1392         return p;
1393 }
1394
1395 static void get_delta(struct rev_info *revs, struct remote_lock *lock)
1396 {
1397         struct commit *commit;
1398         struct object_list **p = &objects, *pending;
1399
1400         while ((commit = get_revision(revs)) != NULL) {
1401                 p = process_tree(commit->tree, p, NULL, "");
1402                 commit->object.flags |= LOCAL;
1403                 if (!(commit->object.flags & UNINTERESTING))
1404                         add_request(&commit->object, lock);
1405         }
1406
1407         for (pending = revs->pending_objects; pending; pending = pending->next) {
1408                 struct object *obj = pending->item;
1409                 const char *name = pending->name;
1410
1411                 if (obj->flags & (UNINTERESTING | SEEN))
1412                         continue;
1413                 if (obj->type == tag_type) {
1414                         obj->flags |= SEEN;
1415                         p = add_object(obj, p, NULL, name);
1416                         continue;
1417                 }
1418                 if (obj->type == tree_type) {
1419                         p = process_tree((struct tree *)obj, p, NULL, name);
1420                         continue;
1421                 }
1422                 if (obj->type == blob_type) {
1423                         p = process_blob((struct blob *)obj, p, NULL, name);
1424                         continue;
1425                 }
1426                 die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
1427         }
1428
1429         while (objects) {
1430                 if (!(objects->item->flags & UNINTERESTING))
1431                         add_request(objects->item, lock);
1432                 objects = objects->next;
1433         }
1434 }
1435
1436 static int update_remote(unsigned char *sha1, struct remote_lock *lock)
1437 {
1438         struct active_request_slot *slot;
1439         struct slot_results results;
1440         char *out_data;
1441         char *if_header;
1442         struct buffer out_buffer;
1443         struct curl_slist *dav_headers = NULL;
1444         int i;
1445
1446         if_header = xmalloc(strlen(lock->token) + 25);
1447         sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
1448         dav_headers = curl_slist_append(dav_headers, if_header);
1449
1450         out_buffer.size = 41;
1451         out_data = xmalloc(out_buffer.size + 1);
1452         i = snprintf(out_data, out_buffer.size + 1, "%s\n", sha1_to_hex(sha1));
1453         if (i != out_buffer.size) {
1454                 fprintf(stderr, "Unable to initialize PUT request body\n");
1455                 return 0;
1456         }
1457         out_buffer.posn = 0;
1458         out_buffer.buffer = out_data;
1459
1460         slot = get_active_slot();
1461         slot->results = &results;
1462         curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1463         curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1464         curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1465         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
1466         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
1467         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1468         curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1469         curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
1470         curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
1471
1472         if (start_active_slot(slot)) {
1473                 run_active_slot(slot);
1474                 free(out_data);
1475                 free(if_header);
1476                 if (results.curl_result != CURLE_OK) {
1477                         fprintf(stderr,
1478                                 "PUT error: curl result=%d, HTTP code=%ld\n",
1479                                 results.curl_result, results.http_code);
1480                         /* We should attempt recovery? */
1481                         return 0;
1482                 }
1483         } else {
1484                 free(out_data);
1485                 free(if_header);
1486                 fprintf(stderr, "Unable to start PUT request\n");
1487                 return 0;
1488         }
1489
1490         return 1;
1491 }
1492
1493 static struct ref *local_refs, **local_tail;
1494 static struct ref *remote_refs, **remote_tail;
1495
1496 static int one_local_ref(const char *refname, const unsigned char *sha1)
1497 {
1498         struct ref *ref;
1499         int len = strlen(refname) + 1;
1500         ref = xcalloc(1, sizeof(*ref) + len);
1501         memcpy(ref->new_sha1, sha1, 20);
1502         memcpy(ref->name, refname, len);
1503         *local_tail = ref;
1504         local_tail = &ref->next;
1505         return 0;
1506 }
1507
1508 static void one_remote_ref(char *refname)
1509 {
1510         struct ref *ref;
1511         unsigned char remote_sha1[20];
1512
1513         if (fetch_ref(refname, remote_sha1) != 0) {
1514                 fprintf(stderr,
1515                         "Unable to fetch ref %s from %s\n",
1516                         refname, remote->url);
1517                 return;
1518         }
1519
1520         int len = strlen(refname) + 1;
1521         ref = xcalloc(1, sizeof(*ref) + len);
1522         memcpy(ref->old_sha1, remote_sha1, 20);
1523         memcpy(ref->name, refname, len);
1524         *remote_tail = ref;
1525         remote_tail = &ref->next;
1526 }
1527
1528 static void get_local_heads(void)
1529 {
1530         local_tail = &local_refs;
1531         for_each_ref(one_local_ref);
1532 }
1533
1534 static void get_dav_remote_heads(void)
1535 {
1536         remote_tail = &remote_refs;
1537         crawl_remote_refs("refs/");
1538 }
1539
1540 static int is_zero_sha1(const unsigned char *sha1)
1541 {
1542         int i;
1543
1544         for (i = 0; i < 20; i++) {
1545                 if (*sha1++)
1546                         return 0;
1547         }
1548         return 1;
1549 }
1550
1551 static void unmark_and_free(struct commit_list *list, unsigned int mark)
1552 {
1553         while (list) {
1554                 struct commit_list *temp = list;
1555                 temp->item->object.flags &= ~mark;
1556                 list = temp->next;
1557                 free(temp);
1558         }
1559 }
1560
1561 static int ref_newer(const unsigned char *new_sha1,
1562                      const unsigned char *old_sha1)
1563 {
1564         struct object *o;
1565         struct commit *old, *new;
1566         struct commit_list *list, *used;
1567         int found = 0;
1568
1569         /* Both new and old must be commit-ish and new is descendant of
1570          * old.  Otherwise we require --force.
1571          */
1572         o = deref_tag(parse_object(old_sha1), NULL, 0);
1573         if (!o || o->type != commit_type)
1574                 return 0;
1575         old = (struct commit *) o;
1576
1577         o = deref_tag(parse_object(new_sha1), NULL, 0);
1578         if (!o || o->type != commit_type)
1579                 return 0;
1580         new = (struct commit *) o;
1581
1582         if (parse_commit(new) < 0)
1583                 return 0;
1584
1585         used = list = NULL;
1586         commit_list_insert(new, &list);
1587         while (list) {
1588                 new = pop_most_recent_commit(&list, TMP_MARK);
1589                 commit_list_insert(new, &used);
1590                 if (new == old) {
1591                         found = 1;
1592                         break;
1593                 }
1594         }
1595         unmark_and_free(list, TMP_MARK);
1596         unmark_and_free(used, TMP_MARK);
1597         return found;
1598 }
1599
1600 static void mark_edge_parents_uninteresting(struct commit *commit)
1601 {
1602         struct commit_list *parents;
1603
1604         for (parents = commit->parents; parents; parents = parents->next) {
1605                 struct commit *parent = parents->item;
1606                 if (!(parent->object.flags & UNINTERESTING))
1607                         continue;
1608                 mark_tree_uninteresting(parent->tree);
1609         }
1610 }
1611
1612 static void mark_edges_uninteresting(struct commit_list *list)
1613 {
1614         for ( ; list; list = list->next) {
1615                 struct commit *commit = list->item;
1616
1617                 if (commit->object.flags & UNINTERESTING) {
1618                         mark_tree_uninteresting(commit->tree);
1619                         continue;
1620                 }
1621                 mark_edge_parents_uninteresting(commit);
1622         }
1623 }
1624
1625 int main(int argc, char **argv)
1626 {
1627         struct transfer_request *request;
1628         struct transfer_request *next_request;
1629         int nr_refspec = 0;
1630         char **refspec = NULL;
1631         struct remote_lock *ref_lock;
1632         struct rev_info revs;
1633         int rc = 0;
1634         int i;
1635
1636         setup_git_directory();
1637         setup_ident();
1638
1639         remote = xmalloc(sizeof(*remote));
1640         remote->url = NULL;
1641         remote->path_len = 0;
1642         remote->packs = NULL;
1643
1644         argv++;
1645         for (i = 1; i < argc; i++, argv++) {
1646                 char *arg = *argv;
1647
1648                 if (*arg == '-') {
1649                         if (!strcmp(arg, "--all")) {
1650                                 push_all = 1;
1651                                 continue;
1652                         }
1653                         if (!strcmp(arg, "--force")) {
1654                                 force_all = 1;
1655                                 continue;
1656                         }
1657                         if (!strcmp(arg, "--verbose")) {
1658                                 push_verbosely = 1;
1659                                 continue;
1660                         }
1661                         usage(http_push_usage);
1662                 }
1663                 if (!remote->url) {
1664                         remote->url = arg;
1665                         char *path = strstr(arg, "//");
1666                         if (path) {
1667                                 path = index(path+2, '/');
1668                                 if (path)
1669                                         remote->path_len = strlen(path);
1670                         }
1671                         continue;
1672                 }
1673                 refspec = argv;
1674                 nr_refspec = argc - i;
1675                 break;
1676         }
1677
1678         if (!remote->url)
1679                 usage(http_push_usage);
1680
1681         memset(remote_dir_exists, -1, 256);
1682
1683         http_init();
1684
1685         no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
1686         default_headers = curl_slist_append(default_headers, "Range:");
1687         default_headers = curl_slist_append(default_headers, "Destination:");
1688         default_headers = curl_slist_append(default_headers, "If:");
1689         default_headers = curl_slist_append(default_headers,
1690                                             "Pragma: no-cache");
1691
1692         /* Verify DAV compliance/lock support */
1693         if (!locking_available()) {
1694                 fprintf(stderr, "Error: no DAV locking support on remote repo %s\n", remote->url);
1695                 rc = 1;
1696                 goto cleanup;
1697         }
1698
1699         /* Get a list of all local and remote heads to validate refspecs */
1700         get_local_heads();
1701         fprintf(stderr, "Fetching remote heads...\n");
1702         get_dav_remote_heads();
1703
1704         /* match them up */
1705         if (!remote_tail)
1706                 remote_tail = &remote_refs;
1707         if (match_refs(local_refs, remote_refs, &remote_tail,
1708                        nr_refspec, refspec, push_all))
1709                 return -1;
1710         if (!remote_refs) {
1711                 fprintf(stderr, "No refs in common and none specified; doing nothing.\n");
1712                 return 0;
1713         }
1714
1715         int ret = 0;
1716         int new_refs = 0;
1717         struct ref *ref;
1718         for (ref = remote_refs; ref; ref = ref->next) {
1719                 char old_hex[60], *new_hex;
1720                 if (!ref->peer_ref)
1721                         continue;
1722                 if (!memcmp(ref->old_sha1, ref->peer_ref->new_sha1, 20)) {
1723                         if (push_verbosely || 1)
1724                                 fprintf(stderr, "'%s': up-to-date\n", ref->name);
1725                         continue;
1726                 }
1727
1728                 if (!force_all &&
1729                     !is_zero_sha1(ref->old_sha1) &&
1730                     !ref->force) {
1731                         if (!has_sha1_file(ref->old_sha1) ||
1732                             !ref_newer(ref->peer_ref->new_sha1,
1733                                        ref->old_sha1)) {
1734                                 /* We do not have the remote ref, or
1735                                  * we know that the remote ref is not
1736                                  * an ancestor of what we are trying to
1737                                  * push.  Either way this can be losing
1738                                  * commits at the remote end and likely
1739                                  * we were not up to date to begin with.
1740                                  */
1741                                 error("remote '%s' is not a strict "
1742                                       "subset of local ref '%s'. "
1743                                       "maybe you are not up-to-date and "
1744                                       "need to pull first?",
1745                                       ref->name,
1746                                       ref->peer_ref->name);
1747                                 ret = -2;
1748                                 continue;
1749                         }
1750                 }
1751                 memcpy(ref->new_sha1, ref->peer_ref->new_sha1, 20);
1752                 if (is_zero_sha1(ref->new_sha1)) {
1753                         error("cannot happen anymore");
1754                         ret = -3;
1755                         continue;
1756                 }
1757                 new_refs++;
1758                 strcpy(old_hex, sha1_to_hex(ref->old_sha1));
1759                 new_hex = sha1_to_hex(ref->new_sha1);
1760
1761                 fprintf(stderr, "updating '%s'", ref->name);
1762                 if (strcmp(ref->name, ref->peer_ref->name))
1763                         fprintf(stderr, " using '%s'", ref->peer_ref->name);
1764                 fprintf(stderr, "\n  from %s\n  to   %s\n", old_hex, new_hex);
1765
1766
1767                 /* Lock remote branch ref */
1768                 ref_lock = lock_remote(ref->name, LOCK_TIME);
1769                 if (ref_lock == NULL) {
1770                         fprintf(stderr, "Unable to lock remote branch %s\n",
1771                                 ref->name);
1772                         rc = 1;
1773                         continue;
1774                 }
1775
1776                 /* Set up revision info for this refspec */
1777                 const char *commit_argv[4];
1778                 int commit_argc = 3;
1779                 char *new_sha1_hex = strdup(sha1_to_hex(ref->new_sha1));
1780                 char *old_sha1_hex = NULL;
1781                 commit_argv[1] = "--objects";
1782                 commit_argv[2] = new_sha1_hex;
1783                 if (!push_all && !is_zero_sha1(ref->old_sha1)) {
1784                         old_sha1_hex = xmalloc(42);
1785                         sprintf(old_sha1_hex, "^%s",
1786                                 sha1_to_hex(ref->old_sha1));
1787                         commit_argv[3] = old_sha1_hex;
1788                         commit_argc++;
1789                 }
1790                 setup_revisions(commit_argc, commit_argv, &revs, NULL);
1791                 free(new_sha1_hex);
1792                 if (old_sha1_hex) {
1793                         free(old_sha1_hex);
1794                         commit_argv[1] = NULL;
1795                 }
1796
1797                 /* Generate a list of objects that need to be pushed */
1798                 pushing = 0;
1799                 prepare_revision_walk(&revs);
1800                 mark_edges_uninteresting(revs.commits);
1801                 fetch_indices();
1802                 get_delta(&revs, ref_lock);
1803                 finish_all_active_slots();
1804
1805                 /* Push missing objects to remote, this would be a
1806                    convenient time to pack them first if appropriate. */
1807                 pushing = 1;
1808                 fill_active_slots();
1809                 finish_all_active_slots();
1810
1811                 /* Update the remote branch if all went well */
1812                 if (aborted || !update_remote(ref->new_sha1, ref_lock)) {
1813                         rc = 1;
1814                         goto unlock;
1815                 }
1816
1817         unlock:
1818                 if (!rc)
1819                         fprintf(stderr, "    done\n");
1820                 unlock_remote(ref_lock);
1821         }
1822
1823  cleanup:
1824         free(remote);
1825
1826         curl_slist_free_all(no_pragma_header);
1827         curl_slist_free_all(default_headers);
1828
1829         http_cleanup();
1830
1831         request = request_queue_head;
1832         while (request != NULL) {
1833                 next_request = request->next;
1834                 release_request(request);
1835                 request = next_request;
1836         }
1837
1838         return rc;
1839 }