use super::RepoDetails;
use crate::repository::test::TestRepository;
use crate::validation::remotes::validate_default_remotes;
pub use factory::RepositoryFactory;
use git_next_config::{GitDir, RemoteUrl};
pub use open::otest::OnFetch;
pub use open::otest::OnPush;
pub use open::OpenRepository;
pub use open::OpenRepositoryLike;
pub use open::RealOpenRepository;
use tracing::info;
pub mod factory;
pub mod open;
mod test;
#[cfg(test)]
mod tests;
#[derive(Clone, Debug)]
#[allow(clippy::large_enum_variant)]
pub enum Repository {
Real,
Test(TestRepository),
}
pub const fn test(fs: kxio::fs::FileSystem) -> TestRepository {
TestRepository::new(fs, vec![], vec![])
}
#[tracing::instrument(skip_all)]
#[cfg(not(tarpaulin_include))] pub fn open(
repository_factory: &dyn factory::RepositoryFactory,
repo_details: &RepoDetails,
) -> Result<Box<dyn OpenRepositoryLike>> {
let open_repository = if !repo_details.gitdir.exists() {
info!("Local copy not found - cloning...");
repository_factory.git_clone(repo_details)?
} else {
info!("Local copy found - opening...");
repository_factory.open(repo_details)?
};
info!("Validating...");
validate_default_remotes(&*open_repository, repo_details)
.map_err(|e| Error::Validation(e.to_string()))?;
Ok(open_repository)
}
pub trait RepositoryLike {
fn open(&self, gitdir: &GitDir) -> Result<OpenRepository>;
fn git_clone(&self, repo_details: &RepoDetails) -> Result<OpenRepository>;
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum Direction {
Push,
Fetch,
}
impl From<Direction> for gix::remote::Direction {
fn from(value: Direction) -> Self {
match value {
Direction::Push => Self::Push,
Direction::Fetch => Self::Fetch,
}
}
}
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("invalid git dir: {0}")]
InvalidGitDir(git_next_config::GitDir),
#[error("kxiofs: {0}")]
KxioFs(#[from] kxio::fs::Error),
#[error("io: {0}")]
Io(std::io::Error),
#[error("git exec wait: {0}")]
Wait(std::io::Error),
#[error("git exec spawn: {0}")]
Spawn(std::io::Error),
#[error("validation: {0}")]
Validation(String),
#[error("git clone: {0}")]
Clone(String),
#[error("open: {0}")]
Open(String),
#[error("git fetch: {0}")]
Fetch(String),
#[error("fake repository lock")]
FakeLock,
#[error("MismatchDefaultFetchRemote(found: {found:?}, expected: {expected:?})")]
MismatchDefaultFetchRemote {
found: Box<RemoteUrl>,
expected: Box<RemoteUrl>,
},
}
mod gix_errors {
#![cfg(not(tarpaulin_include))] use super::Error;
impl From<gix::clone::Error> for Error {
fn from(value: gix::clone::Error) -> Self {
Self::Clone(value.to_string())
}
}
impl From<gix::open::Error> for Error {
fn from(value: gix::open::Error) -> Self {
Self::Open(value.to_string())
}
}
impl From<gix::clone::fetch::Error> for Error {
fn from(value: gix::clone::fetch::Error) -> Self {
Self::Fetch(value.to_string())
}
}
}