#[cfg(feature = "async-network-client")]
use gix_transport::client::async_io::Transport;
#[cfg(feature = "blocking-network-client")]
use gix_transport::client::blocking_io::Transport;
use crate::{
bstr::BString,
remote,
remote::{
fetch::{DryRun, RefMap},
ref_map, Connection,
},
Progress,
};
mod error;
pub use error::Error;
use crate::remote::fetch::WritePackedRefs;
pub enum RefLogMessage {
Prefixed {
action: String,
},
Override {
message: BString,
},
}
impl RefLogMessage {
pub(crate) fn compose(&self, context: &str) -> BString {
match self {
RefLogMessage::Prefixed { action } => format!("{action}: {context}").into(),
RefLogMessage::Override { message } => message.to_owned(),
}
}
}
#[derive(Debug, Clone)]
pub enum Status {
NoPackReceived {
dry_run: bool,
negotiate: Option<outcome::Negotiate>,
update_refs: refs::update::Outcome,
},
Change {
negotiate: outcome::Negotiate,
write_pack_bundle: gix_pack::bundle::write::Outcome,
update_refs: refs::update::Outcome,
},
}
#[derive(Debug, Clone)]
pub struct Outcome {
pub ref_map: RefMap,
pub handshake: gix_protocol::Handshake,
pub status: Status,
}
pub mod outcome {
#[derive(Default, Debug, Clone)]
pub struct Negotiate {
pub graph: gix_negotiate::IdMap,
pub rounds: Vec<gix_protocol::fetch::negotiate::Round>,
}
}
pub use gix_protocol::fetch::ProgressId;
pub mod prepare {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error("Cannot perform a meaningful fetch operation without any configured ref-specs")]
MissingRefSpecs,
#[error(transparent)]
RefMap(#[from] crate::remote::ref_map::Error),
}
impl gix_protocol::transport::IsSpuriousError for Error {
fn is_spurious(&self) -> bool {
match self {
Error::RefMap(err) => err.is_spurious(),
_ => false,
}
}
}
}
impl<'remote, 'repo, T> Connection<'remote, 'repo, T>
where
T: Transport,
{
#[allow(clippy::result_large_err)]
#[gix_protocol::maybe_async::maybe_async]
pub async fn prepare_fetch(
mut self,
progress: impl Progress,
options: ref_map::Options,
) -> Result<Prepare<'remote, 'repo, T>, prepare::Error> {
if self.remote.refspecs(remote::Direction::Fetch).is_empty() && options.extra_refspecs.is_empty() {
return Err(prepare::Error::MissingRefSpecs);
}
let ref_map = self.ref_map_by_ref(progress, options).await?;
Ok(Prepare {
con: Some(self),
ref_map,
dry_run: DryRun::No,
reflog_message: None,
write_packed_refs: WritePackedRefs::Never,
shallow: Default::default(),
})
}
}
impl<T> Prepare<'_, '_, T>
where
T: Transport,
{
pub fn ref_map(&self) -> &RefMap {
&self.ref_map
}
}
mod config;
mod receive_pack;
#[path = "update_refs/mod.rs"]
pub mod refs;
pub struct Prepare<'remote, 'repo, T>
where
T: Transport,
{
con: Option<Connection<'remote, 'repo, T>>,
ref_map: RefMap,
dry_run: DryRun,
reflog_message: Option<RefLogMessage>,
write_packed_refs: WritePackedRefs,
shallow: remote::fetch::Shallow,
}
impl<T> Prepare<'_, '_, T>
where
T: Transport,
{
pub fn with_dry_run(mut self, enabled: bool) -> Self {
self.dry_run = if enabled { DryRun::Yes } else { DryRun::No };
self
}
pub fn with_write_packed_refs_only(mut self, enabled: bool) -> Self {
self.write_packed_refs = if enabled {
WritePackedRefs::Only
} else {
WritePackedRefs::Never
};
self
}
pub fn with_reflog_message(mut self, reflog_message: RefLogMessage) -> Self {
self.reflog_message = reflog_message.into();
self
}
pub fn with_shallow(mut self, shallow: remote::fetch::Shallow) -> Self {
self.shallow = shallow;
self
}
}