13 static const char http_push_usage[] =
14 "git-http-push [--complete] [--force] [--verbose] <url> <ref> [<ref>...]\n";
21 #define XML_STATUS_OK 1
22 #define XML_STATUS_ERROR 0
25 #define RANGE_HEADER_SIZE 30
28 #define DAV_LOCK "LOCK"
29 #define DAV_MKCOL "MKCOL"
30 #define DAV_MOVE "MOVE"
31 #define DAV_PROPFIND "PROPFIND"
33 #define DAV_UNLOCK "UNLOCK"
36 #define DAV_PROP_LOCKWR (1u << 0)
37 #define DAV_PROP_LOCKEX (1u << 1)
38 #define DAV_LOCK_OK (1u << 2)
40 /* DAV XML properties */
41 #define DAV_CTX_LOCKENTRY ".multistatus.response.propstat.prop.supportedlock.lockentry"
42 #define DAV_CTX_LOCKTYPE_WRITE ".multistatus.response.propstat.prop.supportedlock.lockentry.locktype.write"
43 #define DAV_CTX_LOCKTYPE_EXCLUSIVE ".multistatus.response.propstat.prop.supportedlock.lockentry.lockscope.exclusive"
44 #define DAV_ACTIVELOCK_OWNER ".prop.lockdiscovery.activelock.owner.href"
45 #define DAV_ACTIVELOCK_TIMEOUT ".prop.lockdiscovery.activelock.timeout"
46 #define DAV_ACTIVELOCK_TOKEN ".prop.lockdiscovery.activelock.locktoken.href"
47 #define DAV_PROPFIND_RESP ".multistatus.response"
48 #define DAV_PROPFIND_NAME ".multistatus.response.href"
49 #define DAV_PROPFIND_COLLECTION ".multistatus.response.propstat.prop.resourcetype.collection"
51 /* DAV request body templates */
52 #define PROPFIND_SUPPORTEDLOCK_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:prop xmlns:R=\"%s\">\n<D:supportedlock/>\n</D:prop>\n</D:propfind>"
53 #define PROPFIND_ALL_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:allprop/>\n</D:propfind>"
54 #define LOCK_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:lockinfo xmlns:D=\"DAV:\">\n<D:lockscope><D:exclusive/></D:lockscope>\n<D:locktype><D:write/></D:locktype>\n<D:owner>\n<D:href>mailto:%s</D:href>\n</D:owner>\n</D:lockinfo>"
57 #define LOCK_REFRESH 30
59 /* bits #0-4 in revision.h */
61 #define LOCAL (1u << 5)
62 #define REMOTE (1u << 6)
63 #define PUSHING (1u << 7)
65 static int pushing = 0;
66 static int aborted = 0;
67 static char remote_dir_exists[256];
69 static struct curl_slist *no_pragma_header;
70 static struct curl_slist *default_headers;
72 static int push_verbosely = 0;
73 static int push_all = 0;
74 static int force_all = 0;
76 static struct object_list *objects = NULL;
82 struct packed_git *packs;
85 static struct repo *remote = NULL;
86 static struct remote_lock *remote_locks = NULL;
97 struct transfer_request
102 struct remote_lock *lock;
103 struct curl_slist *headers;
104 struct buffer buffer;
105 char filename[PATH_MAX];
106 char tmpfile[PATH_MAX];
107 enum transfer_state state;
108 CURLcode curl_result;
109 char errorstr[CURL_ERROR_SIZE];
111 unsigned char real_sha1[20];
116 struct active_request_slot *slot;
117 struct transfer_request *next;
120 static struct transfer_request *request_queue_head = NULL;
127 void (*userFunc)(struct xml_ctx *ctx, int tag_closed);
140 struct remote_lock *next;
150 static void finish_request(struct transfer_request *request);
152 static void process_response(void *callback_data)
154 struct transfer_request *request =
155 (struct transfer_request *)callback_data;
157 finish_request(request);
160 static void start_mkcol(struct transfer_request *request)
162 char *hex = sha1_to_hex(request->obj->sha1);
163 struct active_request_slot *slot;
166 request->url = xmalloc(strlen(remote->url) + 13);
167 strcpy(request->url, remote->url);
168 posn = request->url + strlen(remote->url);
169 strcpy(posn, "objects/");
171 memcpy(posn, hex, 2);
175 slot = get_active_slot();
176 slot->callback_func = process_response;
177 slot->callback_data = request;
178 curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); /* undo PUT setup */
179 curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
180 curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, request->errorstr);
181 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MKCOL);
182 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
184 if (start_active_slot(slot)) {
185 request->slot = slot;
186 request->state = RUN_MKCOL;
188 request->state = ABORTED;
194 static void start_put(struct transfer_request *request)
196 char *hex = sha1_to_hex(request->obj->sha1);
197 struct active_request_slot *slot;
207 unpacked = read_sha1_file(request->obj->sha1, type, &len);
208 hdrlen = sprintf(hdr, "%s %lu", type, len) + 1;
211 memset(&stream, 0, sizeof(stream));
212 deflateInit(&stream, Z_BEST_COMPRESSION);
213 size = deflateBound(&stream, len + hdrlen);
214 request->buffer.buffer = xmalloc(size);
217 stream.next_out = request->buffer.buffer;
218 stream.avail_out = size;
221 stream.next_in = (void *)hdr;
222 stream.avail_in = hdrlen;
223 while (deflate(&stream, 0) == Z_OK)
226 /* Then the data itself.. */
227 stream.next_in = unpacked;
228 stream.avail_in = len;
229 while (deflate(&stream, Z_FINISH) == Z_OK)
234 request->buffer.size = stream.total_out;
235 request->buffer.posn = 0;
237 request->url = xmalloc(strlen(remote->url) +
238 strlen(request->lock->token) + 51);
239 strcpy(request->url, remote->url);
240 posn = request->url + strlen(remote->url);
241 strcpy(posn, "objects/");
243 memcpy(posn, hex, 2);
246 strcpy(posn, hex + 2);
247 request->dest = xmalloc(strlen(request->url) + 14);
248 sprintf(request->dest, "Destination: %s", request->url);
251 strcpy(posn, request->lock->token);
253 slot = get_active_slot();
254 slot->callback_func = process_response;
255 slot->callback_data = request;
256 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &request->buffer);
257 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, request->buffer.size);
258 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
259 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
260 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
261 curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
262 curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
263 curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
264 curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
266 if (start_active_slot(slot)) {
267 request->slot = slot;
268 request->state = RUN_PUT;
270 request->state = ABORTED;
276 static void start_move(struct transfer_request *request)
278 struct active_request_slot *slot;
279 struct curl_slist *dav_headers = NULL;
281 slot = get_active_slot();
282 slot->callback_func = process_response;
283 slot->callback_data = request;
284 curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); /* undo PUT setup */
285 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MOVE);
286 dav_headers = curl_slist_append(dav_headers, request->dest);
287 dav_headers = curl_slist_append(dav_headers, "Overwrite: T");
288 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
289 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
290 curl_easy_setopt(slot->curl, CURLOPT_URL, request->url);
292 if (start_active_slot(slot)) {
293 request->slot = slot;
294 request->state = RUN_MOVE;
296 request->state = ABORTED;
302 static int refresh_lock(struct remote_lock *check_lock)
304 struct active_request_slot *slot;
305 struct slot_results results;
307 char timeout_header[25];
308 struct curl_slist *dav_headers = NULL;
309 struct remote_lock *lock;
313 /* Refresh all active locks if they're close to expiring */
314 for (lock = remote_locks; lock; lock = lock->next) {
318 current_time = time(NULL);
319 time_remaining = lock->start_time + lock->timeout
321 if (time_remaining > LOCK_REFRESH)
324 lock->refreshing = 1;
326 if_header = xmalloc(strlen(lock->token) + 25);
327 sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
328 sprintf(timeout_header, "Timeout: Second-%ld", lock->timeout);
329 dav_headers = curl_slist_append(dav_headers, if_header);
330 dav_headers = curl_slist_append(dav_headers, timeout_header);
332 slot = get_active_slot();
333 slot->results = &results;
334 curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
335 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
336 curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
337 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
338 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
340 if (start_active_slot(slot)) {
341 run_active_slot(slot);
342 if (results.curl_result != CURLE_OK) {
343 fprintf(stderr, "Got HTTP error %ld\n", results.http_code);
347 lock->start_time = time(NULL);
351 lock->refreshing = 0;
352 curl_slist_free_all(dav_headers);
357 return check_lock->active;
362 static void release_request(struct transfer_request *request)
364 struct transfer_request *entry = request_queue_head;
366 if (request == request_queue_head) {
367 request_queue_head = request->next;
369 while (entry->next != NULL && entry->next != request)
371 if (entry->next == request)
372 entry->next = entry->next->next;
375 if (request->url != NULL)
380 static void finish_request(struct transfer_request *request)
382 request->curl_result = request->slot->curl_result;
383 request->http_code = request->slot->http_code;
384 request->slot = NULL;
386 /* Keep locks active */
387 refresh_lock(request->lock);
389 if (request->headers != NULL)
390 curl_slist_free_all(request->headers);
392 /* URL is reused for MOVE after PUT */
393 if (request->state != RUN_PUT) {
398 if (request->state == RUN_MKCOL) {
399 if (request->curl_result == CURLE_OK ||
400 request->http_code == 405) {
401 remote_dir_exists[request->obj->sha1[0]] = 1;
404 fprintf(stderr, "MKCOL %s failed, aborting (%d/%ld)\n",
405 sha1_to_hex(request->obj->sha1),
406 request->curl_result, request->http_code);
407 request->state = ABORTED;
410 } else if (request->state == RUN_PUT) {
411 if (request->curl_result == CURLE_OK) {
414 fprintf(stderr, "PUT %s failed, aborting (%d/%ld)\n",
415 sha1_to_hex(request->obj->sha1),
416 request->curl_result, request->http_code);
417 request->state = ABORTED;
420 } else if (request->state == RUN_MOVE) {
421 if (request->curl_result == CURLE_OK) {
422 fprintf(stderr, " sent %s\n",
423 sha1_to_hex(request->obj->sha1));
424 request->state = COMPLETE;
425 request->obj->flags |= REMOTE;
426 release_request(request);
428 fprintf(stderr, "MOVE %s failed, aborting (%d/%ld)\n",
429 sha1_to_hex(request->obj->sha1),
430 request->curl_result, request->http_code);
431 request->state = ABORTED;
437 void fill_active_slots(void)
439 struct transfer_request *request = request_queue_head;
440 struct active_request_slot *slot = active_queue_head;
446 while (active_requests < max_requests && request != NULL) {
447 if (pushing && request->state == NEED_PUSH) {
448 if (remote_dir_exists[request->obj->sha1[0]] == 1) {
451 start_mkcol(request);
453 curl_multi_perform(curlm, &num_transfers);
455 request = request->next;
458 while (slot != NULL) {
459 if (!slot->in_use && slot->curl != NULL) {
460 curl_easy_cleanup(slot->curl);
467 static void get_remote_object_list(unsigned char parent);
469 static void add_request(struct object *obj, struct remote_lock *lock)
471 struct transfer_request *request = request_queue_head;
472 struct packed_git *target;
475 * Don't push the object if it's known to exist on the remote
476 * or is already in the request queue
478 if (remote_dir_exists[obj->sha1[0]] == -1)
479 get_remote_object_list(obj->sha1[0]);
480 if (obj->flags & (REMOTE | PUSHING))
482 target = find_sha1_pack(obj->sha1, remote->packs);
484 obj->flags |= REMOTE;
488 obj->flags |= PUSHING;
489 request = xmalloc(sizeof(*request));
492 request->lock = lock;
493 request->headers = NULL;
494 request->state = NEED_PUSH;
495 request->next = request_queue_head;
496 request_queue_head = request;
502 static int fetch_index(unsigned char *sha1)
504 char *hex = sha1_to_hex(sha1);
507 char tmpfile[PATH_MAX];
509 char range[RANGE_HEADER_SIZE];
510 struct curl_slist *range_header = NULL;
513 struct active_request_slot *slot;
514 struct slot_results results;
516 /* Don't use the index if the pack isn't there */
517 url = xmalloc(strlen(remote->url) + 65);
518 sprintf(url, "%s/objects/pack/pack-%s.pack", remote->url, hex);
519 slot = get_active_slot();
520 slot->results = &results;
521 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
522 curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
523 if (start_active_slot(slot)) {
524 run_active_slot(slot);
525 if (results.curl_result != CURLE_OK) {
527 return error("Unable to verify pack %s is available",
531 return error("Unable to start request");
534 if (has_pack_index(sha1))
538 fprintf(stderr, "Getting index for pack %s\n", hex);
540 sprintf(url, "%s/objects/pack/pack-%s.idx", remote->url, hex);
542 filename = sha1_pack_index_name(sha1);
543 snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
544 indexfile = fopen(tmpfile, "a");
546 return error("Unable to open local file %s for pack index",
549 slot = get_active_slot();
550 slot->results = &results;
551 curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
552 curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
553 curl_easy_setopt(slot->curl, CURLOPT_FILE, indexfile);
554 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
555 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
556 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
557 slot->local = indexfile;
559 /* If there is data present from a previous transfer attempt,
560 resume where it left off */
561 prev_posn = ftell(indexfile);
565 "Resuming fetch of index for pack %s at byte %ld\n",
567 sprintf(range, "Range: bytes=%ld-", prev_posn);
568 range_header = curl_slist_append(range_header, range);
569 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, range_header);
572 if (start_active_slot(slot)) {
573 run_active_slot(slot);
574 if (results.curl_result != CURLE_OK) {
577 return error("Unable to get pack index %s\n%s", url,
583 return error("Unable to start request");
589 return move_temp_to_file(tmpfile, filename);
592 static int setup_index(unsigned char *sha1)
594 struct packed_git *new_pack;
596 if (fetch_index(sha1))
599 new_pack = parse_pack_index(sha1);
600 new_pack->next = remote->packs;
601 remote->packs = new_pack;
605 static int fetch_indices(void)
607 unsigned char sha1[20];
609 struct buffer buffer;
613 struct active_request_slot *slot;
614 struct slot_results results;
616 data = xmalloc(4096);
617 memset(data, 0, 4096);
620 buffer.buffer = data;
623 fprintf(stderr, "Getting pack list\n");
625 url = xmalloc(strlen(remote->url) + 21);
626 sprintf(url, "%s/objects/info/packs", remote->url);
628 slot = get_active_slot();
629 slot->results = &results;
630 curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
631 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
632 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
633 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
634 if (start_active_slot(slot)) {
635 run_active_slot(slot);
636 if (results.curl_result != CURLE_OK) {
639 if (results.http_code == 404)
642 return error("%s", curl_errorstr);
647 return error("Unable to start request");
651 data = buffer.buffer;
652 while (i < buffer.posn) {
656 if (i + 52 < buffer.posn &&
657 !strncmp(data + i, " pack-", 6) &&
658 !strncmp(data + i + 46, ".pack\n", 6)) {
659 get_sha1_hex(data + i + 6, sha1);
665 while (data[i] != '\n')
675 static inline int needs_quote(int ch)
678 case '/': case '-': case '.':
679 case 'A'...'Z': case 'a'...'z': case '0'...'9':
686 static inline int hex(int v)
688 if (v < 10) return '0' + v;
689 else return 'A' + v - 10;
692 static char *quote_ref_url(const char *base, const char *ref)
696 int len, baselen, ch;
698 baselen = strlen(base);
700 for (cp = ref; (ch = *cp) != 0; cp++, len++)
702 len += 2; /* extra two hex plus replacement % */
704 memcpy(qref, base, baselen);
705 for (cp = ref, dp = qref + baselen; (ch = *cp) != 0; cp++) {
706 if (needs_quote(ch)) {
708 *dp++ = hex((ch >> 4) & 0xF);
709 *dp++ = hex(ch & 0xF);
719 int fetch_ref(char *ref, unsigned char *sha1)
723 struct buffer buffer;
724 char *base = remote->url;
725 struct active_request_slot *slot;
726 struct slot_results results;
732 url = quote_ref_url(base, ref);
733 slot = get_active_slot();
734 slot->results = &results;
735 curl_easy_setopt(slot->curl, CURLOPT_FILE, &buffer);
736 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
737 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, NULL);
738 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
739 if (start_active_slot(slot)) {
740 run_active_slot(slot);
741 if (results.curl_result != CURLE_OK)
742 return error("Couldn't get %s for %s\n%s",
743 url, ref, curl_errorstr);
745 return error("Unable to start request");
749 get_sha1_hex(hex, sha1);
753 static void one_remote_object(const char *hex)
755 unsigned char sha1[20];
758 if (get_sha1_hex(hex, sha1) != 0)
761 obj = lookup_object(sha1);
763 obj = parse_object(sha1);
765 /* Ignore remote objects that don't exist locally */
769 obj->flags |= REMOTE;
770 if (!object_list_contains(objects, obj))
771 add_object(obj, &objects, NULL, "");
774 static void handle_lockprop_ctx(struct xml_ctx *ctx, int tag_closed)
776 int *lock_flags = (int *)ctx->userData;
779 if (!strcmp(ctx->name, DAV_CTX_LOCKENTRY)) {
780 if ((*lock_flags & DAV_PROP_LOCKEX) &&
781 (*lock_flags & DAV_PROP_LOCKWR)) {
782 *lock_flags |= DAV_LOCK_OK;
784 *lock_flags &= DAV_LOCK_OK;
785 } else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_WRITE)) {
786 *lock_flags |= DAV_PROP_LOCKWR;
787 } else if (!strcmp(ctx->name, DAV_CTX_LOCKTYPE_EXCLUSIVE)) {
788 *lock_flags |= DAV_PROP_LOCKEX;
793 static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
795 struct remote_lock *lock = (struct remote_lock *)ctx->userData;
797 if (tag_closed && ctx->cdata) {
798 if (!strcmp(ctx->name, DAV_ACTIVELOCK_OWNER)) {
799 lock->owner = xmalloc(strlen(ctx->cdata) + 1);
800 strcpy(lock->owner, ctx->cdata);
801 } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TIMEOUT)) {
802 if (!strncmp(ctx->cdata, "Second-", 7))
804 strtol(ctx->cdata + 7, NULL, 10);
805 } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
806 if (!strncmp(ctx->cdata, "opaquelocktoken:", 16)) {
807 lock->token = xmalloc(strlen(ctx->cdata) - 15);
808 strcpy(lock->token, ctx->cdata + 16);
814 static void one_remote_ref(char *refname);
815 static void crawl_remote_refs(char *path);
817 static void handle_crawl_ref_ctx(struct xml_ctx *ctx, int tag_closed)
819 struct remote_dentry *dentry = (struct remote_dentry *)ctx->userData;
823 if (!strcmp(ctx->name, DAV_PROPFIND_RESP) && dentry->name) {
824 if (dentry->is_dir) {
825 if (strcmp(dentry->name, dentry->base)) {
826 crawl_remote_refs(dentry->name);
829 one_remote_ref(dentry->name);
831 } else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
832 dentry->name = xmalloc(strlen(ctx->cdata) -
833 remote->path_len + 1);
835 ctx->cdata + remote->path_len);
836 } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
839 } else if (!strcmp(ctx->name, DAV_PROPFIND_RESP)) {
845 static void handle_remote_object_list_ctx(struct xml_ctx *ctx, int tag_closed)
851 if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
852 path = ctx->cdata + remote->path_len;
853 if (strlen(path) != 50)
856 obj_hex = xmalloc(strlen(path));
857 strncpy(obj_hex, path, 2);
858 strcpy(obj_hex + 2, path + 3);
859 one_remote_object(obj_hex);
866 xml_start_tag(void *userData, const char *name, const char **atts)
868 struct xml_ctx *ctx = (struct xml_ctx *)userData;
869 const char *c = index(name, ':');
877 new_len = strlen(ctx->name) + strlen(c) + 2;
879 if (new_len > ctx->len) {
880 ctx->name = xrealloc(ctx->name, new_len);
883 strcat(ctx->name, ".");
884 strcat(ctx->name, c);
891 ctx->userFunc(ctx, 0);
895 xml_end_tag(void *userData, const char *name)
897 struct xml_ctx *ctx = (struct xml_ctx *)userData;
898 const char *c = index(name, ':');
901 ctx->userFunc(ctx, 1);
908 ep = ctx->name + strlen(ctx->name) - strlen(c) - 1;
913 xml_cdata(void *userData, const XML_Char *s, int len)
915 struct xml_ctx *ctx = (struct xml_ctx *)userData;
918 ctx->cdata = xcalloc(len+1, 1);
919 strncpy(ctx->cdata, s, len);
922 static struct remote_lock *lock_remote(char *path, long timeout)
924 struct active_request_slot *slot;
925 struct slot_results results;
926 struct buffer out_buffer;
927 struct buffer in_buffer;
932 char timeout_header[25];
933 struct remote_lock *lock = remote_locks;
934 XML_Parser parser = XML_ParserCreate(NULL);
935 enum XML_Status result;
936 struct curl_slist *dav_headers = NULL;
939 url = xmalloc(strlen(remote->url) + strlen(path) + 1);
940 sprintf(url, "%s%s", remote->url, path);
942 /* Make sure the url is not already locked */
943 while (lock && strcmp(lock->url, url)) {
948 if (refresh_lock(lock))
954 /* Make sure leading directories exist for the remote ref */
955 ep = strchr(url + strlen(remote->url) + 11, '/');
958 slot = get_active_slot();
959 slot->results = &results;
960 curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
961 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
962 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_MKCOL);
963 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
964 if (start_active_slot(slot)) {
965 run_active_slot(slot);
966 if (results.curl_result != CURLE_OK &&
967 results.http_code != 405) {
969 "Unable to create branch path %s\n",
975 fprintf(stderr, "Unable to start request\n");
980 ep = strchr(ep + 1, '/');
983 out_buffer.size = strlen(LOCK_REQUEST) + strlen(git_default_email) - 2;
984 out_data = xmalloc(out_buffer.size + 1);
985 snprintf(out_data, out_buffer.size + 1, LOCK_REQUEST, git_default_email);
987 out_buffer.buffer = out_data;
989 in_buffer.size = 4096;
990 in_data = xmalloc(in_buffer.size);
992 in_buffer.buffer = in_data;
994 sprintf(timeout_header, "Timeout: Second-%ld", timeout);
995 dav_headers = curl_slist_append(dav_headers, timeout_header);
996 dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
998 slot = get_active_slot();
999 slot->results = &results;
1000 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1001 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1002 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1003 curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1004 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1005 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1006 curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1007 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
1008 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1010 lock = xcalloc(1, sizeof(*lock));
1014 lock->refreshing = 0;
1016 if (start_active_slot(slot)) {
1017 run_active_slot(slot);
1018 if (results.curl_result == CURLE_OK) {
1019 ctx.name = xcalloc(10, 1);
1022 ctx.userFunc = handle_new_lock_ctx;
1023 ctx.userData = lock;
1024 XML_SetUserData(parser, &ctx);
1025 XML_SetElementHandler(parser, xml_start_tag,
1027 XML_SetCharacterDataHandler(parser, xml_cdata);
1028 result = XML_Parse(parser, in_buffer.buffer,
1031 if (result != XML_STATUS_OK) {
1032 fprintf(stderr, "XML error: %s\n",
1034 XML_GetErrorCode(parser)));
1039 fprintf(stderr, "Unable to start request\n");
1042 curl_slist_free_all(dav_headers);
1046 if (lock->token == NULL || lock->timeout <= 0) {
1047 if (lock->token != NULL)
1049 if (lock->owner != NULL)
1057 lock->start_time = time(NULL);
1058 lock->next = remote_locks;
1059 remote_locks = lock;
1065 static int unlock_remote(struct remote_lock *lock)
1067 struct active_request_slot *slot;
1068 struct slot_results results;
1069 char *lock_token_header;
1070 struct curl_slist *dav_headers = NULL;
1073 lock_token_header = xmalloc(strlen(lock->token) + 31);
1074 sprintf(lock_token_header, "Lock-Token: <opaquelocktoken:%s>",
1076 dav_headers = curl_slist_append(dav_headers, lock_token_header);
1078 slot = get_active_slot();
1079 slot->results = &results;
1080 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
1081 curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
1082 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_UNLOCK);
1083 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1085 if (start_active_slot(slot)) {
1086 run_active_slot(slot);
1087 if (results.curl_result == CURLE_OK)
1090 fprintf(stderr, "Got HTTP error %ld\n",
1093 fprintf(stderr, "Unable to start request\n");
1096 curl_slist_free_all(dav_headers);
1097 free(lock_token_header);
1104 static void crawl_remote_refs(char *path)
1107 struct active_request_slot *slot;
1108 struct slot_results results;
1109 struct buffer in_buffer;
1110 struct buffer out_buffer;
1113 XML_Parser parser = XML_ParserCreate(NULL);
1114 enum XML_Status result;
1115 struct curl_slist *dav_headers = NULL;
1117 struct remote_dentry dentry;
1119 fprintf(stderr, " %s\n", path);
1125 url = xmalloc(strlen(remote->url) + strlen(path) + 1);
1126 sprintf(url, "%s%s", remote->url, path);
1128 out_buffer.size = strlen(PROPFIND_ALL_REQUEST);
1129 out_data = xmalloc(out_buffer.size + 1);
1130 snprintf(out_data, out_buffer.size + 1, PROPFIND_ALL_REQUEST);
1131 out_buffer.posn = 0;
1132 out_buffer.buffer = out_data;
1134 in_buffer.size = 4096;
1135 in_data = xmalloc(in_buffer.size);
1137 in_buffer.buffer = in_data;
1139 dav_headers = curl_slist_append(dav_headers, "Depth: 1");
1140 dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1142 slot = get_active_slot();
1143 slot->results = &results;
1144 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1145 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1146 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1147 curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1148 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1149 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1150 curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1151 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
1152 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1154 if (start_active_slot(slot)) {
1155 run_active_slot(slot);
1156 if (results.curl_result == CURLE_OK) {
1157 ctx.name = xcalloc(10, 1);
1160 ctx.userFunc = handle_crawl_ref_ctx;
1161 ctx.userData = &dentry;
1162 XML_SetUserData(parser, &ctx);
1163 XML_SetElementHandler(parser, xml_start_tag,
1165 XML_SetCharacterDataHandler(parser, xml_cdata);
1166 result = XML_Parse(parser, in_buffer.buffer,
1170 if (result != XML_STATUS_OK) {
1171 fprintf(stderr, "XML error: %s\n",
1173 XML_GetErrorCode(parser)));
1177 fprintf(stderr, "Unable to start request\n");
1182 free(in_buffer.buffer);
1183 curl_slist_free_all(dav_headers);
1186 static void get_remote_object_list(unsigned char parent)
1189 struct active_request_slot *slot;
1190 struct slot_results results;
1191 struct buffer in_buffer;
1192 struct buffer out_buffer;
1195 XML_Parser parser = XML_ParserCreate(NULL);
1196 enum XML_Status result;
1197 struct curl_slist *dav_headers = NULL;
1199 char path[] = "/objects/XX/";
1200 static const char hex[] = "0123456789abcdef";
1201 unsigned int val = parent;
1203 path[9] = hex[val >> 4];
1204 path[10] = hex[val & 0xf];
1205 url = xmalloc(strlen(remote->url) + strlen(path) + 1);
1206 sprintf(url, "%s%s", remote->url, path);
1208 out_buffer.size = strlen(PROPFIND_ALL_REQUEST);
1209 out_data = xmalloc(out_buffer.size + 1);
1210 snprintf(out_data, out_buffer.size + 1, PROPFIND_ALL_REQUEST);
1211 out_buffer.posn = 0;
1212 out_buffer.buffer = out_data;
1214 in_buffer.size = 4096;
1215 in_data = xmalloc(in_buffer.size);
1217 in_buffer.buffer = in_data;
1219 dav_headers = curl_slist_append(dav_headers, "Depth: 1");
1220 dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1222 slot = get_active_slot();
1223 slot->results = &results;
1224 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1225 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1226 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1227 curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1228 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1229 curl_easy_setopt(slot->curl, CURLOPT_URL, url);
1230 curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1231 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
1232 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1234 if (start_active_slot(slot)) {
1235 run_active_slot(slot);
1236 if (results.curl_result == CURLE_OK) {
1237 remote_dir_exists[parent] = 1;
1238 ctx.name = xcalloc(10, 1);
1241 ctx.userFunc = handle_remote_object_list_ctx;
1242 XML_SetUserData(parser, &ctx);
1243 XML_SetElementHandler(parser, xml_start_tag,
1245 XML_SetCharacterDataHandler(parser, xml_cdata);
1246 result = XML_Parse(parser, in_buffer.buffer,
1250 if (result != XML_STATUS_OK) {
1251 fprintf(stderr, "XML error: %s\n",
1253 XML_GetErrorCode(parser)));
1256 remote_dir_exists[parent] = 0;
1259 fprintf(stderr, "Unable to start request\n");
1264 free(in_buffer.buffer);
1265 curl_slist_free_all(dav_headers);
1268 static int locking_available(void)
1270 struct active_request_slot *slot;
1271 struct slot_results results;
1272 struct buffer in_buffer;
1273 struct buffer out_buffer;
1276 XML_Parser parser = XML_ParserCreate(NULL);
1277 enum XML_Status result;
1278 struct curl_slist *dav_headers = NULL;
1283 strlen(PROPFIND_SUPPORTEDLOCK_REQUEST) +
1284 strlen(remote->url) - 2;
1285 out_data = xmalloc(out_buffer.size + 1);
1286 snprintf(out_data, out_buffer.size + 1,
1287 PROPFIND_SUPPORTEDLOCK_REQUEST, remote->url);
1288 out_buffer.posn = 0;
1289 out_buffer.buffer = out_data;
1291 in_buffer.size = 4096;
1292 in_data = xmalloc(in_buffer.size);
1294 in_buffer.buffer = in_data;
1296 dav_headers = curl_slist_append(dav_headers, "Depth: 0");
1297 dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
1299 slot = get_active_slot();
1300 slot->results = &results;
1301 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1302 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1303 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1304 curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
1305 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
1306 curl_easy_setopt(slot->curl, CURLOPT_URL, remote->url);
1307 curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1308 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PROPFIND);
1309 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1311 if (start_active_slot(slot)) {
1312 run_active_slot(slot);
1313 if (results.curl_result == CURLE_OK) {
1314 ctx.name = xcalloc(10, 1);
1317 ctx.userFunc = handle_lockprop_ctx;
1318 ctx.userData = &lock_flags;
1319 XML_SetUserData(parser, &ctx);
1320 XML_SetElementHandler(parser, xml_start_tag,
1322 result = XML_Parse(parser, in_buffer.buffer,
1326 if (result != XML_STATUS_OK) {
1327 fprintf(stderr, "XML error: %s\n",
1329 XML_GetErrorCode(parser)));
1334 fprintf(stderr, "Unable to start request\n");
1338 free(in_buffer.buffer);
1339 curl_slist_free_all(dav_headers);
1344 static struct object_list **process_blob(struct blob *blob,
1345 struct object_list **p,
1346 struct name_path *path,
1349 struct object *obj = &blob->object;
1351 obj->flags |= LOCAL;
1353 if (obj->flags & (UNINTERESTING | SEEN))
1357 return add_object(obj, p, path, name);
1360 static struct object_list **process_tree(struct tree *tree,
1361 struct object_list **p,
1362 struct name_path *path,
1365 struct object *obj = &tree->object;
1366 struct tree_entry_list *entry;
1367 struct name_path me;
1369 obj->flags |= LOCAL;
1371 if (obj->flags & (UNINTERESTING | SEEN))
1373 if (parse_tree(tree) < 0)
1374 die("bad tree object %s", sha1_to_hex(obj->sha1));
1377 p = add_object(obj, p, NULL, name);
1380 me.elem_len = strlen(name);
1381 entry = tree->entries;
1382 tree->entries = NULL;
1384 struct tree_entry_list *next = entry->next;
1385 if (entry->directory)
1386 p = process_tree(entry->item.tree, p, &me, entry->name);
1388 p = process_blob(entry->item.blob, p, &me, entry->name);
1395 static void get_delta(struct rev_info *revs, struct remote_lock *lock)
1397 struct commit *commit;
1398 struct object_list **p = &objects, *pending;
1400 while ((commit = get_revision(revs)) != NULL) {
1401 p = process_tree(commit->tree, p, NULL, "");
1402 commit->object.flags |= LOCAL;
1403 if (!(commit->object.flags & UNINTERESTING))
1404 add_request(&commit->object, lock);
1407 for (pending = revs->pending_objects; pending; pending = pending->next) {
1408 struct object *obj = pending->item;
1409 const char *name = pending->name;
1411 if (obj->flags & (UNINTERESTING | SEEN))
1413 if (obj->type == tag_type) {
1415 p = add_object(obj, p, NULL, name);
1418 if (obj->type == tree_type) {
1419 p = process_tree((struct tree *)obj, p, NULL, name);
1422 if (obj->type == blob_type) {
1423 p = process_blob((struct blob *)obj, p, NULL, name);
1426 die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
1430 if (!(objects->item->flags & UNINTERESTING))
1431 add_request(objects->item, lock);
1432 objects = objects->next;
1436 static int update_remote(unsigned char *sha1, struct remote_lock *lock)
1438 struct active_request_slot *slot;
1439 struct slot_results results;
1442 struct buffer out_buffer;
1443 struct curl_slist *dav_headers = NULL;
1446 if_header = xmalloc(strlen(lock->token) + 25);
1447 sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
1448 dav_headers = curl_slist_append(dav_headers, if_header);
1450 out_buffer.size = 41;
1451 out_data = xmalloc(out_buffer.size + 1);
1452 i = snprintf(out_data, out_buffer.size + 1, "%s\n", sha1_to_hex(sha1));
1453 if (i != out_buffer.size) {
1454 fprintf(stderr, "Unable to initialize PUT request body\n");
1457 out_buffer.posn = 0;
1458 out_buffer.buffer = out_data;
1460 slot = get_active_slot();
1461 slot->results = &results;
1462 curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
1463 curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.size);
1464 curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1465 curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
1466 curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
1467 curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
1468 curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
1469 curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
1470 curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
1472 if (start_active_slot(slot)) {
1473 run_active_slot(slot);
1476 if (results.curl_result != CURLE_OK) {
1478 "PUT error: curl result=%d, HTTP code=%ld\n",
1479 results.curl_result, results.http_code);
1480 /* We should attempt recovery? */
1486 fprintf(stderr, "Unable to start PUT request\n");
1493 static struct ref *local_refs, **local_tail;
1494 static struct ref *remote_refs, **remote_tail;
1496 static int one_local_ref(const char *refname, const unsigned char *sha1)
1499 int len = strlen(refname) + 1;
1500 ref = xcalloc(1, sizeof(*ref) + len);
1501 memcpy(ref->new_sha1, sha1, 20);
1502 memcpy(ref->name, refname, len);
1504 local_tail = &ref->next;
1508 static void one_remote_ref(char *refname)
1511 unsigned char remote_sha1[20];
1513 if (fetch_ref(refname, remote_sha1) != 0) {
1515 "Unable to fetch ref %s from %s\n",
1516 refname, remote->url);
1520 int len = strlen(refname) + 1;
1521 ref = xcalloc(1, sizeof(*ref) + len);
1522 memcpy(ref->old_sha1, remote_sha1, 20);
1523 memcpy(ref->name, refname, len);
1525 remote_tail = &ref->next;
1528 static void get_local_heads(void)
1530 local_tail = &local_refs;
1531 for_each_ref(one_local_ref);
1534 static void get_dav_remote_heads(void)
1536 remote_tail = &remote_refs;
1537 crawl_remote_refs("refs/");
1540 static int is_zero_sha1(const unsigned char *sha1)
1544 for (i = 0; i < 20; i++) {
1551 static void unmark_and_free(struct commit_list *list, unsigned int mark)
1554 struct commit_list *temp = list;
1555 temp->item->object.flags &= ~mark;
1561 static int ref_newer(const unsigned char *new_sha1,
1562 const unsigned char *old_sha1)
1565 struct commit *old, *new;
1566 struct commit_list *list, *used;
1569 /* Both new and old must be commit-ish and new is descendant of
1570 * old. Otherwise we require --force.
1572 o = deref_tag(parse_object(old_sha1), NULL, 0);
1573 if (!o || o->type != commit_type)
1575 old = (struct commit *) o;
1577 o = deref_tag(parse_object(new_sha1), NULL, 0);
1578 if (!o || o->type != commit_type)
1580 new = (struct commit *) o;
1582 if (parse_commit(new) < 0)
1586 commit_list_insert(new, &list);
1588 new = pop_most_recent_commit(&list, TMP_MARK);
1589 commit_list_insert(new, &used);
1595 unmark_and_free(list, TMP_MARK);
1596 unmark_and_free(used, TMP_MARK);
1600 static void mark_edge_parents_uninteresting(struct commit *commit)
1602 struct commit_list *parents;
1604 for (parents = commit->parents; parents; parents = parents->next) {
1605 struct commit *parent = parents->item;
1606 if (!(parent->object.flags & UNINTERESTING))
1608 mark_tree_uninteresting(parent->tree);
1612 static void mark_edges_uninteresting(struct commit_list *list)
1614 for ( ; list; list = list->next) {
1615 struct commit *commit = list->item;
1617 if (commit->object.flags & UNINTERESTING) {
1618 mark_tree_uninteresting(commit->tree);
1621 mark_edge_parents_uninteresting(commit);
1625 int main(int argc, char **argv)
1627 struct transfer_request *request;
1628 struct transfer_request *next_request;
1630 char **refspec = NULL;
1631 struct remote_lock *ref_lock;
1632 struct rev_info revs;
1636 setup_git_directory();
1639 remote = xmalloc(sizeof(*remote));
1641 remote->path_len = 0;
1642 remote->packs = NULL;
1645 for (i = 1; i < argc; i++, argv++) {
1649 if (!strcmp(arg, "--all")) {
1653 if (!strcmp(arg, "--force")) {
1657 if (!strcmp(arg, "--verbose")) {
1661 usage(http_push_usage);
1665 char *path = strstr(arg, "//");
1667 path = index(path+2, '/');
1669 remote->path_len = strlen(path);
1674 nr_refspec = argc - i;
1679 usage(http_push_usage);
1681 memset(remote_dir_exists, -1, 256);
1685 no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
1686 default_headers = curl_slist_append(default_headers, "Range:");
1687 default_headers = curl_slist_append(default_headers, "Destination:");
1688 default_headers = curl_slist_append(default_headers, "If:");
1689 default_headers = curl_slist_append(default_headers,
1690 "Pragma: no-cache");
1692 /* Verify DAV compliance/lock support */
1693 if (!locking_available()) {
1694 fprintf(stderr, "Error: no DAV locking support on remote repo %s\n", remote->url);
1699 /* Get a list of all local and remote heads to validate refspecs */
1701 fprintf(stderr, "Fetching remote heads...\n");
1702 get_dav_remote_heads();
1706 remote_tail = &remote_refs;
1707 if (match_refs(local_refs, remote_refs, &remote_tail,
1708 nr_refspec, refspec, push_all))
1711 fprintf(stderr, "No refs in common and none specified; doing nothing.\n");
1718 for (ref = remote_refs; ref; ref = ref->next) {
1719 char old_hex[60], *new_hex;
1722 if (!memcmp(ref->old_sha1, ref->peer_ref->new_sha1, 20)) {
1723 if (push_verbosely || 1)
1724 fprintf(stderr, "'%s': up-to-date\n", ref->name);
1729 !is_zero_sha1(ref->old_sha1) &&
1731 if (!has_sha1_file(ref->old_sha1) ||
1732 !ref_newer(ref->peer_ref->new_sha1,
1734 /* We do not have the remote ref, or
1735 * we know that the remote ref is not
1736 * an ancestor of what we are trying to
1737 * push. Either way this can be losing
1738 * commits at the remote end and likely
1739 * we were not up to date to begin with.
1741 error("remote '%s' is not a strict "
1742 "subset of local ref '%s'. "
1743 "maybe you are not up-to-date and "
1744 "need to pull first?",
1746 ref->peer_ref->name);
1751 memcpy(ref->new_sha1, ref->peer_ref->new_sha1, 20);
1752 if (is_zero_sha1(ref->new_sha1)) {
1753 error("cannot happen anymore");
1758 strcpy(old_hex, sha1_to_hex(ref->old_sha1));
1759 new_hex = sha1_to_hex(ref->new_sha1);
1761 fprintf(stderr, "updating '%s'", ref->name);
1762 if (strcmp(ref->name, ref->peer_ref->name))
1763 fprintf(stderr, " using '%s'", ref->peer_ref->name);
1764 fprintf(stderr, "\n from %s\n to %s\n", old_hex, new_hex);
1767 /* Lock remote branch ref */
1768 ref_lock = lock_remote(ref->name, LOCK_TIME);
1769 if (ref_lock == NULL) {
1770 fprintf(stderr, "Unable to lock remote branch %s\n",
1776 /* Set up revision info for this refspec */
1777 const char *commit_argv[4];
1778 int commit_argc = 3;
1779 char *new_sha1_hex = strdup(sha1_to_hex(ref->new_sha1));
1780 char *old_sha1_hex = NULL;
1781 commit_argv[1] = "--objects";
1782 commit_argv[2] = new_sha1_hex;
1783 if (!push_all && !is_zero_sha1(ref->old_sha1)) {
1784 old_sha1_hex = xmalloc(42);
1785 sprintf(old_sha1_hex, "^%s",
1786 sha1_to_hex(ref->old_sha1));
1787 commit_argv[3] = old_sha1_hex;
1790 setup_revisions(commit_argc, commit_argv, &revs, NULL);
1794 commit_argv[1] = NULL;
1797 /* Generate a list of objects that need to be pushed */
1799 prepare_revision_walk(&revs);
1800 mark_edges_uninteresting(revs.commits);
1802 get_delta(&revs, ref_lock);
1803 finish_all_active_slots();
1805 /* Push missing objects to remote, this would be a
1806 convenient time to pack them first if appropriate. */
1808 fill_active_slots();
1809 finish_all_active_slots();
1811 /* Update the remote branch if all went well */
1812 if (aborted || !update_remote(ref->new_sha1, ref_lock)) {
1819 fprintf(stderr, " done\n");
1820 unlock_remote(ref_lock);
1826 curl_slist_free_all(no_pragma_header);
1827 curl_slist_free_all(default_headers);
1831 request = request_queue_head;
1832 while (request != NULL) {
1833 next_request = request->next;
1834 release_request(request);
1835 request = next_request;