Skip to content

Commit 5fddf7e

Browse files
author
Stephan Dilly
authored
allow hooking into push_transfer_progress & pack_progress callbacks (#617)
* allow hooking into push_transfer_progress callback * support pack_progress
1 parent 7aa5d85 commit 5fddf7e

File tree

2 files changed

+93
-2
lines changed

2 files changed

+93
-2
lines changed

src/packbuilder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::slice;
66
use crate::util::Binding;
77
use crate::{panic, raw, Buf, Error, Oid, Repository, Revwalk};
88

9+
#[derive(PartialEq, Eq, Clone, Debug, Copy)]
910
/// Stages that are reported by the `PackBuilder` progress callback.
1011
pub enum PackBuilderStage {
1112
/// Adding objects to the pack

src/remote_callbacks.rs

+92-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use libc::{c_char, c_int, c_uint, c_void};
1+
use libc::{c_char, c_int, c_uint, c_void, size_t};
22
use std::ffi::{CStr, CString};
33
use std::mem;
44
use std::ptr;
@@ -7,15 +7,19 @@ use std::str;
77

88
use crate::cert::Cert;
99
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+
};
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.
1719
pub 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.
5761
pub 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+
5979
impl<'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

163205
impl<'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

Comments
 (0)