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
;
143 /* Flags that control remote_ls processing */
144 #define PROCESS_FILES (1u << 0)
145 #define PROCESS_DIRS (1u << 1)
146 #define RECURSIVE (1u << 2)
148 /* Flags that remote_ls passes to callback functions */
149 #define IS_DIR (1u << 0)
154 void (*userFunc
)(struct remote_ls_ctx
*ls
);
159 struct remote_ls_ctx
*parent
;
162 static void finish_request(struct transfer_request
*request
);
164 static void process_response(void *callback_data
)
166 struct transfer_request
*request
=
167 (struct transfer_request
*)callback_data
;
169 finish_request(request
);
172 static void start_mkcol(struct transfer_request
*request
)
174 char *hex
= sha1_to_hex(request
->obj
->sha1
);
175 struct active_request_slot
*slot
;
178 request
->url
= xmalloc(strlen(remote
->url
) + 13);
179 strcpy(request
->url
, remote
->url
);
180 posn
= request
->url
+ strlen(remote
->url
);
181 strcpy(posn
, "objects/");
183 memcpy(posn
, hex
, 2);
187 slot
= get_active_slot();
188 slot
->callback_func
= process_response
;
189 slot
->callback_data
= request
;
190 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPGET
, 1); /* undo PUT setup */
191 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, request
->url
);
192 curl_easy_setopt(slot
->curl
, CURLOPT_ERRORBUFFER
, request
->errorstr
);
193 curl_easy_setopt(slot
->curl
, CURLOPT_CUSTOMREQUEST
, DAV_MKCOL
);
194 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_null
);
196 if (start_active_slot(slot
)) {
197 request
->slot
= slot
;
198 request
->state
= RUN_MKCOL
;
200 request
->state
= ABORTED
;
206 static void start_put(struct transfer_request
*request
)
208 char *hex
= sha1_to_hex(request
->obj
->sha1
);
209 struct active_request_slot
*slot
;
219 unpacked
= read_sha1_file(request
->obj
->sha1
, type
, &len
);
220 hdrlen
= sprintf(hdr
, "%s %lu", type
, len
) + 1;
223 memset(&stream
, 0, sizeof(stream
));
224 deflateInit(&stream
, Z_BEST_COMPRESSION
);
225 size
= deflateBound(&stream
, len
+ hdrlen
);
226 request
->buffer
.buffer
= xmalloc(size
);
229 stream
.next_out
= request
->buffer
.buffer
;
230 stream
.avail_out
= size
;
233 stream
.next_in
= (void *)hdr
;
234 stream
.avail_in
= hdrlen
;
235 while (deflate(&stream
, 0) == Z_OK
)
238 /* Then the data itself.. */
239 stream
.next_in
= unpacked
;
240 stream
.avail_in
= len
;
241 while (deflate(&stream
, Z_FINISH
) == Z_OK
)
246 request
->buffer
.size
= stream
.total_out
;
247 request
->buffer
.posn
= 0;
249 request
->url
= xmalloc(strlen(remote
->url
) +
250 strlen(request
->lock
->token
) + 51);
251 strcpy(request
->url
, remote
->url
);
252 posn
= request
->url
+ strlen(remote
->url
);
253 strcpy(posn
, "objects/");
255 memcpy(posn
, hex
, 2);
258 strcpy(posn
, hex
+ 2);
259 request
->dest
= xmalloc(strlen(request
->url
) + 14);
260 sprintf(request
->dest
, "Destination: %s", request
->url
);
263 strcpy(posn
, request
->lock
->token
);
265 slot
= get_active_slot();
266 slot
->callback_func
= process_response
;
267 slot
->callback_data
= request
;
268 curl_easy_setopt(slot
->curl
, CURLOPT_INFILE
, &request
->buffer
);
269 curl_easy_setopt(slot
->curl
, CURLOPT_INFILESIZE
, request
->buffer
.size
);
270 curl_easy_setopt(slot
->curl
, CURLOPT_READFUNCTION
, fread_buffer
);
271 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_null
);
272 curl_easy_setopt(slot
->curl
, CURLOPT_CUSTOMREQUEST
, DAV_PUT
);
273 curl_easy_setopt(slot
->curl
, CURLOPT_UPLOAD
, 1);
274 curl_easy_setopt(slot
->curl
, CURLOPT_PUT
, 1);
275 curl_easy_setopt(slot
->curl
, CURLOPT_NOBODY
, 0);
276 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, request
->url
);
278 if (start_active_slot(slot
)) {
279 request
->slot
= slot
;
280 request
->state
= RUN_PUT
;
282 request
->state
= ABORTED
;
288 static void start_move(struct transfer_request
*request
)
290 struct active_request_slot
*slot
;
291 struct curl_slist
*dav_headers
= NULL
;
293 slot
= get_active_slot();
294 slot
->callback_func
= process_response
;
295 slot
->callback_data
= request
;
296 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPGET
, 1); /* undo PUT setup */
297 curl_easy_setopt(slot
->curl
, CURLOPT_CUSTOMREQUEST
, DAV_MOVE
);
298 dav_headers
= curl_slist_append(dav_headers
, request
->dest
);
299 dav_headers
= curl_slist_append(dav_headers
, "Overwrite: T");
300 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPHEADER
, dav_headers
);
301 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_null
);
302 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, request
->url
);
304 if (start_active_slot(slot
)) {
305 request
->slot
= slot
;
306 request
->state
= RUN_MOVE
;
308 request
->state
= ABORTED
;
314 static int refresh_lock(struct remote_lock
*check_lock
)
316 struct active_request_slot
*slot
;
317 struct slot_results results
;
319 char timeout_header
[25];
320 struct curl_slist
*dav_headers
= NULL
;
321 struct remote_lock
*lock
;
325 /* Refresh all active locks if they're close to expiring */
326 for (lock
= remote_locks
; lock
; lock
= lock
->next
) {
330 current_time
= time(NULL
);
331 time_remaining
= lock
->start_time
+ lock
->timeout
333 if (time_remaining
> LOCK_REFRESH
)
336 lock
->refreshing
= 1;
338 if_header
= xmalloc(strlen(lock
->token
) + 25);
339 sprintf(if_header
, "If: (<opaquelocktoken:%s>)", lock
->token
);
340 sprintf(timeout_header
, "Timeout: Second-%ld", lock
->timeout
);
341 dav_headers
= curl_slist_append(dav_headers
, if_header
);
342 dav_headers
= curl_slist_append(dav_headers
, timeout_header
);
344 slot
= get_active_slot();
345 slot
->results
= &results
;
346 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPGET
, 1);
347 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_null
);
348 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, lock
->url
);
349 curl_easy_setopt(slot
->curl
, CURLOPT_CUSTOMREQUEST
, DAV_LOCK
);
350 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPHEADER
, dav_headers
);
352 if (start_active_slot(slot
)) {
353 run_active_slot(slot
);
354 if (results
.curl_result
!= CURLE_OK
) {
355 fprintf(stderr
, "Got HTTP error %ld\n", results
.http_code
);
359 lock
->start_time
= time(NULL
);
363 lock
->refreshing
= 0;
364 curl_slist_free_all(dav_headers
);
369 return check_lock
->active
;
374 static void release_request(struct transfer_request
*request
)
376 struct transfer_request
*entry
= request_queue_head
;
378 if (request
== request_queue_head
) {
379 request_queue_head
= request
->next
;
381 while (entry
->next
!= NULL
&& entry
->next
!= request
)
383 if (entry
->next
== request
)
384 entry
->next
= entry
->next
->next
;
387 if (request
->url
!= NULL
)
392 static void finish_request(struct transfer_request
*request
)
394 request
->curl_result
= request
->slot
->curl_result
;
395 request
->http_code
= request
->slot
->http_code
;
396 request
->slot
= NULL
;
398 /* Keep locks active */
399 refresh_lock(request
->lock
);
401 if (request
->headers
!= NULL
)
402 curl_slist_free_all(request
->headers
);
404 /* URL is reused for MOVE after PUT */
405 if (request
->state
!= RUN_PUT
) {
410 if (request
->state
== RUN_MKCOL
) {
411 if (request
->curl_result
== CURLE_OK
||
412 request
->http_code
== 405) {
413 remote_dir_exists
[request
->obj
->sha1
[0]] = 1;
416 fprintf(stderr
, "MKCOL %s failed, aborting (%d/%ld)\n",
417 sha1_to_hex(request
->obj
->sha1
),
418 request
->curl_result
, request
->http_code
);
419 request
->state
= ABORTED
;
422 } else if (request
->state
== RUN_PUT
) {
423 if (request
->curl_result
== CURLE_OK
) {
426 fprintf(stderr
, "PUT %s failed, aborting (%d/%ld)\n",
427 sha1_to_hex(request
->obj
->sha1
),
428 request
->curl_result
, request
->http_code
);
429 request
->state
= ABORTED
;
432 } else if (request
->state
== RUN_MOVE
) {
433 if (request
->curl_result
== CURLE_OK
) {
434 fprintf(stderr
, " sent %s\n",
435 sha1_to_hex(request
->obj
->sha1
));
436 request
->state
= COMPLETE
;
437 request
->obj
->flags
|= REMOTE
;
438 release_request(request
);
440 fprintf(stderr
, "MOVE %s failed, aborting (%d/%ld)\n",
441 sha1_to_hex(request
->obj
->sha1
),
442 request
->curl_result
, request
->http_code
);
443 request
->state
= ABORTED
;
449 void fill_active_slots(void)
451 struct transfer_request
*request
= request_queue_head
;
452 struct active_request_slot
*slot
= active_queue_head
;
458 while (active_requests
< max_requests
&& request
!= NULL
) {
459 if (pushing
&& request
->state
== NEED_PUSH
) {
460 if (remote_dir_exists
[request
->obj
->sha1
[0]] == 1) {
463 start_mkcol(request
);
465 curl_multi_perform(curlm
, &num_transfers
);
467 request
= request
->next
;
470 while (slot
!= NULL
) {
471 if (!slot
->in_use
&& slot
->curl
!= NULL
) {
472 curl_easy_cleanup(slot
->curl
);
479 static void get_remote_object_list(unsigned char parent
);
481 static void add_request(struct object
*obj
, struct remote_lock
*lock
)
483 struct transfer_request
*request
= request_queue_head
;
484 struct packed_git
*target
;
487 * Don't push the object if it's known to exist on the remote
488 * or is already in the request queue
490 if (remote_dir_exists
[obj
->sha1
[0]] == -1)
491 get_remote_object_list(obj
->sha1
[0]);
492 if (obj
->flags
& (REMOTE
| PUSHING
))
494 target
= find_sha1_pack(obj
->sha1
, remote
->packs
);
496 obj
->flags
|= REMOTE
;
500 obj
->flags
|= PUSHING
;
501 request
= xmalloc(sizeof(*request
));
504 request
->lock
= lock
;
505 request
->headers
= NULL
;
506 request
->state
= NEED_PUSH
;
507 request
->next
= request_queue_head
;
508 request_queue_head
= request
;
514 static int fetch_index(unsigned char *sha1
)
516 char *hex
= sha1_to_hex(sha1
);
519 char tmpfile
[PATH_MAX
];
521 char range
[RANGE_HEADER_SIZE
];
522 struct curl_slist
*range_header
= NULL
;
525 struct active_request_slot
*slot
;
526 struct slot_results results
;
528 /* Don't use the index if the pack isn't there */
529 url
= xmalloc(strlen(remote
->url
) + 65);
530 sprintf(url
, "%s/objects/pack/pack-%s.pack", remote
->url
, hex
);
531 slot
= get_active_slot();
532 slot
->results
= &results
;
533 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, url
);
534 curl_easy_setopt(slot
->curl
, CURLOPT_NOBODY
, 1);
535 if (start_active_slot(slot
)) {
536 run_active_slot(slot
);
537 if (results
.curl_result
!= CURLE_OK
) {
539 return error("Unable to verify pack %s is available",
543 return error("Unable to start request");
546 if (has_pack_index(sha1
))
550 fprintf(stderr
, "Getting index for pack %s\n", hex
);
552 sprintf(url
, "%s/objects/pack/pack-%s.idx", remote
->url
, hex
);
554 filename
= sha1_pack_index_name(sha1
);
555 snprintf(tmpfile
, sizeof(tmpfile
), "%s.temp", filename
);
556 indexfile
= fopen(tmpfile
, "a");
558 return error("Unable to open local file %s for pack index",
561 slot
= get_active_slot();
562 slot
->results
= &results
;
563 curl_easy_setopt(slot
->curl
, CURLOPT_NOBODY
, 0);
564 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPGET
, 1);
565 curl_easy_setopt(slot
->curl
, CURLOPT_FILE
, indexfile
);
566 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite
);
567 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, url
);
568 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPHEADER
, no_pragma_header
);
569 slot
->local
= indexfile
;
571 /* If there is data present from a previous transfer attempt,
572 resume where it left off */
573 prev_posn
= ftell(indexfile
);
577 "Resuming fetch of index for pack %s at byte %ld\n",
579 sprintf(range
, "Range: bytes=%ld-", prev_posn
);
580 range_header
= curl_slist_append(range_header
, range
);
581 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPHEADER
, range_header
);
584 if (start_active_slot(slot
)) {
585 run_active_slot(slot
);
586 if (results
.curl_result
!= CURLE_OK
) {
589 return error("Unable to get pack index %s\n%s", url
,
595 return error("Unable to start request");
601 return move_temp_to_file(tmpfile
, filename
);
604 static int setup_index(unsigned char *sha1
)
606 struct packed_git
*new_pack
;
608 if (fetch_index(sha1
))
611 new_pack
= parse_pack_index(sha1
);
612 new_pack
->next
= remote
->packs
;
613 remote
->packs
= new_pack
;
617 static int fetch_indices(void)
619 unsigned char sha1
[20];
621 struct buffer buffer
;
625 struct active_request_slot
*slot
;
626 struct slot_results results
;
628 data
= xmalloc(4096);
629 memset(data
, 0, 4096);
632 buffer
.buffer
= data
;
635 fprintf(stderr
, "Getting pack list\n");
637 url
= xmalloc(strlen(remote
->url
) + 21);
638 sprintf(url
, "%s/objects/info/packs", remote
->url
);
640 slot
= get_active_slot();
641 slot
->results
= &results
;
642 curl_easy_setopt(slot
->curl
, CURLOPT_FILE
, &buffer
);
643 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_buffer
);
644 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, url
);
645 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPHEADER
, NULL
);
646 if (start_active_slot(slot
)) {
647 run_active_slot(slot
);
648 if (results
.curl_result
!= CURLE_OK
) {
651 if (results
.http_code
== 404)
654 return error("%s", curl_errorstr
);
659 return error("Unable to start request");
663 data
= buffer
.buffer
;
664 while (i
< buffer
.posn
) {
668 if (i
+ 52 < buffer
.posn
&&
669 !strncmp(data
+ i
, " pack-", 6) &&
670 !strncmp(data
+ i
+ 46, ".pack\n", 6)) {
671 get_sha1_hex(data
+ i
+ 6, sha1
);
677 while (data
[i
] != '\n')
687 static inline int needs_quote(int ch
)
690 case '/': case '-': case '.':
691 case 'A'...'Z': case 'a'...'z': case '0'...'9':
698 static inline int hex(int v
)
700 if (v
< 10) return '0' + v
;
701 else return 'A' + v
- 10;
704 static char *quote_ref_url(const char *base
, const char *ref
)
708 int len
, baselen
, ch
;
710 baselen
= strlen(base
);
712 for (cp
= ref
; (ch
= *cp
) != 0; cp
++, len
++)
714 len
+= 2; /* extra two hex plus replacement % */
716 memcpy(qref
, base
, baselen
);
717 for (cp
= ref
, dp
= qref
+ baselen
; (ch
= *cp
) != 0; cp
++) {
718 if (needs_quote(ch
)) {
720 *dp
++ = hex((ch
>> 4) & 0xF);
721 *dp
++ = hex(ch
& 0xF);
731 int fetch_ref(char *ref
, unsigned char *sha1
)
735 struct buffer buffer
;
736 char *base
= remote
->url
;
737 struct active_request_slot
*slot
;
738 struct slot_results results
;
744 url
= quote_ref_url(base
, ref
);
745 slot
= get_active_slot();
746 slot
->results
= &results
;
747 curl_easy_setopt(slot
->curl
, CURLOPT_FILE
, &buffer
);
748 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_buffer
);
749 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPHEADER
, NULL
);
750 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, url
);
751 if (start_active_slot(slot
)) {
752 run_active_slot(slot
);
753 if (results
.curl_result
!= CURLE_OK
)
754 return error("Couldn't get %s for %s\n%s",
755 url
, ref
, curl_errorstr
);
757 return error("Unable to start request");
761 get_sha1_hex(hex
, sha1
);
765 static void one_remote_object(const char *hex
)
767 unsigned char sha1
[20];
770 if (get_sha1_hex(hex
, sha1
) != 0)
773 obj
= lookup_object(sha1
);
775 obj
= parse_object(sha1
);
777 /* Ignore remote objects that don't exist locally */
781 obj
->flags
|= REMOTE
;
782 if (!object_list_contains(objects
, obj
))
783 add_object(obj
, &objects
, NULL
, "");
786 static void handle_lockprop_ctx(struct xml_ctx
*ctx
, int tag_closed
)
788 int *lock_flags
= (int *)ctx
->userData
;
791 if (!strcmp(ctx
->name
, DAV_CTX_LOCKENTRY
)) {
792 if ((*lock_flags
& DAV_PROP_LOCKEX
) &&
793 (*lock_flags
& DAV_PROP_LOCKWR
)) {
794 *lock_flags
|= DAV_LOCK_OK
;
796 *lock_flags
&= DAV_LOCK_OK
;
797 } else if (!strcmp(ctx
->name
, DAV_CTX_LOCKTYPE_WRITE
)) {
798 *lock_flags
|= DAV_PROP_LOCKWR
;
799 } else if (!strcmp(ctx
->name
, DAV_CTX_LOCKTYPE_EXCLUSIVE
)) {
800 *lock_flags
|= DAV_PROP_LOCKEX
;
805 static void handle_new_lock_ctx(struct xml_ctx
*ctx
, int tag_closed
)
807 struct remote_lock
*lock
= (struct remote_lock
*)ctx
->userData
;
809 if (tag_closed
&& ctx
->cdata
) {
810 if (!strcmp(ctx
->name
, DAV_ACTIVELOCK_OWNER
)) {
811 lock
->owner
= xmalloc(strlen(ctx
->cdata
) + 1);
812 strcpy(lock
->owner
, ctx
->cdata
);
813 } else if (!strcmp(ctx
->name
, DAV_ACTIVELOCK_TIMEOUT
)) {
814 if (!strncmp(ctx
->cdata
, "Second-", 7))
816 strtol(ctx
->cdata
+ 7, NULL
, 10);
817 } else if (!strcmp(ctx
->name
, DAV_ACTIVELOCK_TOKEN
)) {
818 if (!strncmp(ctx
->cdata
, "opaquelocktoken:", 16)) {
819 lock
->token
= xmalloc(strlen(ctx
->cdata
) - 15);
820 strcpy(lock
->token
, ctx
->cdata
+ 16);
826 static void one_remote_ref(char *refname
);
829 xml_start_tag(void *userData
, const char *name
, const char **atts
)
831 struct xml_ctx
*ctx
= (struct xml_ctx
*)userData
;
832 const char *c
= index(name
, ':');
840 new_len
= strlen(ctx
->name
) + strlen(c
) + 2;
842 if (new_len
> ctx
->len
) {
843 ctx
->name
= xrealloc(ctx
->name
, new_len
);
846 strcat(ctx
->name
, ".");
847 strcat(ctx
->name
, c
);
854 ctx
->userFunc(ctx
, 0);
858 xml_end_tag(void *userData
, const char *name
)
860 struct xml_ctx
*ctx
= (struct xml_ctx
*)userData
;
861 const char *c
= index(name
, ':');
864 ctx
->userFunc(ctx
, 1);
871 ep
= ctx
->name
+ strlen(ctx
->name
) - strlen(c
) - 1;
876 xml_cdata(void *userData
, const XML_Char
*s
, int len
)
878 struct xml_ctx
*ctx
= (struct xml_ctx
*)userData
;
881 ctx
->cdata
= xcalloc(len
+1, 1);
882 strncpy(ctx
->cdata
, s
, len
);
885 static struct remote_lock
*lock_remote(char *path
, long timeout
)
887 struct active_request_slot
*slot
;
888 struct slot_results results
;
889 struct buffer out_buffer
;
890 struct buffer in_buffer
;
895 char timeout_header
[25];
896 struct remote_lock
*lock
= remote_locks
;
897 XML_Parser parser
= XML_ParserCreate(NULL
);
898 enum XML_Status result
;
899 struct curl_slist
*dav_headers
= NULL
;
902 url
= xmalloc(strlen(remote
->url
) + strlen(path
) + 1);
903 sprintf(url
, "%s%s", remote
->url
, path
);
905 /* Make sure the url is not already locked */
906 while (lock
&& strcmp(lock
->url
, url
)) {
911 if (refresh_lock(lock
))
917 /* Make sure leading directories exist for the remote ref */
918 ep
= strchr(url
+ strlen(remote
->url
) + 11, '/');
921 slot
= get_active_slot();
922 slot
->results
= &results
;
923 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPGET
, 1);
924 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, url
);
925 curl_easy_setopt(slot
->curl
, CURLOPT_CUSTOMREQUEST
, DAV_MKCOL
);
926 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_null
);
927 if (start_active_slot(slot
)) {
928 run_active_slot(slot
);
929 if (results
.curl_result
!= CURLE_OK
&&
930 results
.http_code
!= 405) {
932 "Unable to create branch path %s\n",
938 fprintf(stderr
, "Unable to start request\n");
943 ep
= strchr(ep
+ 1, '/');
946 out_buffer
.size
= strlen(LOCK_REQUEST
) + strlen(git_default_email
) - 2;
947 out_data
= xmalloc(out_buffer
.size
+ 1);
948 snprintf(out_data
, out_buffer
.size
+ 1, LOCK_REQUEST
, git_default_email
);
950 out_buffer
.buffer
= out_data
;
952 in_buffer
.size
= 4096;
953 in_data
= xmalloc(in_buffer
.size
);
955 in_buffer
.buffer
= in_data
;
957 sprintf(timeout_header
, "Timeout: Second-%ld", timeout
);
958 dav_headers
= curl_slist_append(dav_headers
, timeout_header
);
959 dav_headers
= curl_slist_append(dav_headers
, "Content-Type: text/xml");
961 slot
= get_active_slot();
962 slot
->results
= &results
;
963 curl_easy_setopt(slot
->curl
, CURLOPT_INFILE
, &out_buffer
);
964 curl_easy_setopt(slot
->curl
, CURLOPT_INFILESIZE
, out_buffer
.size
);
965 curl_easy_setopt(slot
->curl
, CURLOPT_READFUNCTION
, fread_buffer
);
966 curl_easy_setopt(slot
->curl
, CURLOPT_FILE
, &in_buffer
);
967 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_buffer
);
968 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, url
);
969 curl_easy_setopt(slot
->curl
, CURLOPT_UPLOAD
, 1);
970 curl_easy_setopt(slot
->curl
, CURLOPT_CUSTOMREQUEST
, DAV_LOCK
);
971 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPHEADER
, dav_headers
);
973 lock
= xcalloc(1, sizeof(*lock
));
977 lock
->refreshing
= 0;
979 if (start_active_slot(slot
)) {
980 run_active_slot(slot
);
981 if (results
.curl_result
== CURLE_OK
) {
982 ctx
.name
= xcalloc(10, 1);
985 ctx
.userFunc
= handle_new_lock_ctx
;
987 XML_SetUserData(parser
, &ctx
);
988 XML_SetElementHandler(parser
, xml_start_tag
,
990 XML_SetCharacterDataHandler(parser
, xml_cdata
);
991 result
= XML_Parse(parser
, in_buffer
.buffer
,
994 if (result
!= XML_STATUS_OK
) {
995 fprintf(stderr
, "XML error: %s\n",
997 XML_GetErrorCode(parser
)));
1002 fprintf(stderr
, "Unable to start request\n");
1005 curl_slist_free_all(dav_headers
);
1009 if (lock
->token
== NULL
|| lock
->timeout
<= 0) {
1010 if (lock
->token
!= NULL
)
1012 if (lock
->owner
!= NULL
)
1020 lock
->start_time
= time(NULL
);
1021 lock
->next
= remote_locks
;
1022 remote_locks
= lock
;
1028 static int unlock_remote(struct remote_lock
*lock
)
1030 struct active_request_slot
*slot
;
1031 struct slot_results results
;
1032 char *lock_token_header
;
1033 struct curl_slist
*dav_headers
= NULL
;
1036 lock_token_header
= xmalloc(strlen(lock
->token
) + 31);
1037 sprintf(lock_token_header
, "Lock-Token: <opaquelocktoken:%s>",
1039 dav_headers
= curl_slist_append(dav_headers
, lock_token_header
);
1041 slot
= get_active_slot();
1042 slot
->results
= &results
;
1043 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_null
);
1044 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, lock
->url
);
1045 curl_easy_setopt(slot
->curl
, CURLOPT_CUSTOMREQUEST
, DAV_UNLOCK
);
1046 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPHEADER
, dav_headers
);
1048 if (start_active_slot(slot
)) {
1049 run_active_slot(slot
);
1050 if (results
.curl_result
== CURLE_OK
)
1053 fprintf(stderr
, "Got HTTP error %ld\n",
1056 fprintf(stderr
, "Unable to start request\n");
1059 curl_slist_free_all(dav_headers
);
1060 free(lock_token_header
);
1067 static void remote_ls(const char *path
, int flags
,
1068 void (*userFunc
)(struct remote_ls_ctx
*ls
),
1071 static void process_ls_object(struct remote_ls_ctx
*ls
)
1073 unsigned int *parent
= (unsigned int *)ls
->userData
;
1074 char *path
= ls
->dentry_name
;
1077 if (!strcmp(ls
->path
, ls
->dentry_name
) && (ls
->flags
& IS_DIR
)) {
1078 remote_dir_exists
[*parent
] = 1;
1082 if (strlen(path
) != 49)
1085 obj_hex
= xmalloc(strlen(path
));
1086 strncpy(obj_hex
, path
, 2);
1087 strcpy(obj_hex
+ 2, path
+ 3);
1088 one_remote_object(obj_hex
);
1092 static void process_ls_ref(struct remote_ls_ctx
*ls
)
1094 if (!strcmp(ls
->path
, ls
->dentry_name
) && (ls
->dentry_flags
& IS_DIR
)) {
1095 fprintf(stderr
, " %s\n", ls
->dentry_name
);
1099 if (!(ls
->dentry_flags
& IS_DIR
))
1100 one_remote_ref(ls
->dentry_name
);
1103 static void handle_remote_ls_ctx(struct xml_ctx
*ctx
, int tag_closed
)
1105 struct remote_ls_ctx
*ls
= (struct remote_ls_ctx
*)ctx
->userData
;
1108 if (!strcmp(ctx
->name
, DAV_PROPFIND_RESP
) && ls
->dentry_name
) {
1109 if (ls
->dentry_flags
& IS_DIR
) {
1110 if (ls
->flags
& PROCESS_DIRS
) {
1113 if (strcmp(ls
->dentry_name
, ls
->path
) &&
1114 ls
->flags
& RECURSIVE
) {
1115 remote_ls(ls
->dentry_name
,
1120 } else if (ls
->flags
& PROCESS_FILES
) {
1123 } else if (!strcmp(ctx
->name
, DAV_PROPFIND_NAME
) && ctx
->cdata
) {
1124 ls
->dentry_name
= xmalloc(strlen(ctx
->cdata
) -
1125 remote
->path_len
+ 1);
1126 strcpy(ls
->dentry_name
, ctx
->cdata
+ remote
->path_len
);
1127 } else if (!strcmp(ctx
->name
, DAV_PROPFIND_COLLECTION
)) {
1128 ls
->dentry_flags
|= IS_DIR
;
1130 } else if (!strcmp(ctx
->name
, DAV_PROPFIND_RESP
)) {
1131 if (ls
->dentry_name
) {
1132 free(ls
->dentry_name
);
1134 ls
->dentry_name
= NULL
;
1135 ls
->dentry_flags
= 0;
1139 static void remote_ls(const char *path
, int flags
,
1140 void (*userFunc
)(struct remote_ls_ctx
*ls
),
1143 char *url
= xmalloc(strlen(remote
->url
) + strlen(path
) + 1);
1144 struct active_request_slot
*slot
;
1145 struct slot_results results
;
1146 struct buffer in_buffer
;
1147 struct buffer out_buffer
;
1150 XML_Parser parser
= XML_ParserCreate(NULL
);
1151 enum XML_Status result
;
1152 struct curl_slist
*dav_headers
= NULL
;
1154 struct remote_ls_ctx ls
;
1157 ls
.path
= strdup(path
);
1158 ls
.dentry_name
= NULL
;
1159 ls
.dentry_flags
= 0;
1160 ls
.userData
= userData
;
1161 ls
.userFunc
= userFunc
;
1163 sprintf(url
, "%s%s", remote
->url
, path
);
1165 out_buffer
.size
= strlen(PROPFIND_ALL_REQUEST
);
1166 out_data
= xmalloc(out_buffer
.size
+ 1);
1167 snprintf(out_data
, out_buffer
.size
+ 1, PROPFIND_ALL_REQUEST
);
1168 out_buffer
.posn
= 0;
1169 out_buffer
.buffer
= out_data
;
1171 in_buffer
.size
= 4096;
1172 in_data
= xmalloc(in_buffer
.size
);
1174 in_buffer
.buffer
= in_data
;
1176 dav_headers
= curl_slist_append(dav_headers
, "Depth: 1");
1177 dav_headers
= curl_slist_append(dav_headers
, "Content-Type: text/xml");
1179 slot
= get_active_slot();
1180 slot
->results
= &results
;
1181 curl_easy_setopt(slot
->curl
, CURLOPT_INFILE
, &out_buffer
);
1182 curl_easy_setopt(slot
->curl
, CURLOPT_INFILESIZE
, out_buffer
.size
);
1183 curl_easy_setopt(slot
->curl
, CURLOPT_READFUNCTION
, fread_buffer
);
1184 curl_easy_setopt(slot
->curl
, CURLOPT_FILE
, &in_buffer
);
1185 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_buffer
);
1186 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, url
);
1187 curl_easy_setopt(slot
->curl
, CURLOPT_UPLOAD
, 1);
1188 curl_easy_setopt(slot
->curl
, CURLOPT_CUSTOMREQUEST
, DAV_PROPFIND
);
1189 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPHEADER
, dav_headers
);
1191 if (start_active_slot(slot
)) {
1192 run_active_slot(slot
);
1193 if (results
.curl_result
== CURLE_OK
) {
1194 ctx
.name
= xcalloc(10, 1);
1197 ctx
.userFunc
= handle_remote_ls_ctx
;
1199 XML_SetUserData(parser
, &ctx
);
1200 XML_SetElementHandler(parser
, xml_start_tag
,
1202 XML_SetCharacterDataHandler(parser
, xml_cdata
);
1203 result
= XML_Parse(parser
, in_buffer
.buffer
,
1207 if (result
!= XML_STATUS_OK
) {
1208 fprintf(stderr
, "XML error: %s\n",
1210 XML_GetErrorCode(parser
)));
1214 fprintf(stderr
, "Unable to start PROPFIND request\n");
1220 free(in_buffer
.buffer
);
1221 curl_slist_free_all(dav_headers
);
1224 static void get_remote_object_list(unsigned char parent
)
1226 char path
[] = "objects/XX/";
1227 static const char hex
[] = "0123456789abcdef";
1228 unsigned int val
= parent
;
1230 path
[8] = hex
[val
>> 4];
1231 path
[9] = hex
[val
& 0xf];
1232 remote_dir_exists
[val
] = 0;
1233 remote_ls(path
, (PROCESS_FILES
| PROCESS_DIRS
),
1234 process_ls_object
, &val
);
1237 static int locking_available(void)
1239 struct active_request_slot
*slot
;
1240 struct slot_results results
;
1241 struct buffer in_buffer
;
1242 struct buffer out_buffer
;
1245 XML_Parser parser
= XML_ParserCreate(NULL
);
1246 enum XML_Status result
;
1247 struct curl_slist
*dav_headers
= NULL
;
1252 strlen(PROPFIND_SUPPORTEDLOCK_REQUEST
) +
1253 strlen(remote
->url
) - 2;
1254 out_data
= xmalloc(out_buffer
.size
+ 1);
1255 snprintf(out_data
, out_buffer
.size
+ 1,
1256 PROPFIND_SUPPORTEDLOCK_REQUEST
, remote
->url
);
1257 out_buffer
.posn
= 0;
1258 out_buffer
.buffer
= out_data
;
1260 in_buffer
.size
= 4096;
1261 in_data
= xmalloc(in_buffer
.size
);
1263 in_buffer
.buffer
= in_data
;
1265 dav_headers
= curl_slist_append(dav_headers
, "Depth: 0");
1266 dav_headers
= curl_slist_append(dav_headers
, "Content-Type: text/xml");
1268 slot
= get_active_slot();
1269 slot
->results
= &results
;
1270 curl_easy_setopt(slot
->curl
, CURLOPT_INFILE
, &out_buffer
);
1271 curl_easy_setopt(slot
->curl
, CURLOPT_INFILESIZE
, out_buffer
.size
);
1272 curl_easy_setopt(slot
->curl
, CURLOPT_READFUNCTION
, fread_buffer
);
1273 curl_easy_setopt(slot
->curl
, CURLOPT_FILE
, &in_buffer
);
1274 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_buffer
);
1275 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, remote
->url
);
1276 curl_easy_setopt(slot
->curl
, CURLOPT_UPLOAD
, 1);
1277 curl_easy_setopt(slot
->curl
, CURLOPT_CUSTOMREQUEST
, DAV_PROPFIND
);
1278 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPHEADER
, dav_headers
);
1280 if (start_active_slot(slot
)) {
1281 run_active_slot(slot
);
1282 if (results
.curl_result
== CURLE_OK
) {
1283 ctx
.name
= xcalloc(10, 1);
1286 ctx
.userFunc
= handle_lockprop_ctx
;
1287 ctx
.userData
= &lock_flags
;
1288 XML_SetUserData(parser
, &ctx
);
1289 XML_SetElementHandler(parser
, xml_start_tag
,
1291 result
= XML_Parse(parser
, in_buffer
.buffer
,
1295 if (result
!= XML_STATUS_OK
) {
1296 fprintf(stderr
, "XML error: %s\n",
1298 XML_GetErrorCode(parser
)));
1303 fprintf(stderr
, "Unable to start request\n");
1307 free(in_buffer
.buffer
);
1308 curl_slist_free_all(dav_headers
);
1313 static struct object_list
**process_blob(struct blob
*blob
,
1314 struct object_list
**p
,
1315 struct name_path
*path
,
1318 struct object
*obj
= &blob
->object
;
1320 obj
->flags
|= LOCAL
;
1322 if (obj
->flags
& (UNINTERESTING
| SEEN
))
1326 return add_object(obj
, p
, path
, name
);
1329 static struct object_list
**process_tree(struct tree
*tree
,
1330 struct object_list
**p
,
1331 struct name_path
*path
,
1334 struct object
*obj
= &tree
->object
;
1335 struct tree_entry_list
*entry
;
1336 struct name_path me
;
1338 obj
->flags
|= LOCAL
;
1340 if (obj
->flags
& (UNINTERESTING
| SEEN
))
1342 if (parse_tree(tree
) < 0)
1343 die("bad tree object %s", sha1_to_hex(obj
->sha1
));
1346 p
= add_object(obj
, p
, NULL
, name
);
1349 me
.elem_len
= strlen(name
);
1350 entry
= tree
->entries
;
1351 tree
->entries
= NULL
;
1353 struct tree_entry_list
*next
= entry
->next
;
1354 if (entry
->directory
)
1355 p
= process_tree(entry
->item
.tree
, p
, &me
, entry
->name
);
1357 p
= process_blob(entry
->item
.blob
, p
, &me
, entry
->name
);
1364 static void get_delta(struct rev_info
*revs
, struct remote_lock
*lock
)
1366 struct commit
*commit
;
1367 struct object_list
**p
= &objects
, *pending
;
1369 while ((commit
= get_revision(revs
)) != NULL
) {
1370 p
= process_tree(commit
->tree
, p
, NULL
, "");
1371 commit
->object
.flags
|= LOCAL
;
1372 if (!(commit
->object
.flags
& UNINTERESTING
))
1373 add_request(&commit
->object
, lock
);
1376 for (pending
= revs
->pending_objects
; pending
; pending
= pending
->next
) {
1377 struct object
*obj
= pending
->item
;
1378 const char *name
= pending
->name
;
1380 if (obj
->flags
& (UNINTERESTING
| SEEN
))
1382 if (obj
->type
== tag_type
) {
1384 p
= add_object(obj
, p
, NULL
, name
);
1387 if (obj
->type
== tree_type
) {
1388 p
= process_tree((struct tree
*)obj
, p
, NULL
, name
);
1391 if (obj
->type
== blob_type
) {
1392 p
= process_blob((struct blob
*)obj
, p
, NULL
, name
);
1395 die("unknown pending object %s (%s)", sha1_to_hex(obj
->sha1
), name
);
1399 if (!(objects
->item
->flags
& UNINTERESTING
))
1400 add_request(objects
->item
, lock
);
1401 objects
= objects
->next
;
1405 static int update_remote(unsigned char *sha1
, struct remote_lock
*lock
)
1407 struct active_request_slot
*slot
;
1408 struct slot_results results
;
1411 struct buffer out_buffer
;
1412 struct curl_slist
*dav_headers
= NULL
;
1415 if_header
= xmalloc(strlen(lock
->token
) + 25);
1416 sprintf(if_header
, "If: (<opaquelocktoken:%s>)", lock
->token
);
1417 dav_headers
= curl_slist_append(dav_headers
, if_header
);
1419 out_buffer
.size
= 41;
1420 out_data
= xmalloc(out_buffer
.size
+ 1);
1421 i
= snprintf(out_data
, out_buffer
.size
+ 1, "%s\n", sha1_to_hex(sha1
));
1422 if (i
!= out_buffer
.size
) {
1423 fprintf(stderr
, "Unable to initialize PUT request body\n");
1426 out_buffer
.posn
= 0;
1427 out_buffer
.buffer
= out_data
;
1429 slot
= get_active_slot();
1430 slot
->results
= &results
;
1431 curl_easy_setopt(slot
->curl
, CURLOPT_INFILE
, &out_buffer
);
1432 curl_easy_setopt(slot
->curl
, CURLOPT_INFILESIZE
, out_buffer
.size
);
1433 curl_easy_setopt(slot
->curl
, CURLOPT_READFUNCTION
, fread_buffer
);
1434 curl_easy_setopt(slot
->curl
, CURLOPT_WRITEFUNCTION
, fwrite_null
);
1435 curl_easy_setopt(slot
->curl
, CURLOPT_CUSTOMREQUEST
, DAV_PUT
);
1436 curl_easy_setopt(slot
->curl
, CURLOPT_HTTPHEADER
, dav_headers
);
1437 curl_easy_setopt(slot
->curl
, CURLOPT_UPLOAD
, 1);
1438 curl_easy_setopt(slot
->curl
, CURLOPT_PUT
, 1);
1439 curl_easy_setopt(slot
->curl
, CURLOPT_URL
, lock
->url
);
1441 if (start_active_slot(slot
)) {
1442 run_active_slot(slot
);
1445 if (results
.curl_result
!= CURLE_OK
) {
1447 "PUT error: curl result=%d, HTTP code=%ld\n",
1448 results
.curl_result
, results
.http_code
);
1449 /* We should attempt recovery? */
1455 fprintf(stderr
, "Unable to start PUT request\n");
1462 static struct ref
*local_refs
, **local_tail
;
1463 static struct ref
*remote_refs
, **remote_tail
;
1465 static int one_local_ref(const char *refname
, const unsigned char *sha1
)
1468 int len
= strlen(refname
) + 1;
1469 ref
= xcalloc(1, sizeof(*ref
) + len
);
1470 memcpy(ref
->new_sha1
, sha1
, 20);
1471 memcpy(ref
->name
, refname
, len
);
1473 local_tail
= &ref
->next
;
1477 static void one_remote_ref(char *refname
)
1480 unsigned char remote_sha1
[20];
1482 if (fetch_ref(refname
, remote_sha1
) != 0) {
1484 "Unable to fetch ref %s from %s\n",
1485 refname
, remote
->url
);
1489 int len
= strlen(refname
) + 1;
1490 ref
= xcalloc(1, sizeof(*ref
) + len
);
1491 memcpy(ref
->old_sha1
, remote_sha1
, 20);
1492 memcpy(ref
->name
, refname
, len
);
1494 remote_tail
= &ref
->next
;
1497 static void get_local_heads(void)
1499 local_tail
= &local_refs
;
1500 for_each_ref(one_local_ref
);
1503 static void get_dav_remote_heads(void)
1505 remote_tail
= &remote_refs
;
1506 remote_ls("refs/", (PROCESS_FILES
| PROCESS_DIRS
| RECURSIVE
), process_ls_ref
, NULL
);
1509 static int is_zero_sha1(const unsigned char *sha1
)
1513 for (i
= 0; i
< 20; i
++) {
1520 static void unmark_and_free(struct commit_list
*list
, unsigned int mark
)
1523 struct commit_list
*temp
= list
;
1524 temp
->item
->object
.flags
&= ~mark
;
1530 static int ref_newer(const unsigned char *new_sha1
,
1531 const unsigned char *old_sha1
)
1534 struct commit
*old
, *new;
1535 struct commit_list
*list
, *used
;
1538 /* Both new and old must be commit-ish and new is descendant of
1539 * old. Otherwise we require --force.
1541 o
= deref_tag(parse_object(old_sha1
), NULL
, 0);
1542 if (!o
|| o
->type
!= commit_type
)
1544 old
= (struct commit
*) o
;
1546 o
= deref_tag(parse_object(new_sha1
), NULL
, 0);
1547 if (!o
|| o
->type
!= commit_type
)
1549 new = (struct commit
*) o
;
1551 if (parse_commit(new) < 0)
1555 commit_list_insert(new, &list
);
1557 new = pop_most_recent_commit(&list
, TMP_MARK
);
1558 commit_list_insert(new, &used
);
1564 unmark_and_free(list
, TMP_MARK
);
1565 unmark_and_free(used
, TMP_MARK
);
1569 static void mark_edge_parents_uninteresting(struct commit
*commit
)
1571 struct commit_list
*parents
;
1573 for (parents
= commit
->parents
; parents
; parents
= parents
->next
) {
1574 struct commit
*parent
= parents
->item
;
1575 if (!(parent
->object
.flags
& UNINTERESTING
))
1577 mark_tree_uninteresting(parent
->tree
);
1581 static void mark_edges_uninteresting(struct commit_list
*list
)
1583 for ( ; list
; list
= list
->next
) {
1584 struct commit
*commit
= list
->item
;
1586 if (commit
->object
.flags
& UNINTERESTING
) {
1587 mark_tree_uninteresting(commit
->tree
);
1590 mark_edge_parents_uninteresting(commit
);
1594 int main(int argc
, char **argv
)
1596 struct transfer_request
*request
;
1597 struct transfer_request
*next_request
;
1599 char **refspec
= NULL
;
1600 struct remote_lock
*ref_lock
;
1601 struct rev_info revs
;
1605 setup_git_directory();
1608 remote
= xmalloc(sizeof(*remote
));
1610 remote
->path_len
= 0;
1611 remote
->packs
= NULL
;
1614 for (i
= 1; i
< argc
; i
++, argv
++) {
1618 if (!strcmp(arg
, "--all")) {
1622 if (!strcmp(arg
, "--force")) {
1626 if (!strcmp(arg
, "--verbose")) {
1630 usage(http_push_usage
);
1634 char *path
= strstr(arg
, "//");
1636 path
= index(path
+2, '/');
1638 remote
->path_len
= strlen(path
);
1643 nr_refspec
= argc
- i
;
1648 usage(http_push_usage
);
1650 memset(remote_dir_exists
, -1, 256);
1654 no_pragma_header
= curl_slist_append(no_pragma_header
, "Pragma:");
1655 default_headers
= curl_slist_append(default_headers
, "Range:");
1656 default_headers
= curl_slist_append(default_headers
, "Destination:");
1657 default_headers
= curl_slist_append(default_headers
, "If:");
1658 default_headers
= curl_slist_append(default_headers
,
1659 "Pragma: no-cache");
1661 /* Verify DAV compliance/lock support */
1662 if (!locking_available()) {
1663 fprintf(stderr
, "Error: no DAV locking support on remote repo %s\n", remote
->url
);
1668 /* Get a list of all local and remote heads to validate refspecs */
1670 fprintf(stderr
, "Fetching remote heads...\n");
1671 get_dav_remote_heads();
1675 remote_tail
= &remote_refs
;
1676 if (match_refs(local_refs
, remote_refs
, &remote_tail
,
1677 nr_refspec
, refspec
, push_all
))
1680 fprintf(stderr
, "No refs in common and none specified; doing nothing.\n");
1687 for (ref
= remote_refs
; ref
; ref
= ref
->next
) {
1688 char old_hex
[60], *new_hex
;
1691 if (!memcmp(ref
->old_sha1
, ref
->peer_ref
->new_sha1
, 20)) {
1692 if (push_verbosely
|| 1)
1693 fprintf(stderr
, "'%s': up-to-date\n", ref
->name
);
1698 !is_zero_sha1(ref
->old_sha1
) &&
1700 if (!has_sha1_file(ref
->old_sha1
) ||
1701 !ref_newer(ref
->peer_ref
->new_sha1
,
1703 /* We do not have the remote ref, or
1704 * we know that the remote ref is not
1705 * an ancestor of what we are trying to
1706 * push. Either way this can be losing
1707 * commits at the remote end and likely
1708 * we were not up to date to begin with.
1710 error("remote '%s' is not a strict "
1711 "subset of local ref '%s'. "
1712 "maybe you are not up-to-date and "
1713 "need to pull first?",
1715 ref
->peer_ref
->name
);
1720 memcpy(ref
->new_sha1
, ref
->peer_ref
->new_sha1
, 20);
1721 if (is_zero_sha1(ref
->new_sha1
)) {
1722 error("cannot happen anymore");
1727 strcpy(old_hex
, sha1_to_hex(ref
->old_sha1
));
1728 new_hex
= sha1_to_hex(ref
->new_sha1
);
1730 fprintf(stderr
, "updating '%s'", ref
->name
);
1731 if (strcmp(ref
->name
, ref
->peer_ref
->name
))
1732 fprintf(stderr
, " using '%s'", ref
->peer_ref
->name
);
1733 fprintf(stderr
, "\n from %s\n to %s\n", old_hex
, new_hex
);
1736 /* Lock remote branch ref */
1737 ref_lock
= lock_remote(ref
->name
, LOCK_TIME
);
1738 if (ref_lock
== NULL
) {
1739 fprintf(stderr
, "Unable to lock remote branch %s\n",
1745 /* Set up revision info for this refspec */
1746 const char *commit_argv
[4];
1747 int commit_argc
= 3;
1748 char *new_sha1_hex
= strdup(sha1_to_hex(ref
->new_sha1
));
1749 char *old_sha1_hex
= NULL
;
1750 commit_argv
[1] = "--objects";
1751 commit_argv
[2] = new_sha1_hex
;
1752 if (!push_all
&& !is_zero_sha1(ref
->old_sha1
)) {
1753 old_sha1_hex
= xmalloc(42);
1754 sprintf(old_sha1_hex
, "^%s",
1755 sha1_to_hex(ref
->old_sha1
));
1756 commit_argv
[3] = old_sha1_hex
;
1759 setup_revisions(commit_argc
, commit_argv
, &revs
, NULL
);
1763 commit_argv
[1] = NULL
;
1766 /* Generate a list of objects that need to be pushed */
1768 prepare_revision_walk(&revs
);
1769 mark_edges_uninteresting(revs
.commits
);
1771 get_delta(&revs
, ref_lock
);
1772 finish_all_active_slots();
1774 /* Push missing objects to remote, this would be a
1775 convenient time to pack them first if appropriate. */
1777 fill_active_slots();
1778 finish_all_active_slots();
1780 /* Update the remote branch if all went well */
1781 if (aborted
|| !update_remote(ref
->new_sha1
, ref_lock
)) {
1788 fprintf(stderr
, " done\n");
1789 unlock_remote(ref_lock
);
1795 curl_slist_free_all(no_pragma_header
);
1796 curl_slist_free_all(default_headers
);
1800 request
= request_queue_head
;
1801 while (request
!= NULL
) {
1802 next_request
= request
->next
;
1803 release_request(request
);
1804 request
= next_request
;