Radish alpha
r
rad:z6cFWeWpnZNHh9rUW8phgA3b5yGt
Git libraries for Radicle
Radicle
Git
radicle-git radicle-git-ext t src repository.rs
use std::{convert::Infallible, io, path::Path};

use git2::Oid;
use radicle_git_ext::{commit::CommitData, ref_format::RefString};
use test_helpers::tempdir::{self, WithTmpDir};

use crate::gen::commit::{self, TreeData};

pub struct Fixture {
    pub inner: WithTmpDir<git2::Repository>,
    pub head: Option<git2::Oid>,
}

/// Initialise a [`git2::Repository`] in a temporary directory.
///
/// The provided `commits` will be added to the repository, and the
/// head commit will be returned.
pub fn fixture(
    refname: &RefString,
    commits: Vec<CommitData<TreeData, Infallible>>,
) -> io::Result<Fixture> {
    let repo = tempdir::WithTmpDir::new(|path| git2::Repository::init(path).map_err(io_other))?;
    let commits = commit::write_commits(&repo, commits).map_err(io_other)?;
    let head = commits.last().copied();

    if let Some(head) = head {
        repo.reference(refname.as_str(), head, false, "Initialise repository")
            .map_err(io_other)?;
    }

    Ok(Fixture { inner: repo, head })
}

pub fn bare_fixture(
    refname: &RefString,
    commits: Vec<CommitData<TreeData, Infallible>>,
) -> io::Result<Fixture> {
    let repo =
        tempdir::WithTmpDir::new(|path| git2::Repository::init_bare(path).map_err(io_other))?;
    let commits = commit::write_commits(&repo, commits).map_err(io_other)?;
    let head = commits.last().copied();

    if let Some(head) = head {
        repo.reference(refname.as_str(), head, false, "Initialise repository")
            .map_err(io_other)?;
    }

    Ok(Fixture { inner: repo, head })
}

pub fn submodule<'a>(
    parent: &'a git2::Repository,
    child: &'a git2::Repository,
    refname: &RefString,
    head: Oid,
    author: &git2::Signature,
) -> io::Result<git2::Submodule<'a>> {
    let url = format!("file://{}", child.path().canonicalize()?.display());
    let mut sub = parent
        .submodule(url.as_str(), Path::new("submodule"), true)
        .map_err(io_other)?;
    sub.open().map_err(io_other)?;
    sub.clone(Some(&mut git2::SubmoduleUpdateOptions::default()))
        .map_err(io_other)?;
    sub.add_to_index(true).map_err(io_other)?;
    sub.add_finalize().map_err(io_other)?;
    {
        let mut ix = parent.index().map_err(io_other)?;
        let tree = ix.write_tree_to(parent).map_err(io_other)?;
        let tree = parent.find_tree(tree).map_err(io_other)?;
        let head = parent.find_commit(head).map_err(io_other)?;
        parent
            .commit(
                Some(refname.as_str()),
                author,
                author,
                "Commit submodule",
                &tree,
                &[&head],
            )
            .map_err(io_other)?;
    }
    Ok(sub)
}

fn io_other<E>(e: E) -> io::Error
where
    E: std::error::Error + Send + Sync + 'static,
{
    io::Error::other(e)
}