|
1 | 1 | #lang racket |
2 | 2 |
|
3 | 3 | (require ffi/unsafe |
| 4 | + ffi/unsafe/os-async-channel |
4 | 5 | (only-in "net.rkt" |
5 | 6 | _git_direction |
6 | 7 | _git_remote_head) |
|
29 | 30 | GIT_REMOTE_COMPLETION_INDEXING |
30 | 31 | GIT_REMOTE_COMPLETION_ERROR))) |
31 | 32 |
|
| 33 | +;; Blocking remote callouts allow other Racket threads to run while libgit2 is |
| 34 | +;; doing network/pack work. Racket requires callbacks entered from such a |
| 35 | +;; callout to have a non-#f #:async-apply. Queue callback thunks to an ordinary |
| 36 | +;; Racket thread so callback bodies may safely perform normal Racket work. |
| 37 | +(define remote-callback-channel (make-os-async-channel)) |
| 38 | + |
| 39 | +(define remote-callback-dispatch-thread |
| 40 | + (thread |
| 41 | + (lambda () |
| 42 | + (let loop () |
| 43 | + (define thunk (sync remote-callback-channel)) |
| 44 | + (thunk) |
| 45 | + (loop))))) |
| 46 | + |
| 47 | +(define (remote-callback-async-apply thunk) |
| 48 | + ;; os-async-channel-put is valid in atomic mode and from an OS thread. |
| 49 | + (os-async-channel-put remote-callback-channel thunk)) |
| 50 | + |
32 | 51 | ;; libgit2 can retain all callbacks in this structure for the lifetime of a |
33 | 52 | ;; remote transport. Use an explicit #:keep hook so the generated callback |
34 | 53 | ;; values can be tied to the git_remote lifetime instead of only to the |
|
43 | 62 |
|
44 | 63 | (define _git_remote_credential_acquire_cb |
45 | 64 | (_fun #:keep keep-current-callback! |
| 65 | + #:async-apply remote-callback-async-apply |
46 | 66 | (_cpointer _git_credential) _string _string _uint _pointer -> _int)) |
47 | 67 |
|
48 | 68 | (define _git_remote_certificate_check_cb |
|
51 | 71 |
|
52 | 72 | (define _git_remote_transfer_progress_cb |
53 | 73 | (_fun #:keep keep-current-callback! |
| 74 | + #:async-apply remote-callback-async-apply |
54 | 75 | _git_transfer_progress-pointer _pointer -> _int)) |
55 | 76 |
|
56 | 77 | (define _git_remote_update_tips_cb |
|
59 | 80 |
|
60 | 81 | (define _git_remote_pack_progress_cb |
61 | 82 | (_fun #:keep keep-current-callback! |
| 83 | + #:async-apply remote-callback-async-apply |
62 | 84 | _int _uint32 _uint32 _pointer -> _int)) |
63 | 85 |
|
64 | 86 | (define _git_push_transfer_progress |
65 | 87 | (_fun #:keep keep-current-callback! |
| 88 | + #:async-apply remote-callback-async-apply |
66 | 89 | _uint _uint _size _pointer -> _int)) |
67 | 90 |
|
68 | 91 | (define-cstruct _git_push_update |
|
395 | 418 | _string |
396 | 419 | -> _int)) |
397 | 420 |
|
| 421 | +;; Blocking variant for callers that need other Racket threads to remain |
| 422 | +;; schedulable while libgit2 fetches. Callbacks used with this variant must |
| 423 | +;; have a non-#f #:async-apply. |
| 424 | +(define-libgit2 git_remote_fetch/blocking |
| 425 | + (_fun #:blocking? #t |
| 426 | + _git_remote |
| 427 | + (_or-null _git_strarray-pointer) |
| 428 | + _git_fetch_opts-pointer/null |
| 429 | + _string |
| 430 | + -> (_git_error_code/check)) |
| 431 | + #:c-id git_remote_fetch) |
| 432 | + |
398 | 433 | (define-libgit2 git_remote_get_fetch_refspecs |
399 | 434 | (_fun [lst : (_git_strarray-pointer/alloc)] |
400 | 435 | _git_remote |
|
454 | 489 | _git_push_opts-pointer/null |
455 | 490 | -> _int)) |
456 | 491 |
|
| 492 | +;; Blocking variant; see git_remote_fetch/blocking. |
| 493 | +(define-libgit2 git_remote_push/blocking |
| 494 | + (_fun #:blocking? #t |
| 495 | + _git_remote |
| 496 | + (_or-null _git_strarray-pointer) |
| 497 | + _git_push_opts-pointer/null |
| 498 | + -> (_git_error_code/check)) |
| 499 | + #:c-id git_remote_push) |
| 500 | + |
457 | 501 | (define-libgit2 git_remote_pushurl |
458 | 502 | (_fun _git_remote -> _string)) |
459 | 503 |
|
|
529 | 573 | (retain-owner-callbacks-for-remote! remote opts) |
530 | 574 | (raw remote refspecs opts reflog-message)))) |
531 | 575 |
|
| 576 | +(let ([raw git_remote_fetch/blocking]) |
| 577 | + (set! git_remote_fetch/blocking |
| 578 | + (lambda (remote refspecs opts reflog-message) |
| 579 | + (retain-owner-callbacks-for-remote! remote opts) |
| 580 | + (raw remote refspecs opts reflog-message)))) |
| 581 | + |
532 | 582 | (let ([raw git_remote_prune]) |
533 | 583 | (set! git_remote_prune |
534 | 584 | (lambda (remote callbacks) |
|
541 | 591 | (retain-owner-callbacks-for-remote! remote opts) |
542 | 592 | (raw remote refspecs opts)))) |
543 | 593 |
|
| 594 | +(let ([raw git_remote_push/blocking]) |
| 595 | + (set! git_remote_push/blocking |
| 596 | + (lambda (remote refspecs opts) |
| 597 | + (retain-owner-callbacks-for-remote! remote opts) |
| 598 | + (raw remote refspecs opts)))) |
| 599 | + |
544 | 600 | (let ([raw git_remote_update_tips]) |
545 | 601 | (set! git_remote_update_tips |
546 | 602 | (lambda (remote callbacks update-fetchhead download-tags reflog-message) |
|
0 commit comments