git-next-core 0.14.1

core for git-next, the trunk-based development manager
Documentation
//
#[cfg(test)]
mod tests;

pub mod oreal;
pub mod otest;

use crate::{
    git,
    git::repository::{
        open::{oreal::RealOpenRepository, otest::TestOpenRepository},
        Direction,
    },
    BranchName, GitDir, RemoteUrl,
};

use std::{
    path::Path,
    sync::{Arc, RwLock},
};

#[allow(clippy::module_name_repetitions)]
#[derive(Clone, Debug)]
pub enum OpenRepository {
    /// A real git repository.
    ///
    /// This variant is the normal implementation for use in production code.
    Real(RealOpenRepository),

    /// A real git repository, but with preprogrammed responses to network access.
    ///
    /// This variant is for use only in testing. Requests to methods
    /// that would require network access, such as to the git remote
    /// server will result in an error, unless a predefined change
    /// has been scheduled for that request.
    Test(TestOpenRepository),
}

#[cfg(not(tarpaulin_include))]
pub fn real(gix_repo: gix::Repository, forge_details: crate::ForgeDetails) -> OpenRepository {
    OpenRepository::Real(oreal::RealOpenRepository::new(
        Arc::new(RwLock::new(gix_repo.into())),
        forge_details,
    ))
}

#[cfg(not(tarpaulin_include))] // don't test mocks
pub(crate) fn test(
    gitdir: &GitDir,
    fs: &kxio::fs::FileSystem,
    on_fetch: Vec<otest::OnFetch>,
    on_push: Vec<otest::OnPush>,
    forge_details: crate::ForgeDetails,
) -> OpenRepository {
    OpenRepository::Test(TestOpenRepository::new(
        gitdir,
        fs,
        on_fetch,
        on_push,
        forge_details,
    ))
}

#[allow(clippy::module_name_repetitions)]
#[mockall::automock]
pub trait OpenRepositoryLike: std::fmt::Debug + Sync + Send {
    /// Creates a clone of the `OpenRepositoryLike`.
    fn duplicate(&self) -> Box<dyn OpenRepositoryLike>;

    /// Returns a `Vec` of all the branches in the remote repo.
    ///
    /// # Errors
    ///
    ///  Will return `Err` if there are any network connectivity issues with
    ///  the remote server.
    fn remote_branches(&self) -> git::push::Result<Vec<BranchName>>;
    fn find_default_remote(&self, direction: Direction) -> Option<RemoteUrl>;

    /// Performs a `git fetch`
    ///
    /// # Errors
    ///
    /// Will return an `Err` if their is no remote fetch defined in .git/config, or
    /// if there are any network connectivity issues with the remote server.
    fn fetch(&self) -> Result<(), git::fetch::Error>;

    /// Performs a `git push`
    ///
    /// # Errors
    ///
    /// Will return an `Err` if their is no remote push defined in .git/config, or
    /// if there are any network connectivity issues with the remote server.
    fn push(
        &self,
        repo_details: &git::RepoDetails,
        branch_name: &BranchName,
        to_commit: &git::GitRef,
        force: &git::push::Force,
    ) -> git::push::Result<()>;

    /// List of commits in a branch, optionally up-to any specified commit.
    ///
    /// # Errors
    ///
    /// Will return `Err` if there are any problems with the branch name being invalid, or any
    /// corruption of the git repository.
    fn commit_log(
        &self,
        branch_name: &BranchName,
        find_commits: &[git::Commit],
    ) -> git::commit::log::Result<Vec<git::Commit>>;

    /// Read the contents of a file as a string.
    ///
    /// Only handles files in the root of the repo.
    ///
    /// # Errors
    ///
    /// Will return `Err` if the file does not exists on the specified branch.
    fn read_file(&self, branch_name: &BranchName, file_name: &Path) -> git::file::Result<String>;
}

#[cfg(test)]
pub(crate) fn mock() -> Box<MockOpenRepositoryLike> {
    Box::new(MockOpenRepositoryLike::new())
}

impl std::ops::Deref for OpenRepository {
    type Target = dyn OpenRepositoryLike;

    fn deref(&self) -> &Self::Target {
        match self {
            Self::Real(real) => real,
            Self::Test(test) => test,
        }
    }
}