use super::RepoDetails;
use super::Result;
pub use crate::repository::open::OpenRepositoryLike;
use crate::repository::{Direction, RealOpenRepository};
use derive_more::Deref as _;
use std::sync::{atomic::AtomicBool, Arc, RwLock};
#[mockall::automock]
pub trait RepositoryFactory: std::fmt::Debug + Sync + Send {
fn duplicate(&self) -> Box<dyn RepositoryFactory>;
fn open(&self, repo_details: &RepoDetails) -> Result<Box<dyn OpenRepositoryLike>>;
fn git_clone(&self, repo_details: &RepoDetails) -> Result<Box<dyn OpenRepositoryLike>>;
}
pub fn real() -> Box<dyn RepositoryFactory> {
Box::new(RealRepositoryFactory)
}
pub fn mock() -> Box<MockRepositoryFactory> {
Box::new(MockRepositoryFactory::new())
}
#[derive(Debug, Clone)]
struct RealRepositoryFactory;
#[cfg(not(tarpaulin_include))] impl RepositoryFactory for RealRepositoryFactory {
fn open(&self, repo_details: &RepoDetails) -> Result<Box<dyn OpenRepositoryLike>> {
let repo = repo_details
.open()
.map_err(|e| crate::repository::Error::Open(e.to_string()))?;
let found = repo.find_default_remote(Direction::Fetch);
repo_details.assert_remote_url(found)?;
Ok(Box::new(repo))
}
fn git_clone(&self, repo_details: &RepoDetails) -> Result<Box<dyn OpenRepositoryLike>> {
tracing::info!("creating");
use secrecy::ExposeSecret;
let (gix_repo, _outcome) = gix::prepare_clone_bare(
repo_details.origin().expose_secret().as_str(),
repo_details.gitdir.deref(),
)?
.fetch_only(gix::progress::Discard, &AtomicBool::new(false))?;
tracing::info!("created");
let repo = RealOpenRepository::new(Arc::new(RwLock::new(gix_repo.into())));
Ok(Box::new(repo))
}
fn duplicate(&self) -> Box<dyn RepositoryFactory> {
Box::new(self.clone())
}
}