Merge branch 'jc/diff' into next
[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 [--all] [--force] [--verbose] <remote> [<head>...]\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 PREV_BUF_SIZE 4096
26 #define RANGE_HEADER_SIZE 30
27
28 /* DAV methods */
29 #define DAV_LOCK "LOCK"
30 #define DAV_MKCOL "MKCOL"
31 #define DAV_MOVE "MOVE"
32 #define DAV_PROPFIND "PROPFIND"
33 #define DAV_PUT "PUT"
34 #define DAV_UNLOCK "UNLOCK"
35
36 /* DAV lock flags */
37 #define DAV_PROP_LOCKWR (1u << 0)
38 #define DAV_PROP_LOCKEX (1u << 1)
39 #define DAV_LOCK_OK (1u << 2)
40
41 /* DAV XML properties */
42 #define DAV_CTX_LOCKENTRY ".multistatus.response.propstat.prop.supportedlock.lockentry"
43 #define DAV_CTX_LOCKTYPE_WRITE ".multistatus.response.propstat.prop.supportedlock.lockentry.locktype.write"
44 #define DAV_CTX_LOCKTYPE_EXCLUSIVE ".multistatus.response.propstat.prop.supportedlock.lockentry.lockscope.exclusive"
45 #define DAV_ACTIVELOCK_OWNER ".prop.lockdiscovery.activelock.owner.href"
46 #define DAV_ACTIVELOCK_TIMEOUT ".prop.lockdiscovery.activelock.timeout"
47 #define DAV_ACTIVELOCK_TOKEN ".prop.lockdiscovery.activelock.locktoken.href"
48 #define DAV_PROPFIND_RESP ".multistatus.response"
49 #define DAV_PROPFIND_NAME ".multistatus.response.href"
50 #define DAV_PROPFIND_COLLECTION ".multistatus.response.propstat.prop.resourcetype.collection"
51
52 /* DAV request body templates */
53 #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>"
54 #define PROPFIND_ALL_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:allprop/>\n</D:propfind>"
55 #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>"
56
57 #define LOCK_TIME 600
58 #define LOCK_REFRESH 30
59
60 /* bits #0-4 in revision.h */
61
62 #define LOCAL    (1u << 5)
63 #define REMOTE   (1u << 6)
64 #define FETCHING (1u << 7)
65 #define PUSHING  (1u << 8)
66
67 static int pushing = 0;
68 static int aborted = 0;
69 static char remote_dir_exists[256];
70
71 static struct curl_slist *no_pragma_header;
72 static struct curl_slist *default_headers;
73
74 static int push_verbosely = 0;
75 static int push_all = 0;
76 static int force_all = 0;
77
78 static struct object_list *objects = NULL;
79
80 struct repo
81 {
82         char *url;
83         int path_len;
84         int has_info_refs;
85         int can_update_info_refs;
86         int has_info_packs;
87         struct packed_git *packs;
88         struct remote_lock *locks;
89 };
90
91 static struct repo *remote = NULL;
92
93 enum transfer_state {
94         NEED_FETCH,
95         RUN_FETCH_LOOSE,
96         RUN_FETCH_PACKED,
97         NEED_PUSH,
98         RUN_MKCOL,
99         RUN_PUT,
100         RUN_MOVE,
101         ABORTED,
102         COMPLETE,
103 };
104
105 struct transfer_request
106 {
107         struct object *obj;
108         char *url;
109         char *dest;
110         struct remote_lock *lock;
111         struct curl_slist *headers;
112         struct buffer buffer;
113         char filename[PATH_MAX];
114         char tmpfile[PATH_MAX];
115         int local_fileno;
116         FILE *local_stream;
117         enum transfer_state state;
118         CURLcode curl_result;
119         char errorstr[CURL_ERROR_SIZE];
120         long http_code;
121         unsigned char real_sha1[20];
122         SHA_CTX c;
123         z_stream stream;
124         int zret;
125         int rename;
126         void *userData;
127         struct active_request_slot *slot;
128         struct transfer_request *next;
129 };
130
131 static struct transfer_request *request_queue_head = NULL;
132
133 struct xml_ctx
134 {
135         char *name;
136         int len;
137         char *cdata;
138         void (*userFunc)(struct xml_ctx *ctx, int tag_closed);
139         void *userData;
140 };
141
142 struct remote_lock
143 {
144         char *url;
145         char *owner;
146         char *token;
147         time_t start_time;
148         long timeout;
149         int refreshing;
150         struct remote_lock *next;
151 };
152
153 /* Flags that control remote_ls processing */
154 #define PROCESS_FILES (1u << 0)
155 #define PROCESS_DIRS  (1u << 1)
156 #define RECURSIVE     (1u << 2)
157
158 /* Flags that remote_ls passes to callback functions */
159 #define IS_DIR (1u << 0)
160
161 struct remote_ls_ctx
162 {
163         char *path;
164         void (*userFunc)(struct remote_ls_ctx *ls);
165         void *userData;
166         int flags;
167         char *dentry_name;
168         int dentry_flags;
169         struct remote_ls_ctx *parent;
170 };
171
172 static void finish_request(struct transfer_request *request);
173 static void release_request(struct transfer_request *request);
174
175 static void process_response(void *callback_data)
176 {
177         struct transfer_request *request =
178                 (struct transfer_request *)callback_data;
179
180         finish_request(request);
181 }
182
183 static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
184                                void *data)
185 {
186         unsigned char expn[4096];
187         size_t size = eltsize * nmemb;
188         int posn = 0;
189         struct transfer_request *request = (struct transfer_request *)data;
190         do {
191                 ssize_t retval = write(request->local_fileno,
192                                        ptr + posn, size - posn);
193                 if (retval < 0)
194                         return posn;
195                 posn += retval;
196         } while (posn < size);
197
198         request->stream.avail_in = size;
199         request->stream.next_in = ptr;
200         do {
201                 request->stream.next_out = expn;
202                 request->stream.avail_out = sizeof(expn);
203                 request->zret = inflate(&request->stream, Z_SYNC_FLUSH);
204                 SHA1_Update(&request->c, expn,
205                             sizeof(expn) - request->stream.avail_out);
206         } while (request->stream.avail_in && request->zret == Z_OK);
207         data_received++;
208         return size;
209 }
210
211 static void start_fetch_loose(struct transfer_request *request)
212 {
213         char *hex = sha1_to_hex(request->obj->sha1);
214         char *filename;
215         char prevfile[PATH_MAX];
216         char *url;
217         char *posn;
218         int prevlocal;
219         unsigned char prev_buf[PREV_BUF_SIZE];
220         ssize_t prev_read = 0;
221         long prev_posn = 0;
222         char range[RANGE_HEADER_SIZE];
223         struct curl_slist *range_header = NULL;
224         struct active_request_slot *slot;
225
226         filename = sha1_file_name(request->obj->sha1);
227         snprintf(request->filename, sizeof(request->filename), "%s", filename);
228         snprintf(request->tmpfile, sizeof(request->tmpfile),
229                  "%s.temp", filename);
230
231         snprintf(prevfile, sizeof(prevfile), "%s.prev", request->filename);
232         unlink(prevfile);
233         rename(request->tmpfile, prevfile);
234         unlink(request->tmpfile);
235
236         if (request->local_fileno != -1)
237                 error("fd leakage in start: %d", request->local_fileno);
238         request->local_fileno = open(request->tmpfile,
239                                      O_WRONLY | O_CREAT | O_EXCL, 0666);
240         /* This could have failed due to the "lazy directory creation";
241          * try to mkdir the last path component.
242          */
243         if (request->local_fileno < 0 && errno == ENOENT) {
244                 char *dir = strrchr(request->tmpfile, '/');
245                 if (dir) {
246                         *dir = 0;
247                         mkdir(request->tmpfile, 0777);
248                         *dir = '/';
249                 }
250                 request->local_fileno = open(request->tmpfile,
251                                              O_WRONLY | O_CREAT | O_EXCL, 0666);
252         }
253
254         if (request->local_fileno < 0) {
255                 request->state = ABORTED;
256                 error("Couldn't create temporary file %s for %s: %s",
257                       request->tmpfile, request->filename, strerror(errno));
258                 return;
259         }
260
261         memset(&request->stream, 0, sizeof(request->stream));
262
263         inflateInit(&request->stream);
264
265         SHA1_Init(&request->c);
266
267         url = xmalloc(strlen(remote->url) + 50);
268         request->url = xmalloc(strlen(remote->url) + 50);
269         strcpy(url, remote->url);
270         posn = url + strlen(remote->url);
271         strcpy(posn, "objects/");
272         posn += 8;
273         memcpy(posn, hex, 2);
274         posn += 2;
275         *(posn++) = '/';
276         strcpy(posn, hex + 2);
277         strcpy(request->url, url);
278
279         /* If a previous temp file is present, process what was already
280            fetched. */
281         prevlocal = open(prevfile, O_RDONLY);
282         if (prevlocal != -1) {
283                 do {
284                         prev_read = read(prevlocal, prev_buf, PREV_BUF_SIZE);
285                         if (prev_read>0) {
286                                 if (fwrite_sha1_file(prev_buf,
287                                                      1,
288                                                      prev_read,
289                                                      request) == prev_read) {
290                                         prev_posn += prev_read;
291                                 } else {
292                                         prev_read = -1;
293                                 }
294                         }
295                 } while (prev_read > 0);
296                 close(prevlocal);
297         }
298         unlink(prevfile);
299
300         /* Reset inflate/SHA1 if there was an error reading the previous temp
301            file; also rewind to the beginning of the local file. */
302         if (prev_read == -1) {
303                 memset(&request->stream, 0, sizeof(request->stream));
304                 inflateInit(&request->stream);
305                 SHA1_Init(&request->c);
306                 if (prev_posn>0) {
307                         prev_posn = 0;
308                         lseek(request->local_fileno, SEEK_SET, 0);
309                         ftruncate(request->local_fileno, 0);
310                 }
311         }
312
313         slot = get_active_slot();
314         slot->callback_func = process_response;
315         slot->callback_data = request;
316         request->slot = slot;
317
318         curl_easy_setopt(slot->curl, CURLOPT_FILE, request);
319         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
320         curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
321         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
322         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
323
324         /* If we have successfully processed data from a previous fetch
325            attempt, only fetch the data we don't already have. */
326         if (prev_posn>0) {
327                 if (push_verbosely)
328                         fprintf(stderr,
329                                 "Resuming fetch of object %s at byte %ld\n",
330                                 hex, prev_posn);
331                 sprintf(range, "Range: bytes=%ld-", prev_posn);
332                 range_header = curl_slist_append(range_header, range);
333                 curl_easy_setopt(slot->curl,
334                                  CURLOPT_HTTPHEADER, range_header);
335         }
336
337         /* Try to get the request started, abort the request on error */
338         request->state = RUN_FETCH_LOOSE;
339         if (!start_active_slot(slot)) {
340                 fprintf(stderr, "Unable to start GET request\n");
341                 remote->can_update_info_refs = 0;
342                 release_request(request);
343         }
344 }
345
346 static void start_fetch_packed(struct transfer_request *request)
347 {
348         char *url;
349         struct packed_git *target;
350         FILE *packfile;
351         char *filename;
352         long prev_posn = 0;
353         char range[RANGE_HEADER_SIZE];
354         struct curl_slist *range_header = NULL;
355
356         struct transfer_request *check_request = request_queue_head;
357         struct active_request_slot *slot;
358
359         target = find_sha1_pack(request->obj->sha1, remote->packs);
360         if (!target) {
361                 fprintf(stderr, "Unable to fetch %s, will not be able to update server info refs\n", sha1_to_hex(request->obj->sha1));
362                 remote->can_update_info_refs = 0;
363                 release_request(request);
364                 return;
365         }
366
367         fprintf(stderr, "Fetching pack %s\n", sha1_to_hex(target->sha1));
368         fprintf(stderr, " which contains %s\n", sha1_to_hex(request->obj->sha1));
369
370         filename = sha1_pack_name(target->sha1);
371         snprintf(request->filename, sizeof(request->filename), "%s", filename);
372         snprintf(request->tmpfile, sizeof(request->tmpfile),
373                  "%s.temp", filename);
374
375         url = xmalloc(strlen(remote->url) + 64);
376         sprintf(url, "%sobjects/pack/pack-%s.pack",
377                 remote->url, sha1_to_hex(target->sha1));
378
379         /* Make sure there isn't another open request for this pack */
380         while (check_request) {
381                 if (check_request->state == RUN_FETCH_PACKED &&
382                     !strcmp(check_request->url, url)) {
383                         free(url);
384                         release_request(request);
385                         return;
386                 }
387                 check_request = check_request->next;
388         }
389
390         packfile = fopen(request->tmpfile, "a");
391         if (!packfile) {
392                 fprintf(stderr, "Unable to open local file %s for pack",
393                         filename);
394                 remote->can_update_info_refs = 0;
395                 free(url);
396                 return;
397         }
398
399         slot = get_active_slot();
400         slot->callback_func = process_response;
401         slot->callback_data = request;
402         request->slot = slot;
403         request->local_stream = packfile;
404         request->userData = target;
405
406         request->url = url;
407         curl_easy_setopt(slot->curl, CURLOPT_FILE, packfile);
408         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
409         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
410         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
411         slot->local = packfile;
412
413         /* If there is data present from a previous transfer attempt,
414            resume where it left off */
415         prev_posn = ftell(packfile);
416         if (prev_posn>0) {
417                 if (push_verbosely)
418                         fprintf(stderr,
419                                 "Resuming fetch of pack %s at byte %ld\n",
420                                 sha1_to_hex(target->sha1), prev_posn);
421                 sprintf(range, "Range: bytes=%ld-", prev_posn);
422                 range_header = curl_slist_append(range_header, range);
423                 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
424         }
425
426         /* Try to get the request started, abort the request on error */
427         request->state = RUN_FETCH_PACKED;
428         if (!start_active_slot(slot)) {
429                 fprintf(stderr, "Unable to start GET request\n");
430                 remote->can_update_info_refs = 0;
431                 release_request(request);
432         }
433 }
434
435 static void start_mkcol(struct transfer_request *request)
436 {
437         char *hex = sha1_to_hex(request->obj->sha1);
438         struct active_request_slot *slot;
439         char *posn;
440
441         request->url = xmalloc(strlen(remote->url) + 13);
442         strcpy(request->url, remote->url);
443         posn = request->url + strlen(remote->url);
444         strcpy(posn, "objects/");
445         posn += 8;
446         memcpy(posn, hex, 2);
447         posn += 2;
448         strcpy(posn, "/");
449
450         slot = get_active_slot();
451         slot->callback_func = process_response;
452         slot->callback_data = request;
453         curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); /* undo PUT setup */
454         curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
455         curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
456         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MKCOL);
457         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
458
459         if (start_active_slot(slot)) {
460                 request->slot = slot;
461                 request->state = RUN_MKCOL;
462         } else {
463                 request->state = ABORTED;
464                 free(request->url);
465                 request->url = NULL;
466         }
467 }
468
469 static void start_put(struct transfer_request *request)
470 {
471         char *hex = sha1_to_hex(request->obj->sha1);
472         struct active_request_slot *slot;
473         char *posn;
474         char type[20];
475         char hdr[50];
476         void *unpacked;
477         unsigned long len;
478         int hdrlen;
479         ssize_t size;
480         z_stream stream;
481
482         unpacked = read_sha1_file(request->obj->sha1, type, &len);
483         hdrlen = sprintf(hdr, "%s %lu", type, len) + 1;
484
485         /* Set it up */
486         memset(&stream, 0, sizeof(stream));
487         deflateInit(&stream, Z_BEST_COMPRESSION);
488         size = deflateBound(&stream, len + hdrlen);
489         request->buffer.buffer = xmalloc(size);
490
491         /* Compress it */
492         stream.next_out = request->buffer.buffer;
493         stream.avail_out = size;
494
495         /* First header.. */
496         stream.next_in = (void *)hdr;
497         stream.avail_in = hdrlen;
498         while (deflate(&stream, 0) == Z_OK)
499                 /* nothing */;
500
501         /* Then the data itself.. */
502         stream.next_in = unpacked;
503         stream.avail_in = len;
504         while (deflate(&stream, Z_FINISH) == Z_OK)
505                 /* nothing */;
506         deflateEnd(&stream);
507         free(unpacked);
508
509         request->buffer.size = stream.total_out;
510         request->buffer.posn = 0;
511
512         request->url = xmalloc(strlen(remote->url) + 
513                                strlen(request->lock->token) + 51);
514         strcpy(request->url, remote->url);
515         posn = request->url + strlen(remote->url);
516         strcpy(posn, "objects/");
517         posn += 8;
518         memcpy(posn, hex, 2);
519         posn += 2;
520         *(posn++) = '/';
521         strcpy(posn, hex + 2);
522         request->dest = xmalloc(strlen(request->url) + 14);
523         sprintf(request->dest, "Destination: %s", request->url);
524         posn += 38;
525         *(posn++) = '.';
526         strcpy(posn, request->lock->token);
527
528         slot = get_active_slot();
529         slot->callback_func = process_response;
530         slot->callback_data = request;
531         curl_easy_setopt(slot->curl, CURLOPT_INFILE, &request->buffer);
532         curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, request->buffer.size);
533         curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
534         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
535         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
536         curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
537         curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
538         curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
539         curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
540
541         if (start_active_slot(slot)) {
542                 request->slot = slot;
543                 request->state = RUN_PUT;
544         } else {
545                 request->state = ABORTED;
546                 free(request->url);
547                 request->url = NULL;
548         }
549 }
550
551 static void start_move(struct transfer_request *request)
552 {
553         struct active_request_slot *slot;
554         struct curl_slist *dav_headers = NULL;
555
556         slot = get_active_slot();
557         slot->callback_func = process_response;
558         slot->callback_data = request;
559         curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); /* undo PUT setup */
560         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MOVE);
561         dav_headers = curl_slist_append(dav_headers, request->dest);
562         dav_headers = curl_slist_append(dav_headers, "Overwrite: T");
563         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
564         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
565         curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
566
567         if (start_active_slot(slot)) {
568                 request->slot = slot;
569                 request->state = RUN_MOVE;
570         } else {
571                 request->state = ABORTED;
572                 free(request->url);
573                 request->url = NULL;
574         }
575 }
576
577 static int refresh_lock(struct remote_lock *lock)
578 {
579         struct active_request_slot *slot;
580         struct slot_results results;
581         char *if_header;
582         char timeout_header[25];
583         struct curl_slist *dav_headers = NULL;
584         int rc = 0;
585
586         lock->refreshing = 1;
587
588         if_header = xmalloc(strlen(lock->token) + 25);
589         sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
590         sprintf(timeout_header, "Timeout: Second-%ld", lock->timeout);
591         dav_headers = curl_slist_append(dav_headers, if_header);
592         dav_headers = curl_slist_append(dav_headers, timeout_header);
593
594         slot = get_active_slot();
595         slot->results = &results;
596         curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
597         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
598         curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
599         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
600         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
601
602         if (start_active_slot(slot)) {
603                 run_active_slot(slot);
604                 if (results.curl_result != CURLE_OK) {
605                         fprintf(stderr, "LOCK HTTP error %ld\n",
606                                 results.http_code);
607                 } else {
608                         lock->start_time = time(NULL);
609                         rc = 1;
610                 }
611         }
612
613         lock->refreshing = 0;
614         curl_slist_free_all(dav_headers);
615         free(if_header);
616
617         return rc;
618 }
619
620 static void check_locks()
621 {
622         struct remote_lock *lock = remote->locks;
623         time_t current_time = time(NULL);
624         int time_remaining;
625
626         while (lock) {
627                 time_remaining = lock->start_time + lock->timeout -
628                         current_time;
629                 if (!lock->refreshing && time_remaining < LOCK_REFRESH) {
630                         if (!refresh_lock(lock)) {
631                                 fprintf(stderr,
632                                         "Unable to refresh lock for %s\n",
633                                         lock->url);
634                                 aborted = 1;
635                                 return;
636                         }
637                 }
638                 lock = lock->next;
639         }
640 }
641
642 static void release_request(struct transfer_request *request)
643 {
644         struct transfer_request *entry = request_queue_head;
645
646         if (request == request_queue_head) {
647                 request_queue_head = request->next;
648         } else {
649                 while (entry->next != NULL && entry->next != request)
650                         entry = entry->next;
651                 if (entry->next == request)
652                         entry->next = entry->next->next;
653         }
654
655         if (request->local_fileno != -1)
656                 close(request->local_fileno);
657         if (request->local_stream)
658                 fclose(request->local_stream);
659         if (request->url != NULL)
660                 free(request->url);
661         free(request);
662 }
663
664 static void finish_request(struct transfer_request *request)
665 {
666         struct stat st;
667         struct packed_git *target;
668         struct packed_git **lst;
669
670         request->curl_result = request->slot->curl_result;
671         request->http_code = request->slot->http_code;
672         request->slot = NULL;
673
674         /* Keep locks active */
675         check_locks();
676
677         if (request->headers != NULL)
678                 curl_slist_free_all(request->headers);
679
680         /* URL is reused for MOVE after PUT */
681         if (request->state != RUN_PUT) {
682                 free(request->url);
683                 request->url = NULL;
684         }
685
686         if (request->state == RUN_MKCOL) {
687                 if (request->curl_result == CURLE_OK ||
688                     request->http_code == 405) {
689                         remote_dir_exists[request->obj->sha1[0]] = 1;
690                         start_put(request);
691                 } else {
692                         fprintf(stderr, "MKCOL %s failed, aborting (%d/%ld)\n",
693                                 sha1_to_hex(request->obj->sha1),
694                                 request->curl_result, request->http_code);
695                         request->state = ABORTED;
696                         aborted = 1;
697                 }
698         } else if (request->state == RUN_PUT) {
699                 if (request->curl_result == CURLE_OK) {
700                         start_move(request);
701                 } else {
702                         fprintf(stderr, "PUT %s failed, aborting (%d/%ld)\n",
703                                 sha1_to_hex(request->obj->sha1),
704                                 request->curl_result, request->http_code);
705                         request->state = ABORTED;
706                         aborted = 1;
707                 }
708         } else if (request->state == RUN_MOVE) {
709                 if (request->curl_result == CURLE_OK) {
710                         if (push_verbosely)
711                                 fprintf(stderr, "    sent %s\n",
712                                         sha1_to_hex(request->obj->sha1));
713                         request->obj->flags |= REMOTE;
714                         release_request(request);
715                 } else {
716                         fprintf(stderr, "MOVE %s failed, aborting (%d/%ld)\n",
717                                 sha1_to_hex(request->obj->sha1),
718                                 request->curl_result, request->http_code);
719                         request->state = ABORTED;
720                         aborted = 1;
721                 }
722         } else if (request->state == RUN_FETCH_LOOSE) {
723                 fchmod(request->local_fileno, 0444);
724                 close(request->local_fileno); request->local_fileno = -1;
725
726                 if (request->curl_result != CURLE_OK &&
727                     request->http_code != 416) {
728                         if (stat(request->tmpfile, &st) == 0) {
729                                 if (st.st_size == 0)
730                                         unlink(request->tmpfile);
731                         }
732                 } else {
733                         if (request->http_code == 416)
734                                 fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
735
736                         inflateEnd(&request->stream);
737                         SHA1_Final(request->real_sha1, &request->c);
738                         if (request->zret != Z_STREAM_END) {
739                                 unlink(request->tmpfile);
740                         } else if (memcmp(request->obj->sha1, request->real_sha1, 20)) {
741                                 unlink(request->tmpfile);
742                         } else {
743                                 request->rename =
744                                         move_temp_to_file(
745                                                 request->tmpfile,
746                                                 request->filename);
747                                 if (request->rename == 0) {
748                                         request->obj->flags |= (LOCAL | REMOTE);
749                                 }
750                         }
751                 }
752
753                 /* Try fetching packed if necessary */
754                 if (request->obj->flags & LOCAL)
755                         release_request(request);
756                 else
757                         start_fetch_packed(request);
758
759         } else if (request->state == RUN_FETCH_PACKED) {
760                 if (request->curl_result != CURLE_OK) {
761                         fprintf(stderr, "Unable to get pack file %s\n%s",
762                                 request->url, curl_errorstr);
763                         remote->can_update_info_refs = 0;
764                 } else {
765                         fclose(request->local_stream);
766                         request->local_stream = NULL;
767                         if (!move_temp_to_file(request->tmpfile,
768                                                request->filename)) {
769                                 target = (struct packed_git *)request->userData;
770                                 lst = &remote->packs;
771                                 while (*lst != target)
772                                         lst = &((*lst)->next);
773                                 *lst = (*lst)->next;
774
775                                 if (!verify_pack(target, 0))
776                                         install_packed_git(target);
777                                 else
778                                         remote->can_update_info_refs = 0;
779                         }
780                 }
781                 release_request(request);
782         }
783 }
784
785 void fill_active_slots(void)
786 {
787         struct transfer_request *request = request_queue_head;
788         struct transfer_request *next;
789         struct active_request_slot *slot = active_queue_head;
790         int num_transfers;
791
792         if (aborted)
793                 return;
794
795         while (active_requests < max_requests && request != NULL) {
796                 next = request->next;
797                 if (request->state == NEED_FETCH) {
798                         start_fetch_loose(request);
799                 } else if (pushing && request->state == NEED_PUSH) {
800                         if (remote_dir_exists[request->obj->sha1[0]] == 1) {
801                                 start_put(request);
802                         } else {
803                                 start_mkcol(request);
804                         }
805                         curl_multi_perform(curlm, &num_transfers);
806                 }
807                 request = next;
808         }
809
810         while (slot != NULL) {
811                 if (!slot->in_use && slot->curl != NULL) {
812                         curl_easy_cleanup(slot->curl);
813                         slot->curl = NULL;
814                 }
815                 slot = slot->next;
816         }
817 }
818
819 static void get_remote_object_list(unsigned char parent);
820
821 static void add_fetch_request(struct object *obj)
822 {
823         struct transfer_request *request;
824
825         check_locks();
826
827         /*
828          * Don't fetch the object if it's known to exist locally
829          * or is already in the request queue
830          */
831         if (remote_dir_exists[obj->sha1[0]] == -1)
832                 get_remote_object_list(obj->sha1[0]);
833         if (obj->flags & (LOCAL | FETCHING))
834                 return;
835
836         obj->flags |= FETCHING;
837         request = xmalloc(sizeof(*request));
838         request->obj = obj;
839         request->url = NULL;
840         request->lock = NULL;
841         request->headers = NULL;
842         request->local_fileno = -1;
843         request->local_stream = NULL;
844         request->state = NEED_FETCH;
845         request->next = request_queue_head;
846         request_queue_head = request;
847
848         fill_active_slots();
849         step_active_slots();
850 }
851
852 static int add_send_request(struct object *obj, struct remote_lock *lock)
853 {
854         struct transfer_request *request = request_queue_head;
855         struct packed_git *target;
856
857         /* Keep locks active */
858         check_locks();
859
860         /*
861          * Don't push the object if it's known to exist on the remote
862          * or is already in the request queue
863          */
864         if (remote_dir_exists[obj->sha1[0]] == -1)
865                 get_remote_object_list(obj->sha1[0]);
866         if (obj->flags & (REMOTE | PUSHING))
867                 return 0;
868         target = find_sha1_pack(obj->sha1, remote->packs);
869         if (target) {
870                 obj->flags |= REMOTE;
871                 return 0;
872         }
873
874         obj->flags |= PUSHING;
875         request = xmalloc(sizeof(*request));
876         request->obj = obj;
877         request->url = NULL;
878         request->lock = lock;
879         request->headers = NULL;
880         request->local_fileno = -1;
881         request->local_stream = NULL;
882         request->state = NEED_PUSH;
883         request->next = request_queue_head;
884         request_queue_head = request;
885
886         fill_active_slots();
887         step_active_slots();
888
889         return 1;
890 }
891
892 static int fetch_index(unsigned char *sha1)
893 {
894         char *hex = sha1_to_hex(sha1);
895         char *filename;
896         char *url;
897         char tmpfile[PATH_MAX];
898         long prev_posn = 0;
899         char range[RANGE_HEADER_SIZE];
900         struct curl_slist *range_header = NULL;
901
902         FILE *indexfile;
903         struct active_request_slot *slot;
904         struct slot_results results;
905
906         /* Don't use the index if the pack isn't there */
907         url = xmalloc(strlen(remote->url) + 64);
908         sprintf(url, "%sobjects/pack/pack-%s.pack", remote->url, hex);
909         slot = get_active_slot();
910         slot->results = &results;
911         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
912         curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
913         if (start_active_slot(slot)) {
914                 run_active_slot(slot);
915                 if (results.curl_result != CURLE_OK) {
916                         free(url);
917                         return error("Unable to verify pack %s is available",
918                                      hex);
919                 }
920         } else {
921                 return error("Unable to start request");
922         }
923
924         if (has_pack_index(sha1))
925                 return 0;
926
927         if (push_verbosely)
928                 fprintf(stderr, "Getting index for pack %s\n", hex);
929
930         sprintf(url, "%sobjects/pack/pack-%s.idx", remote->url, hex);
931
932         filename = sha1_pack_index_name(sha1);
933         snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
934         indexfile = fopen(tmpfile, "a");
935         if (!indexfile)
936                 return error("Unable to open local file %s for pack index",
937                              filename);
938
939         slot = get_active_slot();
940         slot->results = &results;
941         curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
942         curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
943         curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
944         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
945         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
946         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
947         slot->local = indexfile;
948
949         /* If there is data present from a previous transfer attempt,
950            resume where it left off */
951         prev_posn = ftell(indexfile);
952         if (prev_posn>0) {
953                 if (push_verbosely)
954                         fprintf(stderr,
955                                 "Resuming fetch of index for pack %s at byte %ld\n",
956                                 hex, prev_posn);
957                 sprintf(range, "Range: bytes=%ld-", prev_posn);
958                 range_header = curl_slist_append(range_header, range);
959                 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
960         }
961
962         if (start_active_slot(slot)) {
963                 run_active_slot(slot);
964                 if (results.curl_result != CURLE_OK) {
965                         free(url);
966                         fclose(indexfile);
967                         return error("Unable to get pack index %s\n%s", url,
968                                      curl_errorstr);
969                 }
970         } else {
971                 free(url);
972                 fclose(indexfile);
973                 return error("Unable to start request");
974         }
975
976         free(url);
977         fclose(indexfile);
978
979         return move_temp_to_file(tmpfile, filename);
980 }
981
982 static int setup_index(unsigned char *sha1)
983 {
984         struct packed_git *new_pack;
985
986         if (fetch_index(sha1))
987                 return -1;
988
989         new_pack = parse_pack_index(sha1);
990         new_pack->next = remote->packs;
991         remote->packs = new_pack;
992         return 0;
993 }
994
995 static int fetch_indices(void)
996 {
997         unsigned char sha1[20];
998         char *url;
999         struct buffer buffer;
1000         char *data;
1001         int i = 0;
1002
1003         struct active_request_slot *slot;
1004         struct slot_results results;
1005
1006         data = xmalloc(4096);
1007         memset(data, 0, 4096);
1008         buffer.size = 4096;
1009         buffer.posn = 0;
1010         buffer.buffer = data;
1011
1012         if (push_verbosely)
1013                 fprintf(stderr, "Getting pack list\n");
1014
1015         url = xmalloc(strlen(remote->url) + 20);
1016         sprintf(url, "%sobjects/info/packs", remote->url);
1017
1018         slot = get_active_slot();
1019         slot->results = &results;
1020         curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
1021         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1022         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1023         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
1024         if (start_active_slot(slot)) {
1025                 run_active_slot(slot);
1026                 if (results.curl_result != CURLE_OK) {
1027                         free(buffer.buffer);
1028                         free(url);
1029                         if (results.http_code == 404)
1030                                 return 0;
1031                         else
1032                                 return error("%s", curl_errorstr);
1033                 }
1034         } else {
1035                 free(buffer.buffer);
1036                 free(url);
1037                 return error("Unable to start request");
1038         }
1039         free(url);
1040
1041         data = buffer.buffer;
1042         while (i < buffer.posn) {
1043                 switch (data[i]) {
1044                 case 'P':
1045                         i++;
1046                         if (i + 52 < buffer.posn &&
1047                             !strncmp(data + i, " pack-", 6) &&
1048                             !strncmp(data + i + 46, ".pack\n", 6)) {
1049                                 get_sha1_hex(data + i + 6, sha1);
1050                                 setup_index(sha1);
1051                                 i += 51;
1052                                 break;
1053                         }
1054                 default:
1055                         while (data[i] != '\n')
1056                                 i++;
1057                 }
1058                 i++;
1059         }
1060
1061         free(buffer.buffer);
1062         return 0;
1063 }
1064
1065 static inline int needs_quote(int ch)
1066 {
1067         switch (ch) {
1068         case '/': case '-': case '.':
1069         case 'A'...'Z': case 'a'...'z': case '0'...'9':
1070                 return 0;
1071         default:
1072                 return 1;
1073         }
1074 }
1075
1076 static inline int hex(int v)
1077 {
1078         if (v < 10) return '0' + v;
1079         else return 'A' + v - 10;
1080 }
1081
1082 static char *quote_ref_url(const char *base, const char *ref)
1083 {
1084         const char *cp;
1085         char *dp, *qref;
1086         int len, baselen, ch;
1087
1088         baselen = strlen(base);
1089         len = baselen + 1;
1090         for (cp = ref; (ch = *cp) != 0; cp++, len++)
1091                 if (needs_quote(ch))
1092                         len += 2; /* extra two hex plus replacement % */
1093         qref = xmalloc(len);
1094         memcpy(qref, base, baselen);
1095         for (cp = ref, dp = qref + baselen; (ch = *cp) != 0; cp++) {
1096                 if (needs_quote(ch)) {
1097                         *dp++ = '%';
1098                         *dp++ = hex((ch >> 4) & 0xF);
1099                         *dp++ = hex(ch & 0xF);
1100                 }
1101                 else
1102                         *dp++ = ch;
1103         }
1104         *dp = 0;
1105
1106         return qref;
1107 }
1108
1109 int fetch_ref(char *ref, unsigned char *sha1)
1110 {
1111         char *url;
1112         char hex[42];
1113         struct buffer buffer;
1114         char *base = remote->url;
1115         struct active_request_slot *slot;
1116         struct slot_results results;
1117         buffer.size = 41;
1118         buffer.posn = 0;
1119         buffer.buffer = hex;
1120         hex[41] = '\0';
1121
1122         url = quote_ref_url(base, ref);
1123         slot = get_active_slot();
1124         slot->results = &results;
1125         curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
1126         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1127         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
1128         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1129         if (start_active_slot(slot)) {
1130                 run_active_slot(slot);
1131                 if (results.curl_result != CURLE_OK)
1132                         return error("Couldn't get %s for %s\n%s",
1133                                      url, ref, curl_errorstr);
1134         } else {
1135                 return error("Unable to start request");
1136         }
1137
1138         hex[40] = '\0';
1139         get_sha1_hex(hex, sha1);
1140         return 0;
1141 }
1142
1143 static void one_remote_object(const char *hex)
1144 {
1145         unsigned char sha1[20];
1146         struct object *obj;
1147
1148         if (get_sha1_hex(hex, sha1) != 0)
1149                 return;
1150
1151         obj = lookup_object(sha1);
1152         if (!obj)
1153                 obj = parse_object(sha1);
1154
1155         /* Ignore remote objects that don't exist locally */
1156         if (!obj)
1157                 return;
1158
1159         obj->flags |= REMOTE;
1160         if (!object_list_contains(objects, obj))
1161                 add_object(obj, &objects, NULL, "");
1162 }
1163
1164 static void handle_lockprop_ctx(struct xml_ctx *ctx, int tag_closed)
1165 {
1166         int *lock_flags = (int *)ctx->userData;
1167
1168         if (tag_closed) {
1169                 if (!strcmp(ctx->name, DAV_CTX_LOCKENTRY)) {
1170                         if ((*lock_flags & DAV_PROP_LOCKEX) &&
1171                             (*lock_flags & DAV_PROP_LOCKWR)) {
1172                                 *lock_flags |= DAV_LOCK_OK;
1173                         }
1174                         *lock_flags &= DAV_LOCK_OK;
1175                 } else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_WRITE)) {
1176                         *lock_flags |= DAV_PROP_LOCKWR;
1177                 } else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_EXCLUSIVE)) {
1178                         *lock_flags |= DAV_PROP_LOCKEX;
1179                 }
1180         }
1181 }
1182
1183 static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
1184 {
1185         struct remote_lock *lock = (struct remote_lock *)ctx->userData;
1186
1187         if (tag_closed && ctx->cdata) {
1188                 if (!strcmp(ctx->name, DAV_ACTIVELOCK_OWNER)) {
1189                         lock->owner = xmalloc(strlen(ctx->cdata) + 1);
1190                         strcpy(lock->owner, ctx->cdata);
1191                 } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TIMEOUT)) {
1192                         if (!strncmp(ctx->cdata, "Second-", 7))
1193                                 lock->timeout =
1194                                         strtol(ctx->cdata + 7, NULL, 10);
1195                 } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
1196                         if (!strncmp(ctx->cdata, "opaquelocktoken:", 16)) {
1197                                 lock->token = xmalloc(strlen(ctx->cdata) - 15);
1198                                 strcpy(lock->token, ctx->cdata + 16);
1199                         }
1200                 }
1201         }
1202 }
1203
1204 static void one_remote_ref(char *refname);
1205
1206 static void
1207 xml_start_tag(void *userData, const char *name, const char **atts)
1208 {
1209         struct xml_ctx *ctx = (struct xml_ctx *)userData;
1210         const char *c = index(name, ':');
1211         int new_len;
1212
1213         if (c == NULL)
1214                 c = name;
1215         else
1216                 c++;
1217
1218         new_len = strlen(ctx->name) + strlen(c) + 2;
1219
1220         if (new_len > ctx->len) {
1221                 ctx->name = xrealloc(ctx->name, new_len);
1222                 ctx->len = new_len;
1223         }
1224         strcat(ctx->name, ".");
1225         strcat(ctx->name, c);
1226
1227         if (ctx->cdata) {
1228                 free(ctx->cdata);
1229                 ctx->cdata = NULL;
1230         }
1231
1232         ctx->userFunc(ctx, 0);
1233 }
1234
1235 static void
1236 xml_end_tag(void *userData, const char *name)
1237 {
1238         struct xml_ctx *ctx = (struct xml_ctx *)userData;
1239         const char *c = index(name, ':');
1240         char *ep;
1241
1242         ctx->userFunc(ctx, 1);
1243
1244         if (c == NULL)
1245                 c = name;
1246         else
1247                 c++;
1248
1249         ep = ctx->name + strlen(ctx->name) - strlen(c) - 1;
1250         *ep = 0;
1251 }
1252
1253 static void
1254 xml_cdata(void *userData, const XML_Char *s, int len)
1255 {
1256         struct xml_ctx *ctx = (struct xml_ctx *)userData;
1257         if (ctx->cdata)
1258                 free(ctx->cdata);
1259         ctx->cdata = xcalloc(len+1, 1);
1260         strncpy(ctx->cdata, s, len);
1261 }
1262
1263 static struct remote_lock *lock_remote(char *path, long timeout)
1264 {
1265         struct active_request_slot *slot;
1266         struct slot_results results;
1267         struct buffer out_buffer;
1268         struct buffer in_buffer;
1269         char *out_data;
1270         char *in_data;
1271         char *url;
1272         char *ep;
1273         char timeout_header[25];
1274         struct remote_lock *lock = NULL;
1275         XML_Parser parser = XML_ParserCreate(NULL);
1276         enum XML_Status result;
1277         struct curl_slist *dav_headers = NULL;
1278         struct xml_ctx ctx;
1279
1280         url = xmalloc(strlen(remote->url) + strlen(path) + 1);
1281         sprintf(url, "%s%s", remote->url, path);
1282
1283         /* Make sure leading directories exist for the remote ref */
1284         ep = strchr(url + strlen(remote->url) + 11, '/');
1285         while (ep) {
1286                 *ep = 0;
1287                 slot = get_active_slot();
1288                 slot->results = &results;
1289                 curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
1290                 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1291                 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MKCOL);
1292                 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
1293                 if (start_active_slot(slot)) {
1294                         run_active_slot(slot);
1295                         if (results.curl_result != CURLE_OK &&
1296                             results.http_code != 405) {
1297                                 fprintf(stderr,
1298                                         "Unable to create branch path %s\n",
1299                                         url);
1300                                 free(url);
1301                                 return NULL;
1302                         }
1303                 } else {
1304                         fprintf(stderr, "Unable to start MKCOL request\n");
1305                         free(url);
1306                         return NULL;
1307                 }
1308                 *ep = '/';
1309                 ep = strchr(ep + 1, '/');
1310         }
1311
1312         out_buffer.size = strlen(LOCK_REQUEST) + strlen(git_default_email) - 2;
1313         out_data = xmalloc(out_buffer.size + 1);
1314         snprintf(out_data, out_buffer.size + 1, LOCK_REQUEST, git_default_email);
1315         out_buffer.posn = 0;
1316         out_buffer.buffer = out_data;
1317
1318         in_buffer.size = 4096;
1319         in_data = xmalloc(in_buffer.size);
1320         in_buffer.posn = 0;
1321         in_buffer.buffer = in_data;
1322
1323         sprintf(timeout_header, "Timeout: Second-%ld", timeout);
1324         dav_headers = curl_slist_append(dav_headers, timeout_header);
1325         dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1326
1327         slot = get_active_slot();
1328         slot->results = &results;
1329         curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1330         curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1331         curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1332         curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1333         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1334         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1335         curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1336         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
1337         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1338
1339         lock = xcalloc(1, sizeof(*lock));
1340         lock->timeout = -1;
1341
1342         if (start_active_slot(slot)) {
1343                 run_active_slot(slot);
1344                 if (results.curl_result == CURLE_OK) {
1345                         ctx.name = xcalloc(10, 1);
1346                         ctx.len = 0;
1347                         ctx.cdata = NULL;
1348                         ctx.userFunc = handle_new_lock_ctx;
1349                         ctx.userData = lock;
1350                         XML_SetUserData(parser, &ctx);
1351                         XML_SetElementHandler(parser, xml_start_tag,
1352                                               xml_end_tag);
1353                         XML_SetCharacterDataHandler(parser, xml_cdata);
1354                         result = XML_Parse(parser, in_buffer.buffer,
1355                                            in_buffer.posn, 1);
1356                         free(ctx.name);
1357                         if (result != XML_STATUS_OK) {
1358                                 fprintf(stderr, "XML error: %s\n",
1359                                         XML_ErrorString(
1360                                                 XML_GetErrorCode(parser)));
1361                                 lock->timeout = -1;
1362                         }
1363                 }
1364         } else {
1365                 fprintf(stderr, "Unable to start LOCK request\n");
1366         }
1367
1368         curl_slist_free_all(dav_headers);
1369         free(out_data);
1370         free(in_data);
1371
1372         if (lock->token == NULL || lock->timeout <= 0) {
1373                 if (lock->token != NULL)
1374                         free(lock->token);
1375                 if (lock->owner != NULL)
1376                         free(lock->owner);
1377                 free(url);
1378                 free(lock);
1379                 lock = NULL;
1380         } else {
1381                 lock->url = url;
1382                 lock->start_time = time(NULL);
1383                 lock->next = remote->locks;
1384                 remote->locks = lock;
1385         }
1386
1387         return lock;
1388 }
1389
1390 static int unlock_remote(struct remote_lock *lock)
1391 {
1392         struct active_request_slot *slot;
1393         struct slot_results results;
1394         struct remote_lock *prev = remote->locks;
1395         char *lock_token_header;
1396         struct curl_slist *dav_headers = NULL;
1397         int rc = 0;
1398
1399         lock_token_header = xmalloc(strlen(lock->token) + 31);
1400         sprintf(lock_token_header, "Lock-Token: <opaquelocktoken:%s>",
1401                 lock->token);
1402         dav_headers = curl_slist_append(dav_headers, lock_token_header);
1403
1404         slot = get_active_slot();
1405         slot->results = &results;
1406         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
1407         curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
1408         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_UNLOCK);
1409         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1410
1411         if (start_active_slot(slot)) {
1412                 run_active_slot(slot);
1413                 if (results.curl_result == CURLE_OK)
1414                         rc = 1;
1415                 else
1416                         fprintf(stderr, "UNLOCK HTTP error %ld\n",
1417                                 results.http_code);
1418         } else {
1419                 fprintf(stderr, "Unable to start UNLOCK request\n");
1420         }
1421
1422         curl_slist_free_all(dav_headers);
1423         free(lock_token_header);
1424
1425         if (remote->locks == lock) {
1426                 remote->locks = lock->next;
1427         } else {
1428                 while (prev && prev->next != lock)
1429                         prev = prev->next;
1430                 if (prev)
1431                         prev->next = prev->next->next;
1432         }
1433
1434         if (lock->owner != NULL)
1435                 free(lock->owner);
1436         free(lock->url);
1437         free(lock->token);
1438         free(lock);
1439
1440         return rc;
1441 }
1442
1443 static void remote_ls(const char *path, int flags,
1444                       void (*userFunc)(struct remote_ls_ctx *ls),
1445                       void *userData);
1446
1447 static void process_ls_object(struct remote_ls_ctx *ls)
1448 {
1449         unsigned int *parent = (unsigned int *)ls->userData;
1450         char *path = ls->dentry_name;
1451         char *obj_hex;
1452
1453         if (!strcmp(ls->path, ls->dentry_name) && (ls->flags & IS_DIR)) {
1454                 remote_dir_exists[*parent] = 1;
1455                 return;
1456         }
1457
1458         if (strlen(path) != 49)
1459                 return;
1460         path += 8;
1461         obj_hex = xmalloc(strlen(path));
1462         strncpy(obj_hex, path, 2);
1463         strcpy(obj_hex + 2, path + 3);
1464         one_remote_object(obj_hex);
1465         free(obj_hex);
1466 }
1467
1468 static void process_ls_ref(struct remote_ls_ctx *ls)
1469 {
1470         if (!strcmp(ls->path, ls->dentry_name) && (ls->dentry_flags & IS_DIR)) {
1471                 fprintf(stderr, "  %s\n", ls->dentry_name);
1472                 return;
1473         }
1474
1475         if (!(ls->dentry_flags & IS_DIR))
1476                 one_remote_ref(ls->dentry_name);
1477 }
1478
1479 static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
1480 {
1481         struct remote_ls_ctx *ls = (struct remote_ls_ctx *)ctx->userData;
1482
1483         if (tag_closed) {
1484                 if (!strcmp(ctx->name, DAV_PROPFIND_RESP) && ls->dentry_name) {
1485                         if (ls->dentry_flags & IS_DIR) {
1486                                 if (ls->flags & PROCESS_DIRS) {
1487                                         ls->userFunc(ls);
1488                                 }
1489                                 if (strcmp(ls->dentry_name, ls->path) &&
1490                                     ls->flags & RECURSIVE) {
1491                                         remote_ls(ls->dentry_name,
1492                                                   ls->flags,
1493                                                   ls->userFunc,
1494                                                   ls->userData);
1495                                 }
1496                         } else if (ls->flags & PROCESS_FILES) {
1497                                 ls->userFunc(ls);
1498                         }
1499                 } else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
1500                         ls->dentry_name = xmalloc(strlen(ctx->cdata) -
1501                                                   remote->path_len + 1);
1502                         strcpy(ls->dentry_name, ctx->cdata + remote->path_len);
1503                 } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
1504                         ls->dentry_flags |= IS_DIR;
1505                 }
1506         } else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
1507                 if (ls->dentry_name) {
1508                         free(ls->dentry_name);
1509                 }
1510                 ls->dentry_name = NULL;
1511                 ls->dentry_flags = 0;
1512         }
1513 }
1514
1515 static void remote_ls(const char *path, int flags,
1516                       void (*userFunc)(struct remote_ls_ctx *ls),
1517                       void *userData)
1518 {
1519         char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
1520         struct active_request_slot *slot;
1521         struct slot_results results;
1522         struct buffer in_buffer;
1523         struct buffer out_buffer;
1524         char *in_data;
1525         char *out_data;
1526         XML_Parser parser = XML_ParserCreate(NULL);
1527         enum XML_Status result;
1528         struct curl_slist *dav_headers = NULL;
1529         struct xml_ctx ctx;
1530         struct remote_ls_ctx ls;
1531
1532         ls.flags = flags;
1533         ls.path = strdup(path);
1534         ls.dentry_name = NULL;
1535         ls.dentry_flags = 0;
1536         ls.userData = userData;
1537         ls.userFunc = userFunc;
1538
1539         sprintf(url, "%s%s", remote->url, path);
1540
1541         out_buffer.size = strlen(PROPFIND_ALL_REQUEST);
1542         out_data = xmalloc(out_buffer.size + 1);
1543         snprintf(out_data, out_buffer.size + 1, PROPFIND_ALL_REQUEST);
1544         out_buffer.posn = 0;
1545         out_buffer.buffer = out_data;
1546
1547         in_buffer.size = 4096;
1548         in_data = xmalloc(in_buffer.size);
1549         in_buffer.posn = 0;
1550         in_buffer.buffer = in_data;
1551
1552         dav_headers = curl_slist_append(dav_headers, "Depth: 1");
1553         dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1554
1555         slot = get_active_slot();
1556         slot->results = &results;
1557         curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1558         curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1559         curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1560         curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1561         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1562         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1563         curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1564         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
1565         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1566
1567         if (start_active_slot(slot)) {
1568                 run_active_slot(slot);
1569                 if (results.curl_result == CURLE_OK) {
1570                         ctx.name = xcalloc(10, 1);
1571                         ctx.len = 0;
1572                         ctx.cdata = NULL;
1573                         ctx.userFunc = handle_remote_ls_ctx;
1574                         ctx.userData = &ls;
1575                         XML_SetUserData(parser, &ctx);
1576                         XML_SetElementHandler(parser, xml_start_tag,
1577                                               xml_end_tag);
1578                         XML_SetCharacterDataHandler(parser, xml_cdata);
1579                         result = XML_Parse(parser, in_buffer.buffer,
1580                                            in_buffer.posn, 1);
1581                         free(ctx.name);
1582
1583                         if (result != XML_STATUS_OK) {
1584                                 fprintf(stderr, "XML error: %s\n",
1585                                         XML_ErrorString(
1586                                                 XML_GetErrorCode(parser)));
1587                         }
1588                 }
1589         } else {
1590                 fprintf(stderr, "Unable to start PROPFIND request\n");
1591         }
1592
1593         free(ls.path);
1594         free(url);
1595         free(out_data);
1596         free(in_buffer.buffer);
1597         curl_slist_free_all(dav_headers);
1598 }
1599
1600 static void get_remote_object_list(unsigned char parent)
1601 {
1602         char path[] = "objects/XX/";
1603         static const char hex[] = "0123456789abcdef";
1604         unsigned int val = parent;
1605
1606         path[8] = hex[val >> 4];
1607         path[9] = hex[val & 0xf];
1608         remote_dir_exists[val] = 0;
1609         remote_ls(path, (PROCESS_FILES | PROCESS_DIRS),
1610                   process_ls_object, &val);
1611 }
1612
1613 static int locking_available(void)
1614 {
1615         struct active_request_slot *slot;
1616         struct slot_results results;
1617         struct buffer in_buffer;
1618         struct buffer out_buffer;
1619         char *in_data;
1620         char *out_data;
1621         XML_Parser parser = XML_ParserCreate(NULL);
1622         enum XML_Status result;
1623         struct curl_slist *dav_headers = NULL;
1624         struct xml_ctx ctx;
1625         int lock_flags = 0;
1626
1627         out_buffer.size =
1628                 strlen(PROPFIND_SUPPORTEDLOCK_REQUEST) +
1629                 strlen(remote->url) - 2;
1630         out_data = xmalloc(out_buffer.size + 1);
1631         snprintf(out_data, out_buffer.size + 1,
1632                  PROPFIND_SUPPORTEDLOCK_REQUEST, remote->url);
1633         out_buffer.posn = 0;
1634         out_buffer.buffer = out_data;
1635
1636         in_buffer.size = 4096;
1637         in_data = xmalloc(in_buffer.size);
1638         in_buffer.posn = 0;
1639         in_buffer.buffer = in_data;
1640
1641         dav_headers = curl_slist_append(dav_headers, "Depth: 0");
1642         dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1643
1644         slot = get_active_slot();
1645         slot->results = &results;
1646         curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1647         curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1648         curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1649         curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1650         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1651         curl_easy_setopt(slot->curl, CURLOPT_URL, remote->url);
1652         curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1653         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
1654         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1655
1656         if (start_active_slot(slot)) {
1657                 run_active_slot(slot);
1658                 if (results.curl_result == CURLE_OK) {
1659                         ctx.name = xcalloc(10, 1);
1660                         ctx.len = 0;
1661                         ctx.cdata = NULL;
1662                         ctx.userFunc = handle_lockprop_ctx;
1663                         ctx.userData = &lock_flags;
1664                         XML_SetUserData(parser, &ctx);
1665                         XML_SetElementHandler(parser, xml_start_tag,
1666                                               xml_end_tag);
1667                         result = XML_Parse(parser, in_buffer.buffer,
1668                                            in_buffer.posn, 1);
1669                         free(ctx.name);
1670
1671                         if (result != XML_STATUS_OK) {
1672                                 fprintf(stderr, "XML error: %s\n",
1673                                         XML_ErrorString(
1674                                                 XML_GetErrorCode(parser)));
1675                                 lock_flags = 0;
1676                         }
1677                 }
1678         } else {
1679                 fprintf(stderr, "Unable to start PROPFIND request\n");
1680         }
1681
1682         free(out_data);
1683         free(in_buffer.buffer);
1684         curl_slist_free_all(dav_headers);
1685
1686         return lock_flags;
1687 }
1688
1689 static struct object_list **process_blob(struct blob *blob,
1690                                          struct object_list **p,
1691                                          struct name_path *path,
1692                                          const char *name)
1693 {
1694         struct object *obj = &blob->object;
1695
1696         obj->flags |= LOCAL;
1697
1698         if (obj->flags & (UNINTERESTING | SEEN))
1699                 return p;
1700
1701         obj->flags |= SEEN;
1702         return add_object(obj, p, path, name);
1703 }
1704
1705 static struct object_list **process_tree(struct tree *tree,
1706                                          struct object_list **p,
1707                                          struct name_path *path,
1708                                          const char *name)
1709 {
1710         struct object *obj = &tree->object;
1711         struct tree_entry_list *entry;
1712         struct name_path me;
1713
1714         obj->flags |= LOCAL;
1715
1716         if (obj->flags & (UNINTERESTING | SEEN))
1717                 return p;
1718         if (parse_tree(tree) < 0)
1719                 die("bad tree object %s", sha1_to_hex(obj->sha1));
1720
1721         obj->flags |= SEEN;
1722         p = add_object(obj, p, NULL, name);
1723         me.up = path;
1724         me.elem = name;
1725         me.elem_len = strlen(name);
1726         entry = tree->entries;
1727         tree->entries = NULL;
1728         while (entry) {
1729                 struct tree_entry_list *next = entry->next;
1730                 if (entry->directory)
1731                         p = process_tree(entry->item.tree, p, &me, entry->name);
1732                 else
1733                         p = process_blob(entry->item.blob, p, &me, entry->name);
1734                 free(entry);
1735                 entry = next;
1736         }
1737         return p;
1738 }
1739
1740 static int get_delta(struct rev_info *revs, struct remote_lock *lock)
1741 {
1742         struct commit *commit;
1743         struct object_list **p = &objects, *pending;
1744         int count = 0;
1745
1746         while ((commit = get_revision(revs)) != NULL) {
1747                 p = process_tree(commit->tree, p, NULL, "");
1748                 commit->object.flags |= LOCAL;
1749                 if (!(commit->object.flags & UNINTERESTING))
1750                         count += add_send_request(&commit->object, lock);
1751         }
1752
1753         for (pending = revs->pending_objects; pending; pending = pending->next) {
1754                 struct object *obj = pending->item;
1755                 const char *name = pending->name;
1756
1757                 if (obj->flags & (UNINTERESTING | SEEN))
1758                         continue;
1759                 if (obj->type == tag_type) {
1760                         obj->flags |= SEEN;
1761                         p = add_object(obj, p, NULL, name);
1762                         continue;
1763                 }
1764                 if (obj->type == tree_type) {
1765                         p = process_tree((struct tree *)obj, p, NULL, name);
1766                         continue;
1767                 }
1768                 if (obj->type == blob_type) {
1769                         p = process_blob((struct blob *)obj, p, NULL, name);
1770                         continue;
1771                 }
1772                 die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
1773         }
1774
1775         while (objects) {
1776                 if (!(objects->item->flags & UNINTERESTING))
1777                         count += add_send_request(objects->item, lock);
1778                 objects = objects->next;
1779         }
1780
1781         return count;
1782 }
1783
1784 static int update_remote(unsigned char *sha1, struct remote_lock *lock)
1785 {
1786         struct active_request_slot *slot;
1787         struct slot_results results;
1788         char *out_data;
1789         char *if_header;
1790         struct buffer out_buffer;
1791         struct curl_slist *dav_headers = NULL;
1792         int i;
1793
1794         if_header = xmalloc(strlen(lock->token) + 25);
1795         sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
1796         dav_headers = curl_slist_append(dav_headers, if_header);
1797
1798         out_buffer.size = 41;
1799         out_data = xmalloc(out_buffer.size + 1);
1800         i = snprintf(out_data, out_buffer.size + 1, "%s\n", sha1_to_hex(sha1));
1801         if (i != out_buffer.size) {
1802                 fprintf(stderr, "Unable to initialize PUT request body\n");
1803                 return 0;
1804         }
1805         out_buffer.posn = 0;
1806         out_buffer.buffer = out_data;
1807
1808         slot = get_active_slot();
1809         slot->results = &results;
1810         curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1811         curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1812         curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1813         curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
1814         curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
1815         curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1816         curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1817         curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
1818         curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
1819
1820         if (start_active_slot(slot)) {
1821                 run_active_slot(slot);
1822                 free(out_data);
1823                 free(if_header);
1824                 if (results.curl_result != CURLE_OK) {
1825                         fprintf(stderr,
1826                                 "PUT error: curl result=%d, HTTP code=%ld\n",
1827                                 results.curl_result, results.http_code);
1828                         /* We should attempt recovery? */
1829                         return 0;
1830                 }
1831         } else {
1832                 free(out_data);
1833                 free(if_header);
1834                 fprintf(stderr, "Unable to start PUT request\n");
1835                 return 0;
1836         }
1837
1838         return 1;
1839 }
1840
1841 static struct ref *local_refs, **local_tail;
1842 static struct ref *remote_refs, **remote_tail;
1843
1844 static int one_local_ref(const char *refname, const unsigned char *sha1)
1845 {
1846         struct ref *ref;
1847         int len = strlen(refname) + 1;
1848         ref = xcalloc(1, sizeof(*ref) + len);
1849         memcpy(ref->new_sha1, sha1, 20);
1850         memcpy(ref->name, refname, len);
1851         *local_tail = ref;
1852         local_tail = &ref->next;
1853         return 0;
1854 }
1855
1856 static void one_remote_ref(char *refname)
1857 {
1858         struct ref *ref;
1859         unsigned char remote_sha1[20];
1860         struct object *obj;
1861
1862         if (fetch_ref(refname, remote_sha1) != 0) {
1863                 fprintf(stderr,
1864                         "Unable to fetch ref %s from %s\n",
1865                         refname, remote->url);
1866                 return;
1867         }
1868
1869         /*
1870          * Fetch a copy of the object if it doesn't exist locally - it
1871          * may be required for updating server info later.
1872          */
1873         if (remote->can_update_info_refs && !has_sha1_file(remote_sha1)) {
1874                 obj = lookup_unknown_object(remote_sha1);
1875                 if (obj) {
1876                         fprintf(stderr, "  fetch %s for %s\n",
1877                                 sha1_to_hex(remote_sha1), refname);
1878                         add_fetch_request(obj);
1879                 }
1880         }
1881
1882         int len = strlen(refname) + 1;
1883         ref = xcalloc(1, sizeof(*ref) + len);
1884         memcpy(ref->old_sha1, remote_sha1, 20);
1885         memcpy(ref->name, refname, len);
1886         *remote_tail = ref;
1887         remote_tail = &ref->next;
1888 }
1889
1890 static void get_local_heads(void)
1891 {
1892         local_tail = &local_refs;
1893         for_each_ref(one_local_ref);
1894 }
1895
1896 static void get_dav_remote_heads(void)
1897 {
1898         remote_tail = &remote_refs;
1899         remote_ls("refs/", (PROCESS_FILES | PROCESS_DIRS | RECURSIVE), process_ls_ref, NULL);
1900 }
1901
1902 static int is_zero_sha1(const unsigned char *sha1)
1903 {
1904         int i;
1905
1906         for (i = 0; i < 20; i++) {
1907                 if (*sha1++)
1908                         return 0;
1909         }
1910         return 1;
1911 }
1912
1913 static void unmark_and_free(struct commit_list *list, unsigned int mark)
1914 {
1915         while (list) {
1916                 struct commit_list *temp = list;
1917                 temp->item->object.flags &= ~mark;
1918                 list = temp->next;
1919                 free(temp);
1920         }
1921 }
1922
1923 static int ref_newer(const unsigned char *new_sha1,
1924                      const unsigned char *old_sha1)
1925 {
1926         struct object *o;
1927         struct commit *old, *new;
1928         struct commit_list *list, *used;
1929         int found = 0;
1930
1931         /* Both new and old must be commit-ish and new is descendant of
1932          * old.  Otherwise we require --force.
1933          */
1934         o = deref_tag(parse_object(old_sha1), NULL, 0);
1935         if (!o || o->type != commit_type)
1936                 return 0;
1937         old = (struct commit *) o;
1938
1939         o = deref_tag(parse_object(new_sha1), NULL, 0);
1940         if (!o || o->type != commit_type)
1941                 return 0;
1942         new = (struct commit *) o;
1943
1944         if (parse_commit(new) < 0)
1945                 return 0;
1946
1947         used = list = NULL;
1948         commit_list_insert(new, &list);
1949         while (list) {
1950                 new = pop_most_recent_commit(&list, TMP_MARK);
1951                 commit_list_insert(new, &used);
1952                 if (new == old) {
1953                         found = 1;
1954                         break;
1955                 }
1956         }
1957         unmark_and_free(list, TMP_MARK);
1958         unmark_and_free(used, TMP_MARK);
1959         return found;
1960 }
1961
1962 static void mark_edge_parents_uninteresting(struct commit *commit)
1963 {
1964         struct commit_list *parents;
1965
1966         for (parents = commit->parents; parents; parents = parents->next) {
1967                 struct commit *parent = parents->item;
1968                 if (!(parent->object.flags & UNINTERESTING))
1969                         continue;
1970                 mark_tree_uninteresting(parent->tree);
1971         }
1972 }
1973
1974 static void mark_edges_uninteresting(struct commit_list *list)
1975 {
1976         for ( ; list; list = list->next) {
1977                 struct commit *commit = list->item;
1978
1979                 if (commit->object.flags & UNINTERESTING) {
1980                         mark_tree_uninteresting(commit->tree);
1981                         continue;
1982                 }
1983                 mark_edge_parents_uninteresting(commit);
1984         }
1985 }
1986
1987 static void add_remote_info_ref(struct remote_ls_ctx *ls)
1988 {
1989         struct buffer *buf = (struct buffer *)ls->userData;
1990         unsigned char remote_sha1[20];
1991         struct object *o;
1992         int len;
1993         char *ref_info;
1994
1995         if (fetch_ref(ls->dentry_name, remote_sha1) != 0) {
1996                 fprintf(stderr,
1997                         "Unable to fetch ref %s from %s\n",
1998                         ls->dentry_name, remote->url);
1999                 aborted = 1;
2000                 return;
2001         }
2002
2003         o = parse_object(remote_sha1);
2004         if (!o) {
2005                 fprintf(stderr,
2006                         "Unable to parse object %s for remote ref %s\n",
2007                         sha1_to_hex(remote_sha1), ls->dentry_name);
2008                 aborted = 1;
2009                 return;
2010         }
2011
2012         len = strlen(ls->dentry_name) + 42;
2013         ref_info = xcalloc(len + 1, 1);
2014         sprintf(ref_info, "%s   %s\n",
2015                 sha1_to_hex(remote_sha1), ls->dentry_name);
2016         fwrite_buffer(ref_info, 1, len, buf);
2017         free(ref_info);
2018
2019         if (o->type == tag_type) {
2020                 o = deref_tag(o, ls->dentry_name, 0);
2021                 if (o) {
2022                         len = strlen(ls->dentry_name) + 45;
2023                         ref_info = xcalloc(len + 1, 1);
2024                         sprintf(ref_info, "%s   %s^{}\n",
2025                                 sha1_to_hex(o->sha1), ls->dentry_name);
2026                         fwrite_buffer(ref_info, 1, len, buf);
2027                         free(ref_info);
2028                 }
2029         }
2030 }
2031
2032 static void update_remote_info_refs(struct remote_lock *lock)
2033 {
2034         struct buffer buffer;
2035         struct active_request_slot *slot;
2036         struct slot_results results;
2037         char *if_header;
2038         struct curl_slist *dav_headers = NULL;
2039
2040         buffer.buffer = xmalloc(4096);
2041         memset(buffer.buffer, 0, 4096);
2042         buffer.size = 4096;
2043         buffer.posn = 0;
2044         remote_ls("refs/", (PROCESS_FILES | RECURSIVE),
2045                   add_remote_info_ref, &buffer);
2046         if (!aborted) {
2047                 if_header = xmalloc(strlen(lock->token) + 25);
2048                 sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
2049                 dav_headers = curl_slist_append(dav_headers, if_header);
2050
2051                 slot = get_active_slot();
2052                 slot->results = &results;
2053                 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &buffer);
2054                 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, buffer.posn);
2055                 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
2056                 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
2057                 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
2058                 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
2059                 curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
2060                 curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
2061                 curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
2062
2063                 buffer.posn = 0;
2064
2065                 if (start_active_slot(slot)) {
2066                         run_active_slot(slot);
2067                         if (results.curl_result != CURLE_OK) {
2068                                 fprintf(stderr,
2069                                         "PUT error: curl result=%d, HTTP code=%ld\n",
2070                                         results.curl_result, results.http_code);
2071                         }
2072                 }
2073                 free(if_header);
2074         }
2075         free(buffer.buffer);
2076 }
2077
2078 static int remote_exists(const char *path)
2079 {
2080         char *url = xmalloc(strlen(remote->url) + strlen(path) + 1);
2081         struct active_request_slot *slot;
2082         struct slot_results results;
2083
2084         sprintf(url, "%s%s", remote->url, path);
2085
2086         slot = get_active_slot();
2087         slot->results = &results;
2088         curl_easy_setopt(slot->curl, CURLOPT_URL, url);
2089         curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
2090
2091         if (start_active_slot(slot)) {
2092                 run_active_slot(slot);
2093                 if (results.http_code == 404)
2094                         return 0;
2095                 else if (results.curl_result == CURLE_OK)
2096                         return 1;
2097                 else
2098                         fprintf(stderr, "HEAD HTTP error %ld\n", results.http_code);
2099         } else {
2100                 fprintf(stderr, "Unable to start HEAD request\n");
2101         }
2102
2103         return -1;
2104 }
2105
2106 int main(int argc, char **argv)
2107 {
2108         struct transfer_request *request;
2109         struct transfer_request *next_request;
2110         int nr_refspec = 0;
2111         char **refspec = NULL;
2112         struct remote_lock *ref_lock = NULL;
2113         struct remote_lock *info_ref_lock = NULL;
2114         struct rev_info revs;
2115         int objects_to_send;
2116         int rc = 0;
2117         int i;
2118
2119         setup_git_directory();
2120         setup_ident();
2121
2122         remote = xcalloc(sizeof(*remote), 1);
2123
2124         argv++;
2125         for (i = 1; i < argc; i++, argv++) {
2126                 char *arg = *argv;
2127
2128                 if (*arg == '-') {
2129                         if (!strcmp(arg, "--all")) {
2130                                 push_all = 1;
2131                                 continue;
2132                         }
2133                         if (!strcmp(arg, "--force")) {
2134                                 force_all = 1;
2135                                 continue;
2136                         }
2137                         if (!strcmp(arg, "--verbose")) {
2138                                 push_verbosely = 1;
2139                                 continue;
2140                         }
2141                         usage(http_push_usage);
2142                 }
2143                 if (!remote->url) {
2144                         remote->url = arg;
2145                         char *path = strstr(arg, "//");
2146                         if (path) {
2147                                 path = index(path+2, '/');
2148                                 if (path)
2149                                         remote->path_len = strlen(path);
2150                         }
2151                         continue;
2152                 }
2153                 refspec = argv;
2154                 nr_refspec = argc - i;
2155                 break;
2156         }
2157
2158         if (!remote->url)
2159                 usage(http_push_usage);
2160
2161         memset(remote_dir_exists, -1, 256);
2162
2163         http_init();
2164
2165         no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
2166         default_headers = curl_slist_append(default_headers, "Range:");
2167         default_headers = curl_slist_append(default_headers, "Destination:");
2168         default_headers = curl_slist_append(default_headers, "If:");
2169         default_headers = curl_slist_append(default_headers,
2170                                             "Pragma: no-cache");
2171
2172         /* Verify DAV compliance/lock support */
2173         if (!locking_available()) {
2174                 fprintf(stderr, "Error: no DAV locking support on remote repo %s\n", remote->url);
2175                 rc = 1;
2176                 goto cleanup;
2177         }
2178
2179         /* Check whether the remote has server info files */
2180         remote->can_update_info_refs = 0;
2181         remote->has_info_refs = remote_exists("info/refs");
2182         remote->has_info_packs = remote_exists("objects/info/packs");
2183         if (remote->has_info_refs) {
2184                 info_ref_lock = lock_remote("info/refs", LOCK_TIME);
2185                 if (info_ref_lock)
2186                         remote->can_update_info_refs = 1;
2187         }
2188         if (remote->has_info_packs)
2189                 fetch_indices();
2190
2191         /* Get a list of all local and remote heads to validate refspecs */
2192         get_local_heads();
2193         fprintf(stderr, "Fetching remote heads...\n");
2194         get_dav_remote_heads();
2195
2196         /* match them up */
2197         if (!remote_tail)
2198                 remote_tail = &remote_refs;
2199         if (match_refs(local_refs, remote_refs, &remote_tail,
2200                        nr_refspec, refspec, push_all))
2201                 return -1;
2202         if (!remote_refs) {
2203                 fprintf(stderr, "No refs in common and none specified; doing nothing.\n");
2204                 return 0;
2205         }
2206
2207         int new_refs = 0;
2208         struct ref *ref;
2209         for (ref = remote_refs; ref; ref = ref->next) {
2210                 char old_hex[60], *new_hex;
2211                 if (!ref->peer_ref)
2212                         continue;
2213                 if (!memcmp(ref->old_sha1, ref->peer_ref->new_sha1, 20)) {
2214                         if (push_verbosely || 1)
2215                                 fprintf(stderr, "'%s': up-to-date\n", ref->name);
2216                         continue;
2217                 }
2218
2219                 if (!force_all &&
2220                     !is_zero_sha1(ref->old_sha1) &&
2221                     !ref->force) {
2222                         if (!has_sha1_file(ref->old_sha1) ||
2223                             !ref_newer(ref->peer_ref->new_sha1,
2224                                        ref->old_sha1)) {
2225                                 /* We do not have the remote ref, or
2226                                  * we know that the remote ref is not
2227                                  * an ancestor of what we are trying to
2228                                  * push.  Either way this can be losing
2229                                  * commits at the remote end and likely
2230                                  * we were not up to date to begin with.
2231                                  */
2232                                 error("remote '%s' is not a strict "
2233                                       "subset of local ref '%s'. "
2234                                       "maybe you are not up-to-date and "
2235                                       "need to pull first?",
2236                                       ref->name,
2237                                       ref->peer_ref->name);
2238                                 rc = -2;
2239                                 continue;
2240                         }
2241                 }
2242                 memcpy(ref->new_sha1, ref->peer_ref->new_sha1, 20);
2243                 if (is_zero_sha1(ref->new_sha1)) {
2244                         error("cannot happen anymore");
2245                         rc = -3;
2246                         continue;
2247                 }
2248                 new_refs++;
2249                 strcpy(old_hex, sha1_to_hex(ref->old_sha1));
2250                 new_hex = sha1_to_hex(ref->new_sha1);
2251
2252                 fprintf(stderr, "updating '%s'", ref->name);
2253                 if (strcmp(ref->name, ref->peer_ref->name))
2254                         fprintf(stderr, " using '%s'", ref->peer_ref->name);
2255                 fprintf(stderr, "\n  from %s\n  to   %s\n", old_hex, new_hex);
2256
2257
2258                 /* Lock remote branch ref */
2259                 ref_lock = lock_remote(ref->name, LOCK_TIME);
2260                 if (ref_lock == NULL) {
2261                         fprintf(stderr, "Unable to lock remote branch %s\n",
2262                                 ref->name);
2263                         rc = 1;
2264                         continue;
2265                 }
2266
2267                 /* Set up revision info for this refspec */
2268                 const char *commit_argv[4];
2269                 int commit_argc = 3;
2270                 char *new_sha1_hex = strdup(sha1_to_hex(ref->new_sha1));
2271                 char *old_sha1_hex = NULL;
2272                 commit_argv[1] = "--objects";
2273                 commit_argv[2] = new_sha1_hex;
2274                 if (!push_all && !is_zero_sha1(ref->old_sha1)) {
2275                         old_sha1_hex = xmalloc(42);
2276                         sprintf(old_sha1_hex, "^%s",
2277                                 sha1_to_hex(ref->old_sha1));
2278                         commit_argv[3] = old_sha1_hex;
2279                         commit_argc++;
2280                 }
2281                 setup_revisions(commit_argc, commit_argv, &revs, NULL);
2282                 free(new_sha1_hex);
2283                 if (old_sha1_hex) {
2284                         free(old_sha1_hex);
2285                         commit_argv[1] = NULL;
2286                 }
2287
2288                 /* Generate a list of objects that need to be pushed */
2289                 pushing = 0;
2290                 prepare_revision_walk(&revs);
2291                 mark_edges_uninteresting(revs.commits);
2292                 objects_to_send = get_delta(&revs, ref_lock);
2293                 finish_all_active_slots();
2294
2295                 /* Push missing objects to remote, this would be a
2296                    convenient time to pack them first if appropriate. */
2297                 pushing = 1;
2298                 if (objects_to_send)
2299                         fprintf(stderr, "    sending %d objects\n",
2300                                 objects_to_send);
2301                 fill_active_slots();
2302                 finish_all_active_slots();
2303
2304                 /* Update the remote branch if all went well */
2305                 if (aborted || !update_remote(ref->new_sha1, ref_lock)) {
2306                         rc = 1;
2307                         goto unlock;
2308                 }
2309
2310         unlock:
2311                 if (!rc)
2312                         fprintf(stderr, "    done\n");
2313                 unlock_remote(ref_lock);
2314                 check_locks();
2315         }
2316
2317         /* Update remote server info if appropriate */
2318         if (remote->has_info_refs && new_refs) {
2319                 if (info_ref_lock && remote->can_update_info_refs) {
2320                         fprintf(stderr, "Updating remote server info\n");
2321                         update_remote_info_refs(info_ref_lock);
2322                 } else {
2323                         fprintf(stderr, "Unable to update server info\n");
2324                 }
2325         }
2326         if (info_ref_lock)
2327                 unlock_remote(info_ref_lock);
2328
2329  cleanup:
2330         free(remote);
2331
2332         curl_slist_free_all(no_pragma_header);
2333         curl_slist_free_all(default_headers);
2334
2335         http_cleanup();
2336
2337         request = request_queue_head;
2338         while (request != NULL) {
2339                 next_request = request->next;
2340                 release_request(request);
2341                 request = next_request;
2342         }
2343
2344         return rc;
2345 }