refactor: extract git::repository::factory module
All checks were successful
Rust / build (push) Successful in 1m29s
ci/woodpecker/push/cron-docker-builder Pipeline was successful
ci/woodpecker/push/push-next Pipeline was successful
ci/woodpecker/push/tag-created Pipeline was successful

This commit is contained in:
Paul Campbell 2024-07-05 20:31:16 +01:00
parent 5ab075c181
commit 4e60be61f7
10 changed files with 76 additions and 76 deletions

View file

@ -0,0 +1,51 @@
use super::RepoDetails;
use super::Result;
pub use crate::repository::open::OpenRepositoryLike;
use crate::repository::RealOpenRepository;
use derive_more::Deref as _;
use git_next_config::GitDir;
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, gitdir: &GitDir) -> 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))] // requires network access to either clone new and/or fetch.
impl RepositoryFactory for RealRepositoryFactory {
fn open(&self, gitdir: &GitDir) -> Result<Box<dyn OpenRepositoryLike>> {
let gix_repo = gix::ThreadSafeRepository::open(gitdir.to_path_buf())?.to_thread_local();
let repo = RealOpenRepository::new(Arc::new(RwLock::new(gix_repo.into())));
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())
}
}

View file

@ -1,30 +1,23 @@
// //
use std::sync::{atomic::AtomicBool, Arc, RwLock}; use super::RepoDetails;
use crate::repository::test::TestRepository;
use derive_more::Deref as _; use crate::validation::remotes::validate_default_remotes;
pub use factory::RepositoryFactory;
pub mod open;
// mod real;
mod test;
#[cfg(test)]
mod tests;
use git_next_config as config; use git_next_config as config;
use git_next_config::GitDir; use git_next_config::GitDir;
pub use open::otest::OnFetch; pub use open::otest::OnFetch;
pub use open::otest::OnPush; pub use open::otest::OnPush;
pub use open::OpenRepository; pub use open::OpenRepository;
pub use open::OpenRepositoryLike; pub use open::OpenRepositoryLike;
pub use open::RealOpenRepository; pub use open::RealOpenRepository;
use tracing::info; use tracing::info;
use crate::repository::test::TestRepository; pub mod factory;
use crate::validation::remotes::validate_default_remotes; pub mod open;
mod test;
use super::RepoDetails; #[cfg(test)]
mod tests;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[allow(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)]
@ -41,7 +34,7 @@ pub const fn test(fs: kxio::fs::FileSystem) -> TestRepository {
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
#[cfg(not(tarpaulin_include))] // requires network access to either clone new and/or fetch. #[cfg(not(tarpaulin_include))] // requires network access to either clone new and/or fetch.
pub fn open( pub fn open(
repository_factory: &dyn RepositoryFactory, repository_factory: &dyn factory::RepositoryFactory,
repo_details: &RepoDetails, repo_details: &RepoDetails,
gitdir: config::GitDir, gitdir: config::GitDir,
) -> Result<Box<dyn OpenRepositoryLike>> { ) -> Result<Box<dyn OpenRepositoryLike>> {
@ -58,50 +51,6 @@ pub fn open(
Ok(open_repository) Ok(open_repository)
} }
#[mockall::automock]
pub trait RepositoryFactory: std::fmt::Debug + Sync + Send {
fn duplicate(&self) -> Box<dyn RepositoryFactory>;
fn open(&self, gitdir: &GitDir) -> 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))] // requires network access to either clone new and/or fetch.
impl RepositoryFactory for RealRepositoryFactory {
fn open(&self, gitdir: &GitDir) -> Result<Box<dyn OpenRepositoryLike>> {
let gix_repo = gix::ThreadSafeRepository::open(gitdir.to_path_buf())?.to_thread_local();
let repo = RealOpenRepository::new(Arc::new(RwLock::new(gix_repo.into())));
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())
}
}
pub trait RepositoryLike { pub trait RepositoryLike {
fn open(&self, gitdir: &GitDir) -> Result<OpenRepository>; fn open(&self, gitdir: &GitDir) -> Result<OpenRepository>;
fn git_clone(&self, repo_details: &RepoDetails) -> Result<OpenRepository>; fn git_clone(&self, repo_details: &RepoDetails) -> Result<OpenRepository>;

View file

@ -6,6 +6,6 @@ fn should_fetch_from_repo() {
// uses the current repo and fetches from the remote server // uses the current repo and fetches from the remote server
let_assert!(Ok(cwd) = std::env::current_dir()); let_assert!(Ok(cwd) = std::env::current_dir());
let gitdir = GitDir::from(cwd.join("../..")); let gitdir = GitDir::from(cwd.join("../.."));
let_assert!(Ok(repo) = crate::repository::real().open(&gitdir)); let_assert!(Ok(repo) = crate::repository::factory::real().open(&gitdir));
let_assert!(Ok(_) = repo.fetch()); let_assert!(Ok(_) = repo.fetch());
} }

View file

@ -5,7 +5,7 @@ fn should_find_default_push_remote() {
// uses the current repo // uses the current repo
let_assert!(Ok(cwd) = std::env::current_dir()); let_assert!(Ok(cwd) = std::env::current_dir());
let gitdir = config::GitDir::from(cwd.join("../..")); // from ./crate/git directory to the project rook let gitdir = config::GitDir::from(cwd.join("../..")); // from ./crate/git directory to the project rook
let_assert!(Ok(repo) = crate::repository::real().open(&gitdir)); let_assert!(Ok(repo) = git::repository::factory::real().open(&gitdir));
let_assert!(Some(remote) = repo.find_default_remote(crate::repository::Direction::Push)); let_assert!(Some(remote) = repo.find_default_remote(crate::repository::Direction::Push));
assert_eq!( assert_eq!(
remote, remote,

View file

@ -23,7 +23,7 @@ mod repos {
.expect_find_default_remote() .expect_find_default_remote()
.with(mockall::predicate::eq(Direction::Push)) .with(mockall::predicate::eq(Direction::Push))
.return_once(|_| None); .return_once(|_| None);
let mut repository_factory = git::repository::mock(); let mut repository_factory = git::repository::factory::mock();
repository_factory repository_factory
.expect_open() .expect_open()
.return_once(move |_| Ok(mock_open_repository)); .return_once(move |_| Ok(mock_open_repository));
@ -63,7 +63,7 @@ mod positions {
mock_open_repository mock_open_repository
.expect_fetch() .expect_fetch()
.return_once(|| Err(git::fetch::Error::TestFailureExpected)); .return_once(|| Err(git::fetch::Error::TestFailureExpected));
let mut repository_factory = git::repository::mock(); let mut repository_factory = git::repository::factory::mock();
repository_factory repository_factory
.expect_open() .expect_open()
.return_once(move |_| Ok(mock_open_repository)); .return_once(move |_| Ok(mock_open_repository));
@ -104,7 +104,7 @@ mod positions {
Ok(vec![]) Ok(vec![])
} }
}); });
let mut repository_factory = git::repository::mock(); let mut repository_factory = git::repository::factory::mock();
repository_factory repository_factory
.expect_open() .expect_open()
.return_once(move |_| Ok(mock_open_repository)); .return_once(move |_| Ok(mock_open_repository));
@ -143,7 +143,7 @@ mod positions {
Ok(vec![given::a_commit()]) Ok(vec![given::a_commit()])
} }
}); });
let mut repository_factory = git::repository::mock(); let mut repository_factory = git::repository::factory::mock();
repository_factory repository_factory
.expect_open() .expect_open()
.return_once(move |_| Ok(mock_open_repository)); .return_once(move |_| Ok(mock_open_repository));
@ -182,7 +182,7 @@ mod positions {
Ok(vec![given::a_commit()]) Ok(vec![given::a_commit()])
} }
}); });
let mut repository_factory = git::repository::mock(); let mut repository_factory = git::repository::factory::mock();
repository_factory repository_factory
.expect_open() .expect_open()
.return_once(move |_| Ok(mock_open_repository)); .return_once(move |_| Ok(mock_open_repository));

View file

@ -1,7 +1,7 @@
// //
use super::*; use super::*;
use git::repository::MockRepositoryFactory; use git::repository::factory::MockRepositoryFactory;
use git_next_git::repository::open::MockOpenRepositoryLike; use git_next_git::repository::open::MockOpenRepositoryLike;
pub fn fetch_ok(open_repository: &mut MockOpenRepositoryLike) { pub fn fetch_ok(open_repository: &mut MockOpenRepositoryLike) {

View file

@ -290,7 +290,7 @@ async fn should_accept_message_with_current_token() -> TestResult {
//when //when
let (actor, log) = given::a_repo_actor( let (actor, log) = given::a_repo_actor(
repo_details, repo_details,
git::repository::mock(), git::repository::factory::mock(),
given::a_forge(), given::a_forge(),
given::a_network().into(), given::a_network().into(),
); );
@ -314,7 +314,7 @@ async fn should_accept_message_with_new_token() -> TestResult {
//when //when
let (actor, log) = given::a_repo_actor( let (actor, log) = given::a_repo_actor(
repo_details, repo_details,
git::repository::mock(), git::repository::factory::mock(),
given::a_forge(), given::a_forge(),
given::a_network().into(), given::a_network().into(),
); );
@ -338,7 +338,7 @@ async fn should_reject_message_with_expired_token() -> TestResult {
//when //when
let (actor, log) = given::a_repo_actor( let (actor, log) = given::a_repo_actor(
repo_details, repo_details,
git::repository::mock(), git::repository::factory::mock(),
given::a_forge(), given::a_forge(),
given::a_network().into(), given::a_network().into(),
); );

View file

@ -13,7 +13,7 @@ use config::{
RepoAlias, RepoBranches, RepoConfig, ServerRepoConfig, WebhookAuth, WebhookId, RepoAlias, RepoBranches, RepoConfig, ServerRepoConfig, WebhookAuth, WebhookId,
}; };
use git::{ use git::{
repository::{open::MockOpenRepositoryLike, Direction, MockRepositoryFactory}, repository::{factory::MockRepositoryFactory, open::MockOpenRepositoryLike, Direction},
Generation, GitRemote, MockForgeLike, RepoDetails, Generation, GitRemote, MockForgeLike, RepoDetails,
}; };
use git_next_actor_macros::message; use git_next_actor_macros::message;

View file

@ -4,7 +4,7 @@ use git::repository::OpenRepositoryLike;
use super::*; use super::*;
pub fn start_actor( pub fn start_actor(
repository_factory: git::repository::MockRepositoryFactory, repository_factory: git::repository::factory::MockRepositoryFactory,
repo_details: git::RepoDetails, repo_details: git::RepoDetails,
forge: Box<dyn git::ForgeLike>, forge: Box<dyn git::ForgeLike>,
) -> (actix::Addr<RepoActor>, RepoActorLog) { ) -> (actix::Addr<RepoActor>, RepoActorLog) {
@ -24,7 +24,7 @@ pub fn start_actor_with_open_repository(
) -> (actix::Addr<RepoActor>, RepoActorLog) { ) -> (actix::Addr<RepoActor>, RepoActorLog) {
let (actor, log) = given::a_repo_actor( let (actor, log) = given::a_repo_actor(
repo_details, repo_details,
git::repository::mock(), git::repository::factory::mock(),
forge, forge,
given::a_network().into(), given::a_network().into(),
); );

View file

@ -13,7 +13,7 @@ use std::path::PathBuf;
use tracing::{error, info, warn}; use tracing::{error, info, warn};
use webhook::{AddWebhookRecipient, ShutdownWebhook, WebhookActor, WebhookRouter}; use webhook::{AddWebhookRecipient, ShutdownWebhook, WebhookActor, WebhookRouter};
pub use git_next_git::repository::{real as repository_factory, RepositoryFactory}; pub use git_next_git::repository::{factory::real as repository_factory, RepositoryFactory};
message!(ReceiveServerConfig: ServerConfig: "Notification of newly loaded server configuration. message!(ReceiveServerConfig: ServerConfig: "Notification of newly loaded server configuration.