use crate::{
git::{
self,
repository::{
open::{oreal::RealOpenRepository, OpenRepositoryLike},
Direction, Result,
},
RepoDetails,
},
s,
};
use secrecy::ExposeSecret as _;
use std::sync::{atomic::AtomicBool, Arc, RwLock};
#[allow(clippy::module_name_repetitions)]
#[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>>;
}
#[must_use]
pub fn real() -> Box<dyn RepositoryFactory> {
Box::new(RealRepositoryFactory)
}
#[must_use]
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| git::repository::Error::Open(s!(e)))?;
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");
let (gix_repo, _outcome) =
gix::prepare_clone_bare(repo_details.origin().expose_secret(), &*repo_details.gitdir)?
.fetch_only(gix::progress::Discard, &AtomicBool::new(false))?;
tracing::info!("created");
let repo = RealOpenRepository::new(
Arc::new(RwLock::new(gix_repo.into())),
repo_details.forge.clone(),
);
Ok(Box::new(repo))
}
fn duplicate(&self) -> Box<dyn RepositoryFactory> {
Box::new(self.clone())
}
}