WIP RepositoryFactory trait
All checks were successful
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-06-19 16:40:10 +01:00
parent ea20afee12
commit 134049de57
15 changed files with 135 additions and 75 deletions

View file

@ -96,3 +96,4 @@ tokio = { version = "1.37", features = ["rt", "macros"] }
assert2 = "0.3" assert2 = "0.3"
pretty_assertions = "1.4" pretty_assertions = "1.4"
rand = "0.8" rand = "0.8"
mockall = "0.12"

View file

@ -30,7 +30,7 @@ enum Server {
async fn main() { async fn main() {
let fs = fs::new(PathBuf::default()); let fs = fs::new(PathBuf::default());
let net = Network::new_real(); let net = Network::new_real();
let repo = git_next_git::repository::new(); let repo = git_next_git::repository::real();
let commands = Commands::parse(); let commands = Commands::parse();
match commands.command { match commands.command {

View file

@ -56,6 +56,7 @@ actix = { workspace = true }
assert2 = { workspace = true } assert2 = { workspace = true }
rand = { workspace = true } rand = { workspace = true }
pretty_assertions = { workspace = true } pretty_assertions = { workspace = true }
mockall = { workspace = true }
[lints.clippy] [lints.clippy]
nursery = { level = "warn", priority = -1 } nursery = { level = "warn", priority = -1 }

View file

@ -47,7 +47,7 @@ pub enum Error {
} }
pub fn reset( pub fn reset(
repository: &git::OpenRepository, repository: &dyn git::repository::OpenRepositoryLike,
repo_details: &git::RepoDetails, repo_details: &git::RepoDetails,
branch_name: &config::BranchName, branch_name: &config::BranchName,
to_commit: &git::GitRef, to_commit: &git::GitRef,

View file

@ -1,6 +1,10 @@
// //
#[cfg(test)] #[cfg(test)]
mod mock; mod mock;
use std::sync::{atomic::AtomicBool, Arc, Mutex};
use derive_more::Deref as _;
#[cfg(test)] #[cfg(test)]
pub use mock::MockRepository; pub use mock::MockRepository;
#[cfg(test)] #[cfg(test)]
@ -26,11 +30,11 @@ pub use real::RealRepository;
use tracing::info; use tracing::info;
use crate::repository::test::TestRepository; use crate::repository::test::TestRepository;
use crate::validation::repo::validate_repo; use crate::validation::repo::validate_repo;
use super::RepoDetails; use super::RepoDetails;
// TODO: #[deprecated]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[allow(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)]
pub enum Repository { pub enum Repository {
@ -62,11 +66,11 @@ 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: &Repository, repository: &dyn RepositoryFactory,
repo_details: &RepoDetails, repo_details: &RepoDetails,
gitdir: config::GitDir, gitdir: config::GitDir,
) -> Result<OpenRepository> { ) -> Result<Box<dyn OpenRepositoryLike>> {
let repository = if !gitdir.exists() { let open_repository = if !gitdir.exists() {
info!("Local copy not found - cloning..."); info!("Local copy not found - cloning...");
repository.git_clone(repo_details)? repository.git_clone(repo_details)?
} else { } else {
@ -74,8 +78,44 @@ pub fn open(
repository.open(&gitdir)? repository.open(&gitdir)?
}; };
info!("Validating..."); info!("Validating...");
validate_repo(&repository, repo_details).map_err(|e| Error::Validation(e.to_string()))?; validate_repo(&*open_repository, repo_details).map_err(|e| Error::Validation(e.to_string()))?;
Ok(repository) Ok(open_repository)
}
#[cfg_attr(test, mockall::automock)]
pub trait RepositoryFactory: std::fmt::Debug {
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)
}
#[derive(Debug, Clone)]
struct RealRepositoryFactory;
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(Mutex::new(gix_repo)));
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(Mutex::new(gix_repo)));
Ok(Box::new(repo))
}
fn duplicate(&self) -> Box<dyn RepositoryFactory> {
Box::new(self.clone())
}
} }
pub trait RepositoryLike { pub trait RepositoryLike {

View file

@ -23,6 +23,7 @@ pub use omock::MockOpenRepository;
pub use oreal::RealOpenRepository; pub use oreal::RealOpenRepository;
pub use otest::TestOpenRepository; pub use otest::TestOpenRepository;
// TODO: #[deprecated]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum OpenRepository { pub enum OpenRepository {
/// A real git repository. /// A real git repository.
@ -74,7 +75,8 @@ pub fn test_bare(
OpenRepository::Test(TestOpenRepository::new_bare(gitdir, fs, on_fetch, on_push)) OpenRepository::Test(TestOpenRepository::new_bare(gitdir, fs, on_fetch, on_push))
} }
pub trait OpenRepositoryLike { pub trait OpenRepositoryLike: std::fmt::Debug {
fn duplicate(&self) -> Box<dyn OpenRepositoryLike>;
fn remote_branches(&self) -> git::push::Result<Vec<config::BranchName>>; fn remote_branches(&self) -> git::push::Result<Vec<config::BranchName>>;
fn find_default_remote(&self, direction: Direction) -> Option<git::GitRemote>; fn find_default_remote(&self, direction: Direction) -> Option<git::GitRemote>;
fn fetch(&self) -> Result<(), git::fetch::Error>; fn fetch(&self) -> Result<(), git::fetch::Error>;
@ -102,16 +104,16 @@ pub trait OpenRepositoryLike {
file_name: &Path, file_name: &Path,
) -> git::file::Result<String>; ) -> git::file::Result<String>;
} }
impl std::ops::Deref for OpenRepository { // impl std::ops::Deref for OpenRepository {
type Target = dyn OpenRepositoryLike; // type Target = dyn OpenRepositoryLike;
//
fn deref(&self) -> &Self::Target { // fn deref(&self) -> &Self::Target {
match self { // match self {
Self::Real(real) => real, // Self::Real(real) => real,
Self::Test(test) => test, // Self::Test(test) => test,
//
#[cfg(test)] // #[cfg(test)]
Self::Mock(mock) => mock, // Self::Mock(mock) => mock,
} // }
} // }
} // }

View file

@ -1,5 +1,5 @@
// //
use crate as git; use crate::{self as git, repository::OpenRepositoryLike};
use config::BranchName; use config::BranchName;
use derive_more::Constructor; use derive_more::Constructor;
use git_next_config as config; use git_next_config as config;
@ -201,6 +201,10 @@ impl super::OpenRepositoryLike for RealOpenRepository {
Ok(content) Ok(content)
}) })
} }
fn duplicate(&self) -> Box<dyn OpenRepositoryLike> {
Box::new(self.clone())
}
} }
fn as_gix_error(branch: BranchName) -> impl FnOnce(String) -> git::commit::log::Error { fn as_gix_error(branch: BranchName) -> impl FnOnce(String) -> git::commit::log::Error {

View file

@ -1,5 +1,5 @@
// //
use crate as git; use crate::{self as git, repository::OpenRepositoryLike};
use derive_more::{Constructor, Deref}; use derive_more::{Constructor, Deref};
use git_next_config as config; use git_next_config as config;
@ -132,6 +132,10 @@ impl git::repository::OpenRepositoryLike for TestOpenRepository {
) -> git::file::Result<String> { ) -> git::file::Result<String> {
self.real.read_file(branch_name, file_name) self.real.read_file(branch_name, file_name)
} }
fn duplicate(&self) -> Box<dyn OpenRepositoryLike> {
Box::new(self.clone())
}
} }
impl TestOpenRepository { impl TestOpenRepository {
pub fn new( pub fn new(

View file

@ -16,7 +16,7 @@ pub struct Positions {
#[allow(clippy::cognitive_complexity)] // TODO: (#83) reduce complexity #[allow(clippy::cognitive_complexity)] // TODO: (#83) reduce complexity
pub fn validate_positions( pub fn validate_positions(
repository: &git::OpenRepository, open_repository: &dyn git::repository::OpenRepositoryLike,
repo_details: &git::RepoDetails, repo_details: &git::RepoDetails,
repo_config: config::RepoConfig, repo_config: config::RepoConfig,
) -> Result<Positions> { ) -> Result<Positions> {
@ -24,9 +24,9 @@ pub fn validate_positions(
let next_branch = repo_config.branches().next(); let next_branch = repo_config.branches().next();
let dev_branch = repo_config.branches().dev(); let dev_branch = repo_config.branches().dev();
// Collect Commit Histories for `main`, `next` and `dev` branches // Collect Commit Histories for `main`, `next` and `dev` branches
repository.fetch()?; open_repository.fetch()?;
let commit_histories = let commit_histories =
get_commit_histories(repository, &repo_config).map_err(Error::CommitLog)?; get_commit_histories(open_repository, &repo_config).map_err(Error::CommitLog)?;
// branch tips // branch tips
let main = commit_histories let main = commit_histories
.main .main
@ -55,12 +55,12 @@ pub fn validate_positions(
// verify that next is on main or at most one commit on top of main, else reset it back to main // verify that next is on main or at most one commit on top of main, else reset it back to main
if is_not_based_on(&commit_histories.next[0..=1], &main) { if is_not_based_on(&commit_histories.next[0..=1], &main) {
info!("Main not on same commit as next, or it's parent - resetting next to main",); info!("Main not on same commit as next, or it's parent - resetting next to main",);
return reset_next_to_main(repository, repo_details, &main, &next, &next_branch); return reset_next_to_main(open_repository, repo_details, &main, &next, &next_branch);
} }
// verify that next is an ancestor of dev, else reset it back to main // verify that next is an ancestor of dev, else reset it back to main
if is_not_based_on(&commit_histories.dev, &next) { if is_not_based_on(&commit_histories.dev, &next) {
info!("Next is not an ancestor of dev - resetting next to main"); info!("Next is not an ancestor of dev - resetting next to main");
return reset_next_to_main(repository, repo_details, &main, &next, &next_branch); return reset_next_to_main(open_repository, repo_details, &main, &next, &next_branch);
} }
Ok(git::validation::positions::Positions { Ok(git::validation::positions::Positions {
@ -72,7 +72,7 @@ pub fn validate_positions(
} }
fn reset_next_to_main( fn reset_next_to_main(
repository: &crate::OpenRepository, repository: &dyn crate::repository::OpenRepositoryLike,
repo_details: &crate::RepoDetails, repo_details: &crate::RepoDetails,
main: &crate::Commit, main: &crate::Commit,
next: &crate::Commit, next: &crate::Commit,
@ -100,7 +100,7 @@ fn is_not_based_on(commits: &[crate::commit::Commit], needle: &crate::Commit) ->
} }
fn get_commit_histories( fn get_commit_histories(
repository: &git::repository::OpenRepository, repository: &dyn git::repository::OpenRepositoryLike,
repo_config: &config::RepoConfig, repo_config: &config::RepoConfig,
) -> git::commit::log::Result<git::commit::Histories> { ) -> git::commit::log::Result<git::commit::Histories> {
let main = (repository.commit_log(&repo_config.branches().main(), &[]))?; let main = (repository.commit_log(&repo_config.branches().main(), &[]))?;

View file

@ -4,13 +4,13 @@ use crate as git;
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
pub fn validate_repo( pub fn validate_repo(
repository: &git::OpenRepository, open_repository: &dyn git::repository::OpenRepositoryLike,
repo_details: &git::RepoDetails, repo_details: &git::RepoDetails,
) -> Result<()> { ) -> Result<()> {
let push_remote = repository let push_remote = open_repository
.find_default_remote(git::repository::Direction::Push) .find_default_remote(git::repository::Direction::Push)
.ok_or_else(|| Error::NoDefaultPushRemote)?; .ok_or_else(|| Error::NoDefaultPushRemote)?;
let fetch_remote = repository let fetch_remote = open_repository
.find_default_remote(git::repository::Direction::Fetch) .find_default_remote(git::repository::Direction::Fetch)
.ok_or_else(|| Error::NoDefaultFetchRemote)?; .ok_or_else(|| Error::NoDefaultFetchRemote)?;
let git_remote = repo_details.git_remote(); let git_remote = repo_details.git_remote();

View file

@ -16,7 +16,7 @@ pub async fn advance_next(
dev_commit_history: Vec<git::Commit>, dev_commit_history: Vec<git::Commit>,
repo_details: git::RepoDetails, repo_details: git::RepoDetails,
repo_config: config::RepoConfig, repo_config: config::RepoConfig,
repository: git::OpenRepository, open_repository: &dyn git::repository::OpenRepositoryLike,
addr: Addr<super::RepoActor>, addr: Addr<super::RepoActor>,
message_token: MessageToken, message_token: MessageToken,
) { ) {
@ -31,7 +31,7 @@ pub async fn advance_next(
} }
info!("Advancing next to commit '{}'", commit); info!("Advancing next to commit '{}'", commit);
if let Err(err) = git::push::reset( if let Err(err) = git::push::reset(
&repository, open_repository,
&repo_details, &repo_details,
&repo_config.branches().next(), &repo_config.branches().next(),
&commit.into(), &commit.into(),
@ -81,11 +81,11 @@ pub async fn advance_main(
next: git::Commit, next: git::Commit,
repo_details: &git::RepoDetails, repo_details: &git::RepoDetails,
repo_config: &config::RepoConfig, repo_config: &config::RepoConfig,
repository: &git::OpenRepository, open_repository: &dyn git::repository::OpenRepositoryLike,
) { ) {
info!("Advancing main to next"); info!("Advancing main to next");
if let Err(err) = git::push::reset( if let Err(err) = git::push::reset(
repository, &*open_repository,
repo_details, repo_details,
&repo_config.branches().main(), &repo_config.branches().main(),
&next.into(), &next.into(),

View file

@ -32,8 +32,8 @@ pub struct RepoActor {
last_main_commit: Option<git::Commit>, last_main_commit: Option<git::Commit>,
last_next_commit: Option<git::Commit>, last_next_commit: Option<git::Commit>,
last_dev_commit: Option<git::Commit>, last_dev_commit: Option<git::Commit>,
repository: git::Repository, repository: Box<dyn git::repository::RepositoryFactory>,
open_repository: Option<git::OpenRepository>, open_repository: Option<Box<dyn git::repository::OpenRepositoryLike>>,
net: Network, net: Network,
forge: forge::Forge, forge: forge::Forge,
} }
@ -43,7 +43,7 @@ impl RepoActor {
webhook: config::server::Webhook, webhook: config::server::Webhook,
generation: git::Generation, generation: git::Generation,
net: Network, net: Network,
repo: git::Repository, repository: Box<dyn git::repository::RepositoryFactory>,
) -> Self { ) -> Self {
let forge = forge::Forge::new(details.clone(), net.clone()); let forge = forge::Forge::new(details.clone(), net.clone());
debug!(?forge, "new"); debug!(?forge, "new");
@ -57,7 +57,7 @@ impl RepoActor {
last_main_commit: None, last_main_commit: None,
last_next_commit: None, last_next_commit: None,
last_dev_commit: None, last_dev_commit: None,
repository: repo, repository,
open_repository: None, open_repository: None,
net, net,
forge, forge,
@ -96,7 +96,7 @@ impl Handler<CloneRepo> for RepoActor {
#[tracing::instrument(name = "RepoActor::CloneRepo", skip_all, fields(repo = %self.repo_details /*, gitdir = %self.repo_details.gitdir */))] #[tracing::instrument(name = "RepoActor::CloneRepo", skip_all, fields(repo = %self.repo_details /*, gitdir = %self.repo_details.gitdir */))]
fn handle(&mut self, _msg: CloneRepo, ctx: &mut Self::Context) -> Self::Result { fn handle(&mut self, _msg: CloneRepo, ctx: &mut Self::Context) -> Self::Result {
let gitdir = self.repo_details.gitdir.clone(); let gitdir = self.repo_details.gitdir.clone();
match git::repository::open(&self.repository, &self.repo_details, gitdir) { match git::repository::open(&*self.repository, &self.repo_details, gitdir) {
Ok(repository) => { Ok(repository) => {
self.open_repository.replace(repository); self.open_repository.replace(repository);
if self.repo_details.repo_config.is_none() { if self.repo_details.repo_config.is_none() {
@ -121,14 +121,15 @@ impl Handler<LoadConfigFromRepo> for RepoActor {
fn handle(&mut self, _msg: LoadConfigFromRepo, ctx: &mut Self::Context) -> Self::Result { fn handle(&mut self, _msg: LoadConfigFromRepo, ctx: &mut Self::Context) -> Self::Result {
let details = self.repo_details.clone(); let details = self.repo_details.clone();
let addr = ctx.address(); let addr = ctx.address();
let Some(open_repository) = self.open_repository.clone() else { let Some(open_repository) = &self.open_repository else {
warn!("missing open repository - can't load configuration"); warn!("missing open repository - can't load configuration");
return; return;
}; };
repo_actor::load::load_file(details, addr, open_repository) let open_repository = open_repository.duplicate();
async move { repo_actor::load::load_file(details, addr, &*open_repository).await }
.in_current_span() .in_current_span()
.into_actor(self) .into_actor(self)
.wait(ctx); .wait(ctx)
} }
} }
@ -195,15 +196,15 @@ impl Handler<ValidateRepo> for RepoActor {
.into_actor(self) .into_actor(self)
.wait(ctx); .wait(ctx);
} }
if let (Some(repository), Some(repo_config)) = ( if let (Some(open_repository), Some(repo_config)) =
self.open_repository.clone(), (&self.open_repository, self.repo_details.repo_config.clone())
self.repo_details.repo_config.clone(), {
) {
let repo_details = self.repo_details.clone(); let repo_details = self.repo_details.clone();
let addr = ctx.address(); let addr = ctx.address();
let message_token = self.message_token; let message_token = self.message_token;
let open_repository = open_repository.duplicate();
async move { async move {
match validate_positions(&repository, &repo_details, repo_config) { match validate_positions(&*open_repository, &repo_details, repo_config) {
Ok(Positions { Ok(Positions {
main, main,
next, next,
@ -258,16 +259,22 @@ impl Handler<StartMonitoring> for RepoActor {
.into_actor(self) .into_actor(self)
.wait(ctx); .wait(ctx);
} else if dev_ahead_of_next { } else if dev_ahead_of_next {
if let Some(repository) = self.open_repository.clone() { if let Some(open_repository) = &self.open_repository {
branch::advance_next( let open_repository = open_repository.duplicate();
msg.next, let repo_details = self.repo_details.clone();
msg.dev_commit_history, let message_token = self.message_token;
self.repo_details.clone(), async move {
repo_config, branch::advance_next(
repository, msg.next,
addr, msg.dev_commit_history,
self.message_token, repo_details,
) repo_config,
&*open_repository,
addr,
message_token,
)
.await
}
.in_current_span() .in_current_span()
.into_actor(self) .into_actor(self)
.wait(ctx); .wait(ctx);
@ -304,15 +311,16 @@ impl Handler<AdvanceMainTo> for RepoActor {
warn!("No config loaded"); warn!("No config loaded");
return; return;
}; };
let Some(repository) = self.open_repository.clone() else { let Some(open_repository) = &self.open_repository else {
warn!("No repository opened"); warn!("No repository opened");
return; return;
}; };
let repo_details = self.repo_details.clone(); let repo_details = self.repo_details.clone();
let addr = ctx.address(); let addr = ctx.address();
let message_token = self.message_token; let message_token = self.message_token;
let open_repository = open_repository.duplicate();
async move { async move {
branch::advance_main(msg.0, &repo_details, &repo_config, &repository).await; branch::advance_main(msg.0, &repo_details, &repo_config, &*open_repository).await;
match repo_config.source() { match repo_config.source() {
git_next_config::RepoConfigSource::Repo => addr.do_send(LoadConfigFromRepo), git_next_config::RepoConfigSource::Repo => addr.do_send(LoadConfigFromRepo),
git_next_config::RepoConfigSource::Server => { git_next_config::RepoConfigSource::Server => {

View file

@ -15,10 +15,10 @@ use super::{LoadedConfig, RepoActor};
pub async fn load_file( pub async fn load_file(
repo_details: git::RepoDetails, repo_details: git::RepoDetails,
addr: Addr<RepoActor>, addr: Addr<RepoActor>,
open_repository: git::OpenRepository, open_repository: &dyn git::repository::OpenRepositoryLike,
) { ) {
info!("Loading .git-next.toml from repo"); info!("Loading .git-next.toml from repo");
let repo_config = match load(&repo_details, &open_repository).await { let repo_config = match load(&repo_details, open_repository).await {
Ok(repo_config) => repo_config, Ok(repo_config) => repo_config,
Err(err) => { Err(err) => {
error!(?err, "Failed to load config"); error!(?err, "Failed to load config");
@ -31,7 +31,7 @@ pub async fn load_file(
async fn load( async fn load(
details: &git::RepoDetails, details: &git::RepoDetails,
open_repository: &git::OpenRepository, open_repository: &dyn git::repository::OpenRepositoryLike,
) -> Result<config::RepoConfig, Error> { ) -> Result<config::RepoConfig, Error> {
let contents = open_repository.read_file(&details.branch, &PathBuf::from(".git-next.toml"))?; let contents = open_repository.read_file(&details.branch, &PathBuf::from(".git-next.toml"))?;
let config = config::RepoConfig::parse(&contents)?; let config = config::RepoConfig::parse(&contents)?;
@ -50,7 +50,7 @@ pub enum Error {
pub async fn validate( pub async fn validate(
config: config::RepoConfig, config: config::RepoConfig,
open_repository: &git::OpenRepository, open_repository: &dyn git::repository::OpenRepositoryLike,
) -> Result<config::RepoConfig, Error> { ) -> Result<config::RepoConfig, Error> {
let branches = open_repository.remote_branches()?; let branches = open_repository.remote_branches()?;
if !branches if !branches

View file

@ -7,7 +7,7 @@ use config::server::{ServerConfig, ServerStorage, Webhook};
use git_next_config::{ use git_next_config::{
self as config, ForgeAlias, ForgeConfig, GitDir, RepoAlias, ServerRepoConfig, self as config, ForgeAlias, ForgeConfig, GitDir, RepoAlias, ServerRepoConfig,
}; };
use git_next_git::{Generation, RepoDetails, Repository}; use git_next_git::{repository::RepositoryFactory, Generation, RepoDetails};
use git_next_repo_actor::{CloneRepo, RepoActor}; use git_next_repo_actor::{CloneRepo, RepoActor};
use kxio::{fs::FileSystem, network::Network}; use kxio::{fs::FileSystem, network::Network};
use tracing::{error, info, warn}; use tracing::{error, info, warn};
@ -38,7 +38,7 @@ pub struct Server {
webhook: Option<Addr<WebhookActor>>, webhook: Option<Addr<WebhookActor>>,
fs: FileSystem, fs: FileSystem,
net: Network, net: Network,
repo: Repository, repository_factory: Box<dyn RepositoryFactory>,
} }
impl Actor for Server { impl Actor for Server {
type Context = Context<Self>; type Context = Context<Self>;
@ -114,14 +114,14 @@ impl Handler<ServerConfig> for Server {
} }
} }
impl Server { impl Server {
pub fn new(fs: FileSystem, net: Network, repo: Repository) -> Self { pub fn new(fs: FileSystem, net: Network, repo: Box<dyn RepositoryFactory>) -> Self {
let generation = Generation::new(); let generation = Generation::new();
Self { Self {
generation, generation,
webhook: None, webhook: None,
fs, fs,
net, net,
repo, repository_factory: repo,
} }
} }
fn create_forge_data_directories( fn create_forge_data_directories(
@ -180,7 +180,7 @@ impl Server {
let server_storage = server_storage.clone(); let server_storage = server_storage.clone();
let webhook = webhook.clone(); let webhook = webhook.clone();
let net = self.net.clone(); let net = self.net.clone();
let repo = self.repo.clone(); let repository_factory = self.repository_factory.duplicate();
let generation = self.generation; let generation = self.generation;
move |(repo_alias, server_repo_config)| { move |(repo_alias, server_repo_config)| {
let span = tracing::info_span!("create_actor", alias = %repo_alias, config = %server_repo_config); let span = tracing::info_span!("create_actor", alias = %repo_alias, config = %server_repo_config);
@ -213,7 +213,7 @@ impl Server {
webhook.clone(), webhook.clone(),
generation, generation,
net.clone(), net.clone(),
repo.clone(), repository_factory.duplicate(),
); );
(forge_name.clone(), repo_alias, actor) (forge_name.clone(), repo_alias, actor)
} }

View file

@ -3,7 +3,7 @@ mod config;
// //
use actix::prelude::*; use actix::prelude::*;
use git_next_git::Repository; use git_next_git::repository::RepositoryFactory;
use kxio::{fs::FileSystem, network::Network}; use kxio::{fs::FileSystem, network::Network};
use std::path::PathBuf; use std::path::PathBuf;
@ -37,7 +37,7 @@ pub fn init(fs: FileSystem) {
} }
} }
pub async fn start(fs: FileSystem, net: Network, repo: Repository) { pub async fn start(fs: FileSystem, net: Network, repo: Box<dyn RepositoryFactory>) {
init_logging(); init_logging();
info!("Starting Server..."); info!("Starting Server...");