1
- use libc:: { c_char, c_int, c_uint, c_void} ;
1
+ use libc:: { c_char, c_int, c_uint, c_void, size_t } ;
2
2
use std:: ffi:: { CStr , CString } ;
3
3
use std:: mem;
4
4
use std:: ptr;
@@ -7,15 +7,19 @@ use std::str;
7
7
8
8
use crate :: cert:: Cert ;
9
9
use crate :: util:: Binding ;
10
- use crate :: { panic, raw, Cred , CredentialType , Error , IndexerProgress , Oid , Progress } ;
10
+ use crate :: {
11
+ panic, raw, Cred , CredentialType , Error , IndexerProgress , Oid , PackBuilderStage , Progress ,
12
+ } ;
11
13
12
14
/// A structure to contain the callbacks which are invoked when a repository is
13
15
/// being updated or downloaded.
14
16
///
15
17
/// These callbacks are used to manage facilities such as authentication,
16
18
/// transfer progress, etc.
17
19
pub struct RemoteCallbacks < ' a > {
20
+ push_progress : Option < Box < PushTransferProgress < ' a > > > ,
18
21
progress : Option < Box < IndexerProgress < ' a > > > ,
22
+ pack_progress : Option < Box < PackProgress < ' a > > > ,
19
23
credentials : Option < Box < Credentials < ' a > > > ,
20
24
sideband_progress : Option < Box < TransportMessage < ' a > > > ,
21
25
update_tips : Option < Box < UpdateTips < ' a > > > ,
@@ -56,6 +60,22 @@ pub type CertificateCheck<'a> = dyn FnMut(&Cert<'_>, &str) -> bool + 'a;
56
60
/// was rejected by the remote server with a reason why.
57
61
pub type PushUpdateReference < ' a > = dyn FnMut ( & str , Option < & str > ) -> Result < ( ) , Error > + ' a ;
58
62
63
+ /// Callback for push transfer progress
64
+ ///
65
+ /// Parameters:
66
+ /// * current
67
+ /// * total
68
+ /// * bytes
69
+ pub type PushTransferProgress < ' a > = dyn FnMut ( usize , usize , usize ) + ' a ;
70
+
71
+ /// Callback for pack progress
72
+ ///
73
+ /// Parameters:
74
+ /// * stage
75
+ /// * current
76
+ /// * total
77
+ pub type PackProgress < ' a > = dyn FnMut ( PackBuilderStage , usize , usize ) + ' a ;
78
+
59
79
impl < ' a > Default for RemoteCallbacks < ' a > {
60
80
fn default ( ) -> Self {
61
81
Self :: new ( )
@@ -68,10 +88,12 @@ impl<'a> RemoteCallbacks<'a> {
68
88
RemoteCallbacks {
69
89
credentials : None ,
70
90
progress : None ,
91
+ pack_progress : None ,
71
92
sideband_progress : None ,
72
93
update_tips : None ,
73
94
certificate_check : None ,
74
95
push_update_reference : None ,
96
+ push_progress : None ,
75
97
}
76
98
}
77
99
@@ -158,6 +180,26 @@ impl<'a> RemoteCallbacks<'a> {
158
180
self . push_update_reference = Some ( Box :: new ( cb) as Box < PushUpdateReference < ' a > > ) ;
159
181
self
160
182
}
183
+
184
+ /// The callback through which progress of push transfer is monitored
185
+ pub fn push_transfer_progress < F > ( & mut self , cb : F ) -> & mut RemoteCallbacks < ' a >
186
+ where
187
+ F : FnMut ( usize , usize , usize ) + ' a ,
188
+ {
189
+ self . push_progress = Some ( Box :: new ( cb) as Box < PushTransferProgress < ' a > > ) ;
190
+ self
191
+ }
192
+
193
+ /// Function to call with progress information during pack building.
194
+ /// Be aware that this is called inline with pack building operations,
195
+ /// so performance may be affected.
196
+ pub fn pack_progress < F > ( & mut self , cb : F ) -> & mut RemoteCallbacks < ' a >
197
+ where
198
+ F : FnMut ( PackBuilderStage , usize , usize ) + ' a ,
199
+ {
200
+ self . pack_progress = Some ( Box :: new ( cb) as Box < PackProgress < ' a > > ) ;
201
+ self
202
+ }
161
203
}
162
204
163
205
impl < ' a > Binding for RemoteCallbacks < ' a > {
@@ -188,6 +230,12 @@ impl<'a> Binding for RemoteCallbacks<'a> {
188
230
if self . push_update_reference . is_some ( ) {
189
231
callbacks. push_update_reference = Some ( push_update_reference_cb) ;
190
232
}
233
+ if self . push_progress . is_some ( ) {
234
+ callbacks. push_transfer_progress = Some ( push_transfer_progress_cb) ;
235
+ }
236
+ if self . pack_progress . is_some ( ) {
237
+ callbacks. pack_progress = Some ( pack_progress_cb) ;
238
+ }
191
239
if self . update_tips . is_some ( ) {
192
240
let f: extern "C" fn (
193
241
* const c_char ,
@@ -360,3 +408,45 @@ extern "C" fn push_update_reference_cb(
360
408
} )
361
409
. unwrap_or ( -1 )
362
410
}
411
+
412
+ extern "C" fn push_transfer_progress_cb (
413
+ progress : c_uint ,
414
+ total : c_uint ,
415
+ bytes : size_t ,
416
+ data : * mut c_void ,
417
+ ) -> c_int {
418
+ panic:: wrap ( || unsafe {
419
+ let payload = & mut * ( data as * mut RemoteCallbacks < ' _ > ) ;
420
+ let callback = match payload. push_progress {
421
+ Some ( ref mut c) => c,
422
+ None => return 0 ,
423
+ } ;
424
+
425
+ callback ( progress as usize , total as usize , bytes as usize ) ;
426
+
427
+ 0
428
+ } )
429
+ . unwrap_or ( -1 )
430
+ }
431
+
432
+ extern "C" fn pack_progress_cb (
433
+ stage : raw:: git_packbuilder_stage_t ,
434
+ current : c_uint ,
435
+ total : c_uint ,
436
+ data : * mut c_void ,
437
+ ) -> c_int {
438
+ panic:: wrap ( || unsafe {
439
+ let payload = & mut * ( data as * mut RemoteCallbacks < ' _ > ) ;
440
+ let callback = match payload. pack_progress {
441
+ Some ( ref mut c) => c,
442
+ None => return 0 ,
443
+ } ;
444
+
445
+ let stage = Binding :: from_raw ( stage) ;
446
+
447
+ callback ( stage, current as usize , total as usize ) ;
448
+
449
+ 0
450
+ } )
451
+ . unwrap_or ( -1 )
452
+ }
0 commit comments