use std::ops::ControlFlow;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use super::workflow::{select, selected};
use super::{
DownloadedFetch, FetchLimits, FetchReady, FetchRequest, FetchUpdate, FetchWorkflowError,
KnownHistory,
};
use crate::transport::TransportControl;
#[derive(Debug)]
pub struct FetchDownload {
request: FetchRequest,
updates: Vec<FetchUpdate>,
downloaded: DownloadedFetch,
}
impl FetchDownload {
pub fn validate(
self,
cancel: &AtomicBool,
progress: impl FnMut(&[u8]) -> ControlFlow<()>,
) -> Result<FetchReady, FetchWorkflowError> {
self.validate_with_progress(cancel, progress, |_| {})
}
pub fn validate_with_progress(
self,
cancel: &AtomicBool,
progress: impl FnMut(&[u8]) -> ControlFlow<()>,
observe: impl FnMut(super::ValidationProgress),
) -> Result<FetchReady, FetchWorkflowError> {
Ok(FetchReady {
request: self.request,
updates: self.updates,
received: self
.downloaded
.validate_with_progress(cancel, progress, observe)?,
})
}
}
impl FetchRequest {
#[cfg(feature = "http")]
pub async fn receive_http(
self,
remote: &crate::transport::http::HttpRemote,
known: Option<Arc<KnownHistory>>,
limits: FetchLimits,
control: TransportControl<'_>,
) -> Result<FetchDownload, FetchWorkflowError> {
self.receive_http_with_progress(remote, known, limits, control, |_| {})
.await
}
#[cfg(feature = "http")]
pub async fn receive_http_with_progress(
self,
remote: &crate::transport::http::HttpRemote,
known: Option<Arc<KnownHistory>>,
limits: FetchLimits,
control: TransportControl<'_>,
progress: impl FnMut(&[u8]),
) -> Result<FetchDownload, FetchWorkflowError> {
self.check_known(known.as_deref().unwrap_or(&KnownHistory::default()))?;
let mut plan = None;
let downloaded = super::receive_http_with_depth_and_progress(
remote,
|advertisement| select(self.plan(advertisement), &mut plan),
known,
self.depth,
limits,
control,
progress,
)
.await;
let updates = selected(plan, &downloaded)?;
Ok(FetchDownload {
request: self,
updates,
downloaded: downloaded?,
})
}
#[cfg(all(feature = "ssh", any(target_os = "macos", target_os = "linux")))]
pub async fn receive_ssh(
self,
remote: &crate::transport::ssh::SshRemote,
known: Option<Arc<KnownHistory>>,
limits: FetchLimits,
control: TransportControl<'_>,
) -> Result<FetchDownload, FetchWorkflowError> {
self.receive_ssh_with_progress(remote, known, limits, control, |_| {}, |_| {})
.await
}
#[cfg(all(feature = "ssh", any(target_os = "macos", target_os = "linux")))]
pub async fn receive_ssh_with_progress(
self,
remote: &crate::transport::ssh::SshRemote,
known: Option<Arc<KnownHistory>>,
limits: FetchLimits,
control: TransportControl<'_>,
diagnostics: impl FnMut(&[u8]),
progress: impl FnMut(&[u8]),
) -> Result<FetchDownload, FetchWorkflowError> {
self.check_known(known.as_deref().unwrap_or(&KnownHistory::default()))?;
let mut plan = None;
let downloaded = super::receive_ssh_with_progress(
remote,
|advertisement| select(self.plan(advertisement), &mut plan),
known,
super::FetchOptions {
limits,
depth: self.depth,
},
control,
diagnostics,
progress,
)
.await;
let updates = selected(plan, &downloaded)?;
Ok(FetchDownload {
request: self,
updates,
downloaded: downloaded?,
})
}
}