WIP RepositoryFactory trait
This commit is contained in:
parent
ea20afee12
commit
c126020656
22 changed files with 861 additions and 816 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 {
|
||||||
|
|
|
@ -51,12 +51,15 @@ actix = { workspace = true }
|
||||||
# actix-rt = { workspace = true }
|
# actix-rt = { workspace = true }
|
||||||
# tokio = { workspace = true }
|
# tokio = { workspace = true }
|
||||||
|
|
||||||
|
mockall = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
# Testing
|
# Testing
|
||||||
assert2 = { workspace = true }
|
assert2 = { workspace = true }
|
||||||
rand = { workspace = true }
|
rand = { workspace = true }
|
||||||
pretty_assertions = { workspace = true }
|
pretty_assertions = { workspace = true }
|
||||||
|
|
||||||
|
|
||||||
[lints.clippy]
|
[lints.clippy]
|
||||||
nursery = { level = "warn", priority = -1 }
|
nursery = { level = "warn", priority = -1 }
|
||||||
# pedantic = "warn"
|
# pedantic = "warn"
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -10,10 +10,10 @@ use crate as git;
|
||||||
use git_next_config as config;
|
use git_next_config as config;
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct MockRepository {
|
pub struct FakeRepository {
|
||||||
open_repos: Arc<Mutex<HashMap<config::GitDir, git::repository::MockOpenRepository>>>,
|
open_repos: Arc<Mutex<HashMap<config::GitDir, git::repository::FakeOpenRepository>>>,
|
||||||
}
|
}
|
||||||
impl MockRepository {
|
impl FakeRepository {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
open_repos: Default::default(),
|
open_repos: Default::default(),
|
||||||
|
@ -23,8 +23,8 @@ impl MockRepository {
|
||||||
pub fn given_can_be_opened(
|
pub fn given_can_be_opened(
|
||||||
&mut self,
|
&mut self,
|
||||||
gitdir: &config::GitDir,
|
gitdir: &config::GitDir,
|
||||||
) -> git::repository::MockOpenRepository {
|
) -> git::repository::FakeOpenRepository {
|
||||||
let open_repo = git::repository::MockOpenRepository::new();
|
let open_repo = git::repository::FakeOpenRepository::new();
|
||||||
#[allow(clippy::unwrap_used)]
|
#[allow(clippy::unwrap_used)]
|
||||||
self.open_repos
|
self.open_repos
|
||||||
.lock()
|
.lock()
|
||||||
|
@ -34,20 +34,20 @@ impl MockRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seal(self) -> (git::Repository, Self) {
|
pub fn seal(self) -> (git::Repository, Self) {
|
||||||
(git::Repository::Mock(self.clone()), self)
|
(git::Repository::Fake(self.clone()), self)
|
||||||
}
|
}
|
||||||
pub fn unseal(self, _repository: git::Repository) -> Self {
|
pub fn unseal(self, _repository: git::Repository) -> Self {
|
||||||
// drop repository to allow same mutable access to mock repository
|
// drop repository to allow same mutable access to mock repository
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn get(&self, gitdir: &config::GitDir) -> Option<git::repository::MockOpenRepository> {
|
pub fn get(&self, gitdir: &config::GitDir) -> Option<git::repository::FakeOpenRepository> {
|
||||||
self.open_repos
|
self.open_repos
|
||||||
.lock()
|
.lock()
|
||||||
.map(|or| or.get(gitdir).cloned())
|
.map(|or| or.get(gitdir).cloned())
|
||||||
.unwrap_or(None)
|
.unwrap_or(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl git::repository::RepositoryLike for MockRepository {
|
impl git::repository::RepositoryLike for FakeRepository {
|
||||||
fn open(
|
fn open(
|
||||||
&self,
|
&self,
|
||||||
gitdir: &config::GitDir,
|
gitdir: &config::GitDir,
|
||||||
|
@ -55,7 +55,7 @@ impl git::repository::RepositoryLike for MockRepository {
|
||||||
#[allow(clippy::unwrap_used)]
|
#[allow(clippy::unwrap_used)]
|
||||||
self.open_repos
|
self.open_repos
|
||||||
.lock()
|
.lock()
|
||||||
.map_err(|_| crate::repository::Error::MockLock)
|
.map_err(|_| crate::repository::Error::FakeLock)
|
||||||
.map(|or| or.get(gitdir).cloned())
|
.map(|or| or.get(gitdir).cloned())
|
||||||
.transpose()
|
.transpose()
|
||||||
.unwrap_or_else(|| Err(crate::repository::Error::InvalidGitDir(gitdir.clone())))
|
.unwrap_or_else(|| Err(crate::repository::Error::InvalidGitDir(gitdir.clone())))
|
|
@ -1,12 +1,16 @@
|
||||||
//
|
//
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod mock;
|
mod fake;
|
||||||
#[cfg(test)]
|
use std::sync::{atomic::AtomicBool, Arc, Mutex};
|
||||||
pub use mock::MockRepository;
|
|
||||||
#[cfg(test)]
|
|
||||||
pub use open::MockOpenRepository;
|
|
||||||
|
|
||||||
mod open;
|
use derive_more::Deref as _;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub use fake::FakeRepository;
|
||||||
|
#[cfg(test)]
|
||||||
|
pub use open::FakeOpenRepository;
|
||||||
|
|
||||||
|
pub mod open;
|
||||||
mod real;
|
mod real;
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
|
@ -26,27 +30,28 @@ 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 {
|
||||||
Real,
|
Real,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
Mock(MockRepository),
|
Fake(FakeRepository),
|
||||||
Test(TestRepository),
|
Test(TestRepository),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deprecated(note = "use git::repository::real()")]
|
||||||
pub const fn new() -> Repository {
|
pub const fn new() -> Repository {
|
||||||
Repository::Real
|
Repository::Real
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn mock() -> MockRepository {
|
pub fn fake() -> FakeRepository {
|
||||||
MockRepository::new()
|
FakeRepository::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn test(fs: kxio::fs::FileSystem) -> TestRepository {
|
pub const fn test(fs: kxio::fs::FileSystem) -> TestRepository {
|
||||||
|
@ -62,11 +67,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 +79,50 @@ 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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;
|
||||||
|
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 {
|
||||||
|
@ -91,7 +138,7 @@ impl std::ops::Deref for Repository {
|
||||||
Self::Test(test_repository) => test_repository,
|
Self::Test(test_repository) => test_repository,
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
Self::Mock(mock_repository) => mock_repository,
|
Self::Fake(mock_repository) => mock_repository,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,8 +187,8 @@ pub enum Error {
|
||||||
#[error("git fetch: {0}")]
|
#[error("git fetch: {0}")]
|
||||||
Fetch(String),
|
Fetch(String),
|
||||||
|
|
||||||
#[error("mock lock")]
|
#[error("fake repository lock")]
|
||||||
MockLock,
|
FakeLock,
|
||||||
}
|
}
|
||||||
|
|
||||||
mod gix_errors {
|
mod gix_errors {
|
||||||
|
|
|
@ -8,7 +8,7 @@ pub mod oreal;
|
||||||
pub mod otest;
|
pub mod otest;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod omock;
|
pub mod ofake;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
path::Path,
|
path::Path,
|
||||||
|
@ -19,10 +19,11 @@ use crate as git;
|
||||||
use git::repository::Direction;
|
use git::repository::Direction;
|
||||||
use git_next_config as config;
|
use git_next_config as config;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub use omock::MockOpenRepository;
|
pub use ofake::FakeOpenRepository;
|
||||||
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.
|
||||||
|
@ -45,7 +46,7 @@ pub enum OpenRepository {
|
||||||
/// variant is ready for use, tests should be converted to using
|
/// variant is ready for use, tests should be converted to using
|
||||||
/// that instead.
|
/// that instead.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
Mock(git::repository::MockOpenRepository), // TODO: (#38) contain a mock model of a repo
|
Mock(git::repository::FakeOpenRepository), // TODO: (#38) contain a mock model of a repo
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn real(gix_repo: gix::Repository) -> OpenRepository {
|
pub fn real(gix_repo: gix::Repository) -> OpenRepository {
|
||||||
|
@ -74,7 +75,9 @@ 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 {
|
#[mockall::automock]
|
||||||
|
pub trait OpenRepositoryLike: std::fmt::Debug + Sync {
|
||||||
|
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,6 +105,11 @@ pub trait OpenRepositoryLike {
|
||||||
file_name: &Path,
|
file_name: &Path,
|
||||||
) -> git::file::Result<String>;
|
) -> git::file::Result<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mock() -> Box<MockOpenRepositoryLike> {
|
||||||
|
Box::new(MockOpenRepositoryLike::new())
|
||||||
|
}
|
||||||
|
|
||||||
impl std::ops::Deref for OpenRepository {
|
impl std::ops::Deref for OpenRepository {
|
||||||
type Target = dyn OpenRepositoryLike;
|
type Target = dyn OpenRepositoryLike;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
use crate as git;
|
use crate::{self as git, repository::OpenRepositoryLike};
|
||||||
use git_next_config as config;
|
use git_next_config as config;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -8,12 +8,12 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct MockOpenRepository {
|
pub struct FakeOpenRepository {
|
||||||
default_push_remote: Arc<Mutex<Option<git::GitRemote>>>,
|
default_push_remote: Arc<Mutex<Option<git::GitRemote>>>,
|
||||||
default_fetch_remote: Arc<Mutex<Option<git::GitRemote>>>,
|
default_fetch_remote: Arc<Mutex<Option<git::GitRemote>>>,
|
||||||
operations: Arc<Mutex<Vec<String>>>,
|
operations: Arc<Mutex<Vec<String>>>,
|
||||||
}
|
}
|
||||||
impl MockOpenRepository {
|
impl FakeOpenRepository {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
@ -50,13 +50,13 @@ impl MockOpenRepository {
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<MockOpenRepository> for git::OpenRepository {
|
impl From<FakeOpenRepository> for git::OpenRepository {
|
||||||
fn from(value: MockOpenRepository) -> Self {
|
fn from(value: FakeOpenRepository) -> Self {
|
||||||
Self::Mock(value)
|
Self::Mock(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[allow(clippy::unwrap_used)]
|
#[allow(clippy::unwrap_used)]
|
||||||
impl git::repository::OpenRepositoryLike for MockOpenRepository {
|
impl git::repository::OpenRepositoryLike for FakeOpenRepository {
|
||||||
fn remote_branches(&self) -> git::push::Result<Vec<config::BranchName>> {
|
fn remote_branches(&self) -> git::push::Result<Vec<config::BranchName>> {
|
||||||
todo!("MockOpenRepository::remote_branched")
|
todo!("MockOpenRepository::remote_branched")
|
||||||
}
|
}
|
||||||
|
@ -118,4 +118,8 @@ impl git::repository::OpenRepositoryLike for MockOpenRepository {
|
||||||
) -> git::file::Result<String> {
|
) -> git::file::Result<String> {
|
||||||
todo!("MockOpenRepository::read_file")
|
todo!("MockOpenRepository::read_file")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn duplicate(&self) -> Box<dyn OpenRepositoryLike> {
|
||||||
|
Box::new(self.clone())
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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(
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
use crate as git;
|
use crate as git;
|
||||||
use crate::repository::RepositoryLike as _;
|
use crate::repository::RepositoryLike as _;
|
||||||
use git::tests::given;
|
use git::tests::given;
|
||||||
use git::tests::then;
|
|
||||||
use git_next_config as config;
|
use git_next_config as config;
|
||||||
|
|
||||||
use assert2::let_assert;
|
use assert2::let_assert;
|
||||||
|
@ -50,6 +49,7 @@ mod server_repo_config {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_repo() {
|
fn should_return_repo() {
|
||||||
let repo_path = given::a_name();
|
let repo_path = given::a_name();
|
||||||
|
@ -64,6 +64,7 @@ mod server_repo_config {
|
||||||
|
|
||||||
assert_eq!(src.repo(), config::RepoPath::new(repo_path));
|
assert_eq!(src.repo(), config::RepoPath::new(repo_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_branch() {
|
fn should_return_branch() {
|
||||||
let branch = given::a_name();
|
let branch = given::a_name();
|
||||||
|
@ -78,6 +79,7 @@ mod server_repo_config {
|
||||||
|
|
||||||
assert_eq!(src.branch(), config::BranchName::new(branch));
|
assert_eq!(src.branch(), config::BranchName::new(branch));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_gitdir() {
|
fn should_return_gitdir() {
|
||||||
let gitdir = given::a_name();
|
let gitdir = given::a_name();
|
||||||
|
@ -96,6 +98,7 @@ mod server_repo_config {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod repo_config {
|
mod repo_config {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -149,6 +152,7 @@ mod repo_config {
|
||||||
assert_eq!(repo_config.source(), config::RepoConfigSource::Repo);
|
assert_eq!(repo_config.source(), config::RepoConfigSource::Repo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod forge_config {
|
mod forge_config {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
@ -198,6 +202,7 @@ mod forge_config {
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_forge_type() {
|
fn should_return_forge_type() {
|
||||||
let forge_type = config::ForgeType::MockForge;
|
let forge_type = config::ForgeType::MockForge;
|
||||||
|
@ -209,6 +214,7 @@ mod forge_config {
|
||||||
|
|
||||||
assert_eq!(fc.forge_type(), config::ForgeType::MockForge);
|
assert_eq!(fc.forge_type(), config::ForgeType::MockForge);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_hostname() {
|
fn should_return_hostname() {
|
||||||
let forge_type = config::ForgeType::MockForge;
|
let forge_type = config::ForgeType::MockForge;
|
||||||
|
@ -220,6 +226,7 @@ mod forge_config {
|
||||||
|
|
||||||
assert_eq!(fc.hostname(), config::Hostname::new(hostname));
|
assert_eq!(fc.hostname(), config::Hostname::new(hostname));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_user() {
|
fn should_return_user() {
|
||||||
let forge_type = config::ForgeType::MockForge;
|
let forge_type = config::ForgeType::MockForge;
|
||||||
|
@ -231,6 +238,7 @@ mod forge_config {
|
||||||
|
|
||||||
assert_eq!(fc.user(), config::User::new(user));
|
assert_eq!(fc.user(), config::User::new(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_token() {
|
fn should_return_token() {
|
||||||
let forge_type = config::ForgeType::MockForge;
|
let forge_type = config::ForgeType::MockForge;
|
||||||
|
@ -242,6 +250,7 @@ mod forge_config {
|
||||||
|
|
||||||
assert_eq!(fc.token().expose_secret(), token.as_str());
|
assert_eq!(fc.token().expose_secret(), token.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_return_repo() {
|
fn should_return_repo() {
|
||||||
let forge_type = config::ForgeType::MockForge;
|
let forge_type = config::ForgeType::MockForge;
|
||||||
|
@ -266,6 +275,7 @@ mod forge_config {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut repos = BTreeMap::new();
|
let mut repos = BTreeMap::new();
|
||||||
repos.insert(red_name.clone(), red.clone());
|
repos.insert(red_name.clone(), red.clone());
|
||||||
repos.insert(blue_name, blue);
|
repos.insert(blue_name, blue);
|
||||||
|
@ -277,6 +287,27 @@ mod forge_config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mod remote_branches {
|
||||||
|
// use super::*;
|
||||||
|
// #[test]
|
||||||
|
// // assumes running in the git-next repo which should have main, next and dev as remote branches
|
||||||
|
// fn should_return_remote_branches() -> TestResult {
|
||||||
|
// let_assert!(Ok(fs) = kxio::fs::temp());
|
||||||
|
// let gitdir: config::GitDir = fs.base().to_path_buf().into();
|
||||||
|
// let test_repository = git::repository::test(fs.clone());
|
||||||
|
// let_assert!(Ok(open_repository) = test_repository.open(&gitdir));
|
||||||
|
// let repo_config = &given::a_repo_config();
|
||||||
|
// let branches = repo_config.branches();
|
||||||
|
// then::create_a_commit_on_branch(&fs, &gitdir, &branches.main())?;
|
||||||
|
// then::create_a_commit_on_branch(&fs, &gitdir, &branches.next())?;
|
||||||
|
// then::create_a_commit_on_branch(&fs, &gitdir, &branches.dev())?;
|
||||||
|
// let_assert!(Ok(remote_branches) = open_repository.remote_branches());
|
||||||
|
// assert!(remote_branches.contains(&branches.main()));
|
||||||
|
// assert!(remote_branches.contains(&branches.next()));
|
||||||
|
// assert!(remote_branches.contains(&branches.dev()));
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
mod find_default_remote {
|
mod find_default_remote {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -287,7 +318,7 @@ mod find_default_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::new().open(&gitdir));
|
let_assert!(Ok(repo) = crate::repository::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,
|
||||||
|
@ -304,37 +335,16 @@ mod fetch {
|
||||||
use git_next_config::GitDir;
|
use git_next_config::GitDir;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore] // requires authentication to the server
|
#[ignore] // requires authentication to the server - which the CI doesn't have
|
||||||
fn should_fetch_from_repo() {
|
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::new().open(&gitdir));
|
let_assert!(Ok(repo) = crate::repository::real().open(&gitdir));
|
||||||
let_assert!(Ok(_) = repo.fetch());
|
let_assert!(Ok(_) = repo.fetch());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod remote_branches {
|
|
||||||
use super::*;
|
|
||||||
#[test]
|
|
||||||
// assumes running in the git-next repo which should have main, next and dev as remote branches
|
|
||||||
fn should_return_remote_branches() -> TestResult {
|
|
||||||
let_assert!(Ok(fs) = kxio::fs::temp());
|
|
||||||
let gitdir: config::GitDir = fs.base().to_path_buf().into();
|
|
||||||
let test_repository = git::repository::test(fs.clone());
|
|
||||||
let_assert!(Ok(open_repository) = test_repository.open(&gitdir));
|
|
||||||
let repo_config = &given::a_repo_config();
|
|
||||||
let branches = repo_config.branches();
|
|
||||||
then::create_a_commit_on_branch(&fs, &gitdir, &branches.main())?;
|
|
||||||
then::create_a_commit_on_branch(&fs, &gitdir, &branches.next())?;
|
|
||||||
then::create_a_commit_on_branch(&fs, &gitdir, &branches.dev())?;
|
|
||||||
let_assert!(Ok(remote_branches) = open_repository.remote_branches());
|
|
||||||
assert!(remote_branches.contains(&branches.main()));
|
|
||||||
assert!(remote_branches.contains(&branches.next()));
|
|
||||||
assert!(remote_branches.contains(&branches.dev()));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mod commit_log {
|
mod commit_log {
|
||||||
use git::tests::given;
|
use git::tests::given;
|
||||||
|
|
||||||
|
@ -407,6 +417,7 @@ mod commit_log {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod read_file {
|
mod read_file {
|
||||||
|
|
||||||
use git::tests::given;
|
use git::tests::given;
|
||||||
|
|
|
@ -1,173 +1,100 @@
|
||||||
use crate as git;
|
use crate as git;
|
||||||
|
|
||||||
mod validate {
|
mod validate {
|
||||||
use crate::{validation::repo::validate_repo, GitRemote, RepoDetails};
|
use crate::{tests::given, validation::repo::validate_repo};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use assert2::let_assert;
|
use git::repository::Direction;
|
||||||
use git_next_config::{ForgeDetails, GitDir, Hostname, RepoPath};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_ok_a_valid_repo() {
|
fn should_ok_a_valid_repo() {
|
||||||
let repo_details = RepoDetails::default()
|
let fs = given::a_filesystem();
|
||||||
.with_forge(
|
let repo_details = given::repo_details(&fs);
|
||||||
ForgeDetails::default().with_hostname(Hostname::new("localhost".to_string())),
|
let repo_details_mock = repo_details.clone();
|
||||||
)
|
|
||||||
.with_repo_path(RepoPath::new("kemitix/test".to_string()));
|
|
||||||
let gitdir = GitDir::from("foo");
|
|
||||||
let remote = GitRemote::new(
|
|
||||||
Hostname::new("localhost"),
|
|
||||||
RepoPath::new("kemitix/test".to_string()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut mock_repository = git::repository::mock();
|
let mut open_repository = git::repository::open::mock();
|
||||||
{
|
open_repository
|
||||||
let mut mock_open_repo = mock_repository.given_can_be_opened(&gitdir);
|
.expect_find_default_remote()
|
||||||
mock_open_repo
|
.returning(move |_direction| Some(repo_details_mock.git_remote()));
|
||||||
.given_has_default_remote(git::repository::Direction::Push, Some(remote.clone()));
|
|
||||||
mock_open_repo
|
let result = validate_repo(&*open_repository, &repo_details);
|
||||||
.given_has_default_remote(git::repository::Direction::Fetch, Some(remote));
|
println!("{result:?}");
|
||||||
}
|
assert!(result.is_ok());
|
||||||
let (repository, _mock_repository) = mock_repository.seal();
|
|
||||||
let_assert!(Ok(open_repository) = repository.open(&gitdir));
|
|
||||||
let_assert!(Ok(_) = validate_repo(&open_repository, &repo_details));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_fail_where_no_default_push_remote() {
|
fn should_fail_where_no_default_push_remote() {
|
||||||
let repo_details = RepoDetails::default()
|
let fs = given::a_filesystem();
|
||||||
.with_forge(
|
let repo_details = given::repo_details(&fs);
|
||||||
ForgeDetails::default().with_hostname(Hostname::new("localhost".to_string())),
|
let repo_details_mock = repo_details.clone();
|
||||||
)
|
|
||||||
.with_repo_path(RepoPath::new("kemitix/test".to_string()));
|
|
||||||
let gitdir = GitDir::from("foo");
|
|
||||||
let remote = GitRemote::new(
|
|
||||||
Hostname::new("localhost"),
|
|
||||||
RepoPath::new("kemitix/test".to_string()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut mock_repository = git::repository::mock();
|
let mut open_repository = git::repository::open::mock();
|
||||||
{
|
open_repository
|
||||||
let mut mock_open_repo = mock_repository.given_can_be_opened(&gitdir);
|
.expect_find_default_remote()
|
||||||
mock_open_repo.given_has_default_remote(git::repository::Direction::Push, None);
|
.returning(move |direction| match direction {
|
||||||
mock_open_repo
|
Direction::Push => None,
|
||||||
.given_has_default_remote(git::repository::Direction::Fetch, Some(remote));
|
Direction::Fetch => Some(repo_details_mock.git_remote()),
|
||||||
}
|
});
|
||||||
let (repository, _mock_repository) = mock_repository.seal();
|
|
||||||
let_assert!(Ok(open_repository) = repository.open(&gitdir));
|
let result = validate_repo(&*open_repository, &repo_details);
|
||||||
let_assert!(Err(_) = validate_repo(&open_repository, &repo_details));
|
println!("{result:?}");
|
||||||
|
assert!(result.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_fail_where_no_default_fetch_remote() {
|
fn should_fail_where_no_default_fetch_remote() {
|
||||||
let repo_details = RepoDetails::default()
|
let fs = given::a_filesystem();
|
||||||
.with_forge(
|
let repo_details = given::repo_details(&fs);
|
||||||
ForgeDetails::default().with_hostname(Hostname::new("localhost".to_string())),
|
let repo_details_mock = repo_details.clone();
|
||||||
)
|
|
||||||
.with_repo_path(RepoPath::new("kemitix/test".to_string()));
|
|
||||||
let gitdir = GitDir::from("foo");
|
|
||||||
let remote = GitRemote::new(
|
|
||||||
Hostname::new("localhost"),
|
|
||||||
RepoPath::new("kemitix/test".to_string()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut mock_repository = git::repository::mock();
|
let mut open_repository = git::repository::open::mock();
|
||||||
{
|
open_repository
|
||||||
let mut mock_open_repo = mock_repository.given_can_be_opened(&gitdir);
|
.expect_find_default_remote()
|
||||||
mock_open_repo.given_has_default_remote(git::repository::Direction::Push, None);
|
.returning(move |direction| match direction {
|
||||||
mock_open_repo
|
Direction::Push => Some(repo_details_mock.git_remote()),
|
||||||
.given_has_default_remote(git::repository::Direction::Fetch, Some(remote));
|
Direction::Fetch => None,
|
||||||
}
|
});
|
||||||
let (repository, _mock_repository) = mock_repository.seal();
|
|
||||||
let_assert!(Ok(open_repository) = repository.open(&gitdir));
|
let result = validate_repo(&*open_repository, &repo_details);
|
||||||
let_assert!(Err(_) = validate_repo(&open_repository, &repo_details));
|
println!("{result:?}");
|
||||||
|
assert!(result.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_fail_where_invalid_default_push_remote() {
|
fn should_fail_where_invalid_default_push_remote() {
|
||||||
let repo_details = RepoDetails::default()
|
let fs = given::a_filesystem();
|
||||||
.with_forge(
|
let repo_details = given::repo_details(&fs);
|
||||||
ForgeDetails::default().with_hostname(Hostname::new("localhost".to_string())),
|
let repo_details_mock = repo_details.clone();
|
||||||
)
|
|
||||||
.with_repo_path(RepoPath::new("kemitix/test".to_string()));
|
|
||||||
let gitdir = GitDir::from("foo");
|
|
||||||
let remote = GitRemote::new(
|
|
||||||
Hostname::new("localhost"),
|
|
||||||
RepoPath::new("kemitix/test".to_string()),
|
|
||||||
);
|
|
||||||
let other_remote = GitRemote::new(
|
|
||||||
Hostname::new("localhost"),
|
|
||||||
RepoPath::new("kemitix/other".to_string()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut mock_repository = git::repository::mock();
|
let mut open_repository = git::repository::open::mock();
|
||||||
{
|
open_repository
|
||||||
let mut mock_open_repo = mock_repository.given_can_be_opened(&gitdir);
|
.expect_find_default_remote()
|
||||||
mock_open_repo
|
.returning(move |direction| match direction {
|
||||||
.given_has_default_remote(git::repository::Direction::Push, Some(other_remote));
|
Direction::Push => Some(given::a_git_remote()),
|
||||||
mock_open_repo
|
Direction::Fetch => Some(repo_details_mock.git_remote()),
|
||||||
.given_has_default_remote(git::repository::Direction::Fetch, Some(remote));
|
});
|
||||||
}
|
|
||||||
let (repository, _mock_repository) = mock_repository.seal();
|
let result = validate_repo(&*open_repository, &repo_details);
|
||||||
let_assert!(Ok(open_repository) = repository.open(&gitdir));
|
println!("{result:?}");
|
||||||
let_assert!(Err(_) = validate_repo(&open_repository, &repo_details));
|
assert!(result.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_fail_where_invalid_default_fetch_remote() {
|
fn should_fail_where_invalid_default_fetch_remote() {
|
||||||
let repo_details = RepoDetails::default()
|
let fs = given::a_filesystem();
|
||||||
.with_forge(
|
let repo_details = given::repo_details(&fs);
|
||||||
ForgeDetails::default().with_hostname(Hostname::new("localhost".to_string())),
|
let repo_details_mock = repo_details.clone();
|
||||||
)
|
|
||||||
.with_repo_path(RepoPath::new("kemitix/test".to_string()));
|
|
||||||
let gitdir = GitDir::from("foo");
|
|
||||||
let remote = GitRemote::new(
|
|
||||||
Hostname::new("localhost"),
|
|
||||||
RepoPath::new("kemitix/test".to_string()),
|
|
||||||
);
|
|
||||||
let other_remote = GitRemote::new(
|
|
||||||
Hostname::new("localhost"),
|
|
||||||
RepoPath::new("kemitix/other".to_string()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut mock_repository = git::repository::mock();
|
let mut open_repository = git::repository::open::mock();
|
||||||
{
|
open_repository
|
||||||
let mut mock_open_repo = mock_repository.given_can_be_opened(&gitdir);
|
.expect_find_default_remote()
|
||||||
mock_open_repo.given_has_default_remote(git::repository::Direction::Push, Some(remote));
|
.returning(move |direction| match direction {
|
||||||
mock_open_repo
|
Direction::Push => Some(repo_details_mock.git_remote()),
|
||||||
.given_has_default_remote(git::repository::Direction::Fetch, Some(other_remote));
|
Direction::Fetch => Some(given::a_git_remote()),
|
||||||
}
|
});
|
||||||
let (repository, _mock_repository) = mock_repository.seal();
|
|
||||||
let_assert!(Ok(open_repository) = repository.open(&gitdir));
|
let result = validate_repo(&*open_repository, &repo_details);
|
||||||
let_assert!(Err(_) = validate_repo(&open_repository, &repo_details));
|
println!("{result:?}");
|
||||||
}
|
assert!(result.is_err());
|
||||||
}
|
|
||||||
|
|
||||||
mod git_clone {
|
|
||||||
use super::*;
|
|
||||||
use assert2::let_assert;
|
|
||||||
use git_next_config::{ForgeDetails, GitDir, Hostname, RepoPath};
|
|
||||||
|
|
||||||
use crate::{GitRemote, RepoDetails};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[ignore] // slow test ~1.5 seconds
|
|
||||||
fn should_clone_repo() {
|
|
||||||
let_assert!(Ok(fs) = kxio::fs::temp());
|
|
||||||
let r = crate::repository::new();
|
|
||||||
let repo_details = RepoDetails::default()
|
|
||||||
.with_forge(
|
|
||||||
ForgeDetails::default().with_hostname(Hostname::new("git.kemitix.net".to_string())),
|
|
||||||
)
|
|
||||||
.with_gitdir(GitDir::new(fs.base()))
|
|
||||||
.with_repo_path(RepoPath::new("kemitix/git-next".to_string()));
|
|
||||||
let_assert!(Ok(open_repo) = r.git_clone(&repo_details));
|
|
||||||
let_assert!(
|
|
||||||
Some(remote) = open_repo.find_default_remote(git::repository::Direction::Fetch)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
remote,
|
|
||||||
GitRemote::new(
|
|
||||||
Hostname::new("git.kemitix.net"),
|
|
||||||
RepoPath::new("kemitix/git-next".to_string())
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use crate as git;
|
use crate as git;
|
||||||
use git_next_config as config;
|
use git_next_config as config;
|
||||||
|
|
||||||
|
@ -102,37 +104,38 @@ mod push {
|
||||||
|
|
||||||
mod reset {
|
mod reset {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{tests::given, OpenRepository};
|
use crate::tests::given;
|
||||||
use assert2::let_assert;
|
use assert2::let_assert;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_perform_a_fetch_then_push() {
|
fn should_perform_a_fetch_then_push() {
|
||||||
|
let mut open_repository = git::repository::open::mock();
|
||||||
|
let mut seq = mockall::Sequence::new();
|
||||||
|
open_repository
|
||||||
|
.expect_fetch()
|
||||||
|
.times(1)
|
||||||
|
.in_sequence(&mut seq)
|
||||||
|
.returning(|| Ok(()));
|
||||||
|
open_repository
|
||||||
|
.expect_push()
|
||||||
|
.times(1)
|
||||||
|
.in_sequence(&mut seq)
|
||||||
|
.returning(|_repo_details, _branch_name, _gitref, _force| Ok(()));
|
||||||
|
|
||||||
let fs = given::a_filesystem();
|
let fs = given::a_filesystem();
|
||||||
let (mock_open_repository, gitdir, mock_repository) = given::an_open_repository(&fs);
|
|
||||||
let open_repository: OpenRepository = mock_open_repository.into();
|
|
||||||
let repo_details = given::repo_details(&fs);
|
let repo_details = given::repo_details(&fs);
|
||||||
let branch_name = &repo_details.branch;
|
let branch_name = &repo_details.branch;
|
||||||
let commit = given::a_commit();
|
let commit = given::a_commit();
|
||||||
let gitref = GitRef::from(commit);
|
let gitref = GitRef::from(commit);
|
||||||
let_assert!(
|
let_assert!(
|
||||||
Ok(_) = git::push::reset(
|
Ok(_) = git::push::reset(
|
||||||
&open_repository,
|
&*open_repository,
|
||||||
&repo_details,
|
&repo_details,
|
||||||
branch_name,
|
branch_name,
|
||||||
&gitref,
|
&gitref,
|
||||||
&git::push::Force::No
|
&git::push::Force::No
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
let_assert!(Some(mock_open_repository) = mock_repository.get(&gitdir));
|
|
||||||
let operations = mock_open_repository.operations();
|
|
||||||
let forge_alias = repo_details.forge.forge_alias();
|
|
||||||
let repo_alias = &repo_details.repo_alias;
|
|
||||||
let to_commit = gitref;
|
|
||||||
let force = "fast-forward";
|
|
||||||
assert_eq!(
|
|
||||||
operations,
|
|
||||||
vec![format!("fetch"), format!("push fa:{forge_alias} ra:{repo_alias} bn:{branch_name} tc:{to_commit} f:{force}")]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,7 +218,7 @@ pub mod given {
|
||||||
//
|
//
|
||||||
use crate::{
|
use crate::{
|
||||||
self as git,
|
self as git,
|
||||||
repository::{MockOpenRepository, MockRepository},
|
repository::{FakeOpenRepository, FakeRepository},
|
||||||
tests::given,
|
tests::given,
|
||||||
};
|
};
|
||||||
use config::{
|
use config::{
|
||||||
|
@ -348,12 +351,19 @@ pub mod given {
|
||||||
|
|
||||||
pub fn an_open_repository(
|
pub fn an_open_repository(
|
||||||
fs: &kxio::fs::FileSystem,
|
fs: &kxio::fs::FileSystem,
|
||||||
) -> (MockOpenRepository, GitDir, MockRepository) {
|
) -> (FakeOpenRepository, GitDir, FakeRepository) {
|
||||||
let mut mock = git::repository::mock();
|
let mut mock = git::repository::fake();
|
||||||
let gitdir = a_git_dir(fs);
|
let gitdir = a_git_dir(fs);
|
||||||
let or = mock.given_can_be_opened(&gitdir);
|
let or = mock.given_can_be_opened(&gitdir);
|
||||||
(or, gitdir, mock)
|
(or, gitdir, mock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn a_git_remote() -> git::GitRemote {
|
||||||
|
git::GitRemote::new(
|
||||||
|
config::Hostname::new(given::a_name()),
|
||||||
|
config::RepoPath::new(given::a_name()),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub mod then {
|
pub mod then {
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
|
@ -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();
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ fn repo_details_find_default_push_remote_finds_correct_remote() -> Result<()> {
|
||||||
.with_hostname(Hostname::new("git.kemitix.net"));
|
.with_hostname(Hostname::new("git.kemitix.net"));
|
||||||
repo_details.repo_path = RepoPath::new("kemitix/git-next".to_string());
|
repo_details.repo_path = RepoPath::new("kemitix/git-next".to_string());
|
||||||
let gitdir = &repo_details.gitdir;
|
let gitdir = &repo_details.gitdir;
|
||||||
let repository = git::repository::new().open(gitdir)?;
|
let repository = git::repository::mock().open(gitdir)?;
|
||||||
let_assert!(
|
let_assert!(
|
||||||
Some(found_git_remote) = repository.find_default_remote(Direction::Push),
|
Some(found_git_remote) = repository.find_default_remote(Direction::Push),
|
||||||
"Default Push Remote not found"
|
"Default Push Remote not found"
|
||||||
|
@ -91,8 +91,8 @@ fn gitdir_validate_should_pass_a_valid_git_repo() -> Result<()> {
|
||||||
.with_hostname(Hostname::new("git.kemitix.net"));
|
.with_hostname(Hostname::new("git.kemitix.net"));
|
||||||
repo_details.repo_path = RepoPath::new("kemitix/git-next".to_string());
|
repo_details.repo_path = RepoPath::new("kemitix/git-next".to_string());
|
||||||
let gitdir = &repo_details.gitdir;
|
let gitdir = &repo_details.gitdir;
|
||||||
let repository = git::repository::new().open(gitdir)?;
|
let repository = git::repository::mock().open(gitdir)?;
|
||||||
validate_repo(&repository, &repo_details)?;
|
validate_repo(&*repository, &repo_details)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -112,8 +112,8 @@ fn gitdir_validate_should_fail_a_git_repo_with_wrong_remote() -> Result<()> {
|
||||||
);
|
);
|
||||||
repo_details.repo_path = RepoPath::new("hello/world".to_string());
|
repo_details.repo_path = RepoPath::new("hello/world".to_string());
|
||||||
let gitdir = &repo_details.gitdir;
|
let gitdir = &repo_details.gitdir;
|
||||||
let repository = git::repository::new().open(gitdir)?;
|
let repository = git::repository::mock().open(gitdir)?;
|
||||||
let_assert!(Err(_) = validate_repo(&repository, &repo_details));
|
let_assert!(Err(_) = validate_repo(&*repository, &repo_details));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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