WIP RepositoryFactory trait
This commit is contained in:
parent
ea20afee12
commit
134049de57
15 changed files with 135 additions and 75 deletions
|
@ -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"
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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(), &[]))?;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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...");
|
||||||
|
|
Loading…
Reference in a new issue