1- use libc:: { c_char, c_int, c_uint, c_void} ;
1+ use libc:: { c_char, c_int, c_uint, c_void, size_t } ;
22use std:: ffi:: { CStr , CString } ;
33use std:: mem;
44use std:: ptr;
@@ -7,15 +7,19 @@ use std::str;
77
88use crate :: cert:: Cert ;
99use 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+ } ;
1113
1214/// A structure to contain the callbacks which are invoked when a repository is
1315/// being updated or downloaded.
1416///
1517/// These callbacks are used to manage facilities such as authentication,
1618/// transfer progress, etc.
1719pub struct RemoteCallbacks < ' a > {
20+ push_progress : Option < Box < PushTransferProgress < ' a > > > ,
1821 progress : Option < Box < IndexerProgress < ' a > > > ,
22+ pack_progress : Option < Box < PackProgress < ' a > > > ,
1923 credentials : Option < Box < Credentials < ' a > > > ,
2024 sideband_progress : Option < Box < TransportMessage < ' a > > > ,
2125 update_tips : Option < Box < UpdateTips < ' a > > > ,
@@ -56,6 +60,22 @@ pub type CertificateCheck<'a> = dyn FnMut(&Cert<'_>, &str) -> bool + 'a;
5660/// was rejected by the remote server with a reason why.
5761pub type PushUpdateReference < ' a > = dyn FnMut ( & str , Option < & str > ) -> Result < ( ) , Error > + ' a ;
5862
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+
5979impl < ' a > Default for RemoteCallbacks < ' a > {
6080 fn default ( ) -> Self {
6181 Self :: new ( )
@@ -68,10 +88,12 @@ impl<'a> RemoteCallbacks<'a> {
6888 RemoteCallbacks {
6989 credentials : None ,
7090 progress : None ,
91+ pack_progress : None ,
7192 sideband_progress : None ,
7293 update_tips : None ,
7394 certificate_check : None ,
7495 push_update_reference : None ,
96+ push_progress : None ,
7597 }
7698 }
7799
@@ -158,6 +180,26 @@ impl<'a> RemoteCallbacks<'a> {
158180 self . push_update_reference = Some ( Box :: new ( cb) as Box < PushUpdateReference < ' a > > ) ;
159181 self
160182 }
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+ }
161203}
162204
163205impl < ' a > Binding for RemoteCallbacks < ' a > {
@@ -188,6 +230,12 @@ impl<'a> Binding for RemoteCallbacks<'a> {
188230 if self . push_update_reference . is_some ( ) {
189231 callbacks. push_update_reference = Some ( push_update_reference_cb) ;
190232 }
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+ }
191239 if self . update_tips . is_some ( ) {
192240 let f: extern "C" fn (
193241 * const c_char ,
@@ -360,3 +408,45 @@ extern "C" fn push_update_reference_cb(
360408 } )
361409 . unwrap_or ( -1 )
362410}
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