radicle/git/raw: Capture all `git2` re-exports

A refactoring internal to the `radicle` crate, with the goal of
making dependency on `git2` clearer and more controlled.
`radicle::git::raw` is changed from a complete re-export of `git2`
to a module that selectively re-exports (many) members of `git2`.
required to build the workspace (potentially breaking dependents
outside the workspace, but given just how many types are
re-exported, this seems unlikely).

In the future, no more `use git2::…` statements should be added
outside of `crates/radicle/src/git/raw.rs`. This is in an effort to
decrease dependence on `git2` in the future.
This commit is contained in:
Lorenz Leutgeb 2025-10-04 11:59:26 +02:00
parent 633059040c
commit 880634acd4
No known key found for this signature in database
23 changed files with 285 additions and 215 deletions

View File

@ -126,7 +126,7 @@ pub enum ApplyError {
#[error("document does not contain any changes to current identity")]
DocUnchanged,
#[error("git: {0}")]
Git(#[from] git2::Error),
Git(#[from] crate::git::raw::Error),
#[error("git: {0}")]
GitExt(#[from] git_ext::Error),
#[error("identity document error: {0}")]

View File

@ -21,7 +21,7 @@ pub enum OpEncodingError {
#[error("encoding failed: {0}")]
Encoding(#[from] serde_json::Error),
#[error("git: {0}")]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
}
#[derive(Error, Debug)]

View File

@ -8,6 +8,7 @@ use std::marker::PhantomData;
use serde::Deserialize;
use crate::git;
use crate::git::Oid;
use super::{ObjectId, Op, TypeName};
@ -92,7 +93,7 @@ impl HasRoot for CobRange {
///
/// To construct a `Stream`, use [`Stream::new`].
pub struct Stream<'a, A> {
repo: &'a git2::Repository,
repo: &'a git::raw::Repository,
range: CobRange,
typename: TypeName,
marker: PhantomData<A>,
@ -101,7 +102,7 @@ pub struct Stream<'a, A> {
impl<'a, A> Stream<'a, A> {
/// Construct a new stream providing the underlying `repo`, a [`CobRange`],
/// and the [`TypeName`] of the COB that is being streamed.
pub fn new(repo: &'a git2::Repository, range: CobRange, typename: TypeName) -> Self {
pub fn new(repo: &'a git::raw::Repository, range: CobRange, typename: TypeName) -> Self {
Self {
repo,
range,
@ -185,7 +186,7 @@ mod tests {
"xyz.radicle.test".parse::<TypeName>().unwrap()
}
fn gen_ops(repo: &git2::Repository, signer: &MockSigner) -> Vec<cob::Entry> {
fn gen_ops(repo: &git::raw::Repository, signer: &MockSigner) -> Vec<cob::Entry> {
// Number of ops
let n = gen::<u8>(1).clamp(1, 10);
let mut entries = Vec::with_capacity(n.into());
@ -213,7 +214,7 @@ mod tests {
}
fn create_entry(
repo: &git2::Repository,
repo: &git::raw::Repository,
signer: &MockSigner,
contents: NonEmpty<Vec<u8>>,
parent: Option<Oid>,

View File

@ -22,7 +22,7 @@ impl Stream {
#[derive(Debug, Error)]
pub enum Ops {
#[error("failed to get a commit while iterating over stream: {source}")]
Commit { source: git2::Error },
Commit { source: crate::git::raw::Error },
#[error("failed to load COB operation: {source}")]
Load { source: op::LoadError },
#[error("failed to load COB manifest: {source}")]

View File

@ -39,7 +39,7 @@ impl From<PatternString> for Until {
/// from.
pub(super) struct WalkIter<'a> {
/// Git repository for looking up the commit object during the revwalk.
repo: &'a git2::Repository,
repo: &'a git::raw::Repository,
/// The root commit that is being walked from.
///
/// N.b. This is required since ranges are non-inclusive in Git, and if the
@ -47,7 +47,7 @@ pub(super) struct WalkIter<'a> {
/// error.
from: Option<Oid>,
/// The revwalk that is being iterated over.
inner: git2::Revwalk<'a>,
inner: git::raw::Revwalk<'a>,
}
impl From<CobRange> for Walk {
@ -76,10 +76,10 @@ impl Walk {
}
/// Get the iterator for the walk.
pub(super) fn iter(self, repo: &git2::Repository) -> Result<WalkIter<'_>, git2::Error> {
pub(super) fn iter(self, repo: &git::raw::Repository) -> Result<WalkIter<'_>, git::raw::Error> {
let mut walk = repo.revwalk()?;
// N.b. ensure that we start from the `self.from` commit.
walk.set_sorting(git2::Sort::TOPOLOGICAL.union(git2::Sort::REVERSE))?;
walk.set_sorting(git::raw::Sort::TOPOLOGICAL.union(git::raw::Sort::REVERSE))?;
match self.until {
Until::Tip(tip) => walk.push_range(&format!("{}..{}", self.from, tip))?,
Until::Glob(glob) => {
@ -97,7 +97,7 @@ impl Walk {
}
impl<'a> Iterator for WalkIter<'a> {
type Item = Result<git2::Commit<'a>, git2::Error>;
type Item = Result<git::raw::Commit<'a>, git::raw::Error>;
fn next(&mut self) -> Option<Self::Item> {
// N.b. ensure that we start using the `from` commit and use the revwalk

View File

@ -1,4 +1,5 @@
pub mod canonical;
pub mod raw;
use std::io;
use std::path::Path;
@ -20,7 +21,6 @@ pub use ext::is_not_found_err;
pub use ext::Error;
pub use ext::NotFound;
pub use ext::Oid;
pub use git2 as raw;
pub use git_ext::ref_format as fmt;
pub use git_ext::ref_format::{
component, lit, name, qualified, refname, refspec,
@ -173,13 +173,13 @@ pub enum RefError {
err: Box<dyn std::error::Error + Send + Sync + 'static>,
},
#[error(transparent)]
Other(#[from] git2::Error),
Other(#[from] raw::Error),
}
#[derive(thiserror::Error, Debug)]
pub enum ListRefsError {
#[error("git error: {0}")]
Git(#[from] git2::Error),
Git(#[from] raw::Error),
#[error("invalid ref: {0}")]
InvalidRef(#[from] RefError),
}
@ -189,7 +189,7 @@ pub mod refs {
use radicle_cob as cob;
/// Try to get a qualified reference from a generic reference.
pub fn qualified_from<'a>(r: &'a git2::Reference) -> Result<(Qualified<'a>, Oid), RefError> {
pub fn qualified_from<'a>(r: &'a raw::Reference) -> Result<(Qualified<'a>, Oid), RefError> {
let name = r.name().ok_or(RefError::InvalidName)?;
let refstr = RefStr::try_from_str(name)?;
let target = r.resolve()?.target().ok_or(RefError::NoTarget)?;
@ -462,9 +462,9 @@ pub mod refs {
pub fn remote_refs(url: &Url) -> Result<RandomMap<RemoteId, Refs>, ListRefsError> {
let url = url.to_string();
let mut remotes = RandomMap::default();
let mut remote = git2::Remote::create_detached(url)?;
let mut remote = raw::Remote::create_detached(url)?;
remote.connect(git2::Direction::Fetch)?;
remote.connect(raw::Direction::Fetch)?;
let refs = remote.list()?;
for r in refs {
@ -557,9 +557,9 @@ where
/// Create an initial empty commit.
pub fn initial_commit<'a>(
repo: &'a git2::Repository,
sig: &git2::Signature,
) -> Result<git2::Commit<'a>, git2::Error> {
repo: &'a raw::Repository,
sig: &raw::Signature,
) -> Result<raw::Commit<'a>, raw::Error> {
let tree_id = repo.index()?.write_tree()?;
let tree = repo.find_tree(tree_id)?;
let oid = repo.commit(None, sig, sig, "Initial commit", &tree, &[])?;
@ -570,13 +570,13 @@ pub fn initial_commit<'a>(
/// Create a commit and update the given ref to it.
pub fn commit<'a>(
repo: &'a git2::Repository,
parent: &'a git2::Commit,
repo: &'a raw::Repository,
parent: &'a raw::Commit,
target: &RefStr,
message: &str,
sig: &git2::Signature,
tree: &git2::Tree,
) -> Result<git2::Commit<'a>, git2::Error> {
sig: &raw::Signature,
tree: &raw::Tree,
) -> Result<raw::Commit<'a>, raw::Error> {
let oid = repo.commit(Some(target.as_str()), sig, sig, message, tree, &[parent])?;
let commit = repo.find_commit(oid)?;
@ -585,12 +585,12 @@ pub fn commit<'a>(
/// Create an empty commit on top of the parent.
pub fn empty_commit<'a>(
repo: &'a git2::Repository,
parent: &'a git2::Commit,
repo: &'a raw::Repository,
parent: &'a raw::Commit,
target: &RefStr,
message: &str,
sig: &git2::Signature,
) -> Result<git2::Commit<'a>, git2::Error> {
sig: &raw::Signature,
) -> Result<raw::Commit<'a>, raw::Error> {
let tree = parent.tree()?;
let oid = repo.commit(Some(target.as_str()), sig, sig, message, &tree, &[parent])?;
let commit = repo.find_commit(oid)?;
@ -599,7 +599,7 @@ pub fn empty_commit<'a>(
}
/// Get the repository head.
pub fn head(repo: &git2::Repository) -> Result<git2::Commit, git2::Error> {
pub fn head(repo: &raw::Repository) -> Result<raw::Commit, raw::Error> {
let head = repo.head()?.peel_to_commit()?;
Ok(head)
@ -609,8 +609,8 @@ pub fn head(repo: &git2::Repository) -> Result<git2::Commit, git2::Error> {
pub fn write_tree<'r>(
path: &Path,
bytes: &[u8],
repo: &'r git2::Repository,
) -> Result<git2::Tree<'r>, Error> {
repo: &'r raw::Repository,
) -> Result<raw::Tree<'r>, Error> {
let blob_id = repo.blob(bytes)?;
let mut builder = repo.treebuilder(None)?;
builder.insert(path, blob_id, 0o100_644)?;
@ -624,7 +624,7 @@ pub fn write_tree<'r>(
/// Configure a radicle repository.
///
/// * Sets `push.default = upstream`.
pub fn configure_repository(repo: &git2::Repository) -> Result<(), git2::Error> {
pub fn configure_repository(repo: &raw::Repository) -> Result<(), raw::Error> {
let mut cfg = repo.config()?;
cfg.set_str("push.default", "upstream")?;
@ -652,11 +652,11 @@ pub fn configure_repository(repo: &git2::Repository) -> Result<(), git2::Error>
/// 2. `tagOpt = --no-tags` to ensure that tags are not fetched and stored
/// under `refs/tags`, again, because these are fetched by the `rad` remote.
pub fn configure_remote<'r>(
repo: &'r git2::Repository,
repo: &'r raw::Repository,
name: &str,
fetch: &Url,
push: &Url,
) -> Result<git2::Remote<'r>, git2::Error> {
) -> Result<raw::Remote<'r>, raw::Error> {
let fetchspec = format!("+refs/heads/*:refs/remotes/{name}/*");
let remote = repo.remote_with_fetch(name, fetch.to_string().as_str(), &fetchspec)?;
@ -679,14 +679,14 @@ pub fn configure_remote<'r>(
}
/// Fetch from the given `remote`.
pub fn fetch(repo: &git2::Repository, remote: &str) -> Result<(), git2::Error> {
pub fn fetch(repo: &raw::Repository, remote: &str) -> Result<(), raw::Error> {
repo.find_remote(remote)?.fetch::<&str>(
&[],
Some(
git2::FetchOptions::new()
raw::FetchOptions::new()
.update_fetchhead(false)
.prune(git2::FetchPrune::On)
.download_tags(git2::AutotagOption::None),
.prune(raw::FetchPrune::On)
.download_tags(raw::AutotagOption::None),
),
None,
)
@ -694,10 +694,10 @@ pub fn fetch(repo: &git2::Repository, remote: &str) -> Result<(), git2::Error> {
/// Push `refspecs` to the given `remote` using the provided `namespace`.
pub fn push<'a>(
repo: &git2::Repository,
repo: &raw::Repository,
remote: &str,
refspecs: impl IntoIterator<Item = (&'a Qualified<'a>, &'a Qualified<'a>)>,
) -> Result<(), git2::Error> {
) -> Result<(), raw::Error> {
let refspecs = refspecs
.into_iter()
.map(|(src, dst)| format!("{src}:{dst}"));
@ -719,11 +719,11 @@ pub fn push<'a>(
/// merge = refs/heads/main
/// ```
pub fn set_upstream(
repo: &git2::Repository,
repo: &raw::Repository,
remote: impl AsRef<str>,
branch: impl AsRef<str>,
merge: impl AsRef<str>,
) -> Result<(), git2::Error> {
) -> Result<(), raw::Error> {
let remote = remote.as_ref();
let branch = branch.as_ref();
let merge = merge.as_ref();
@ -752,14 +752,14 @@ pub fn set_upstream(
Ok(())
}
pub fn init_default_branch(repo: &git2::Repository) -> Result<Option<String>, git2::Error> {
pub fn init_default_branch(repo: &raw::Repository) -> Result<Option<String>, raw::Error> {
let config = repo.config().and_then(|mut c| c.snapshot())?;
let default_branch = config.get_str("init.defaultbranch")?;
let branch = repo.find_branch(default_branch, git2::BranchType::Local)?;
let branch = repo.find_branch(default_branch, raw::BranchType::Local)?;
Ok(branch.into_reference().shorthand().map(ToOwned::to_owned))
}
pub fn head_refname(repo: &git2::Repository) -> Result<Option<String>, git2::Error> {
pub fn head_refname(repo: &raw::Repository) -> Result<Option<String>, raw::Error> {
let head = repo.head()?;
match head.shorthand() {
Some("HEAD") => Ok(None),

View File

@ -167,7 +167,7 @@ pub struct GraphDescendant {
// `git2` implementations of the above effects
// ===========================================
impl FindMergeBase for git2::Repository {
impl FindMergeBase for git::raw::Repository {
fn merge_base(&self, a: Oid, b: Oid) -> Result<MergeBase, MergeBaseError> {
self.merge_base(*a, *b)
.map_err(|err| MergeBaseError {
@ -183,7 +183,7 @@ impl FindMergeBase for git2::Repository {
}
}
impl Ancestry for git2::Repository {
impl Ancestry for git::raw::Repository {
fn graph_ahead_behind(
&self,
commit: Oid,
@ -199,7 +199,7 @@ impl Ancestry for git2::Repository {
}
}
impl FindObjects for git2::Repository {
impl FindObjects for git::raw::Repository {
fn find_objects<'a, 'b, I>(
&self,
refname: &Qualified,

View File

@ -780,7 +780,7 @@ mod tests {
doc.delegates().clone()
}
fn tag(name: RefString, head: git2::Oid, repo: &git2::Repository) -> git::Oid {
fn tag(name: RefString, head: git::raw::Oid, repo: &git::raw::Repository) -> git::Oid {
let commit = fixtures::commit(name.as_str(), &[head], repo);
let target = repo.find_object(*commit, None).unwrap();
let tagger = repo.signature().unwrap();

View File

@ -0,0 +1,34 @@
//! This module re-exports selected items from the [`git2`] crate and provides
//! an extension trait for its [`git2::Error`] type to more conveniently handle
//! errors associated with the code [`git2::ErrorCode::NotFound`].
//!
// Re-exports created by manually scanning the `heartwood` workspace on 2025-10-04.
// Re-exports that are only used within this crate.
pub(crate) use git2::{
message_trailers_strs, AutotagOption, Blob, Config, FetchOptions, FetchPrune, Object,
RemoteCallbacks, Revwalk, Sort,
};
// Re-exports that are used by other crates in the workspace, including this crate.
pub use git2::{
Branch, BranchType, Commit, Direction, Error, ErrorClass, ErrorCode, FileMode, ObjectType, Oid,
Reference, Remote, Repository, RepositoryInitOptions, RepositoryOpenFlags, Signature, Time,
Tree,
};
// Re-exports that are used by other crates in the workspace, but *not* this crate.
pub use git2::{
AnnotatedCommit, Diff, DiffFindOptions, DiffOptions, DiffStats, MergeAnalysis, MergeOptions,
};
// Re-exports for `radicle-cli`.
pub mod build {
pub use git2::build::CheckoutBuilder;
}
pub(crate) mod transport {
pub use git2::transport::{
register, Service, SmartSubtransport, SmartSubtransportStream, Transport,
};
}

View File

@ -54,7 +54,7 @@ pub enum DocError {
#[error("git: {0}")]
GitExt(#[from] git::Error),
#[error("git: {0}")]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
#[error("missing identity document")]
Missing,
}
@ -687,7 +687,7 @@ impl Doc {
}
/// Construct a [`Doc`] contained in the provided Git blob.
pub fn from_blob(blob: &git2::Blob) -> Result<Self, DocError> {
pub fn from_blob(blob: &git::raw::Blob) -> Result<Self, DocError> {
RawDoc::from_json(blob.content())?.verified()
}
@ -830,7 +830,7 @@ impl Doc {
pub(crate) fn blob_at<R: ReadRepository>(
commit: Oid,
repo: &R,
) -> Result<git2::Blob, DocError> {
) -> Result<git::raw::Blob, DocError> {
let path = Path::new("embeds").join(*PATH);
repo.blob_at(commit, path.as_path()).map_err(DocError::from)
}
@ -843,7 +843,7 @@ impl Doc {
serde_json::Serializer::with_formatter(&mut buf, CanonicalFormatter::new());
self.serialize(&mut serializer)?;
let oid = git2::Oid::hash_object(git2::ObjectType::Blob, &buf)?;
let oid = git::raw::Oid::hash_object(git::raw::ObjectType::Blob, &buf)?;
Ok((oid.into(), buf))
}
@ -1157,7 +1157,7 @@ mod test {
let remote = arbitrary::gen::<RemoteId>(1);
let proj = arbitrary::gen::<RepoId>(1);
let repo = storage.create(proj).unwrap();
let oid = git2::Oid::from_str("2d52a53ce5e4f141148a5f770cfd3ead2d6a45b8").unwrap();
let oid = git::raw::Oid::from_str("2d52a53ce5e4f141148a5f770cfd3ead2d6a45b8").unwrap();
let err = repo.identity_head_of(&remote).unwrap_err();
matches!(err, git::ext::Error::NotFound(_));

View File

@ -13,7 +13,7 @@ pub const RAD_PREFIX: &str = "rad:";
#[derive(Error, Debug)]
pub enum IdError {
#[error("invalid git object id: {0}")]
InvalidOid(#[from] git2::Error),
InvalidOid(#[from] git::raw::Error),
#[error(transparent)]
Multibase(#[from] multibase::Error),
}
@ -102,8 +102,8 @@ impl From<git::Oid> for RepoId {
}
}
impl From<git2::Oid> for RepoId {
fn from(oid: git2::Oid) -> Self {
impl From<git::raw::Oid> for RepoId {
fn from(oid: git::raw::Oid) -> Self {
Self(oid.into())
}
}

View File

@ -88,7 +88,7 @@ pub mod env {
/// Get the configured pager program from the environment.
pub fn pager() -> Option<String> {
if let Ok(cfg) = git2::Config::open_default() {
if let Ok(cfg) = crate::git::raw::Config::open_default() {
if let Ok(pager) = cfg.get_string("core.pager") {
return Some(pager);
}

View File

@ -39,7 +39,7 @@ pub enum InitError {
#[error("project payload: {0}")]
ProjectPayload(String),
#[error("git: {0}")]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
#[error("i/o: {0}")]
Io(#[from] io::Error),
#[error("storage: {0}")]
@ -48,7 +48,7 @@ pub enum InitError {
/// Initialize a new radicle project from a git repository.
pub fn init<G, S>(
repo: &git2::Repository,
repo: &git::raw::Repository,
name: ProjectName,
description: &str,
default_branch: BranchName,
@ -96,7 +96,7 @@ where
}
fn init_configure<G>(
repo: &git2::Repository,
repo: &git::raw::Repository,
stored: &Repository,
default_branch: &BranchName,
url: &git::Url,
@ -152,7 +152,7 @@ where
#[derive(Error, Debug)]
pub enum ForkError {
#[error("git: {0}")]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
#[error("storage: {0}")]
Storage(#[from] storage::Error),
#[error("payload: {0}")]
@ -236,7 +236,7 @@ pub enum CheckoutError {
stdout: String,
},
#[error("git: {0}")]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
#[error("payload: {0}")]
Payload(#[from] doc::PayloadError),
#[error("repository `{0}` was not found in storage")]
@ -253,19 +253,19 @@ pub fn checkout<P: AsRef<Path>, S: storage::ReadStorage>(
path: P,
storage: &S,
bare: bool,
) -> Result<git2::Repository, CheckoutError> {
) -> Result<git::raw::Repository, CheckoutError> {
// TODO: Decide on whether we can use `clone_local`
// TODO: Look into sharing object databases.
let doc = storage.get(proj)?.ok_or(CheckoutError::NotFound(proj))?;
let project = doc.project()?;
let mut opts = git2::RepositoryInitOptions::new();
let mut opts = git::raw::RepositoryInitOptions::new();
opts.no_reinit(true)
.external_template(false)
.description(project.description())
.bare(bare);
let repo = git2::Repository::init_opts(path.as_ref(), &opts)?;
let repo = git::raw::Repository::init_opts(path.as_ref(), &opts)?;
let url = git::Url::from(proj);
// Configure repository for radicle.
@ -335,7 +335,7 @@ pub fn checkout<P: AsRef<Path>, S: storage::ReadStorage>(
#[derive(Error, Debug)]
pub enum RemoteError {
#[error("git: {0}")]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
#[error("invalid remote url: {0}")]
Url(#[from] transport::local::UrlError),
#[error("invalid utf-8 string")]
@ -347,9 +347,9 @@ pub enum RemoteError {
}
/// Get the radicle ("rad") remote of a repository, and return the associated project id.
pub fn remote(repo: &git2::Repository) -> Result<(git2::Remote<'_>, RepoId), RemoteError> {
pub fn remote(repo: &git::raw::Repository) -> Result<(git::raw::Remote<'_>, RepoId), RemoteError> {
let remote = repo.find_remote(&REMOTE_NAME).map_err(|e| {
if e.code() == git2::ErrorCode::NotFound {
if e.code() == git::raw::ErrorCode::NotFound {
RemoteError::NotFound(REMOTE_NAME.to_string())
} else {
RemoteError::from(e)
@ -362,9 +362,9 @@ pub fn remote(repo: &git2::Repository) -> Result<(git2::Remote<'_>, RepoId), Rem
}
/// Delete the radicle ("rad") remote of a repository.
pub fn remove_remote(repo: &git2::Repository) -> Result<(), RemoteError> {
pub fn remove_remote(repo: &git::raw::Repository) -> Result<(), RemoteError> {
repo.remote_delete(&REMOTE_NAME).map_err(|e| {
if e.code() == git2::ErrorCode::NotFound {
if e.code() == git::raw::ErrorCode::NotFound {
RemoteError::NotFound(REMOTE_NAME.to_string())
} else {
RemoteError::from(e)
@ -380,7 +380,7 @@ pub enum CwdError {
#[error("Detection failed (git: '{git}', jj: '{jj}')")]
Detection {
git: git2::Error,
git: git::raw::Error,
jj: JujutsuGitRootError,
},
}
@ -395,7 +395,7 @@ pub enum CwdError {
/// This function should only perform read operations since we do not
/// want to modify the wrong repository in the case that it found a
/// Git repository that is not a Radicle repository.
pub fn cwd() -> Result<(git2::Repository, RepoId), CwdError> {
pub fn cwd() -> Result<(git::raw::Repository, RepoId), CwdError> {
let repo =
repo().or_else(|git| repo_jj_git_root().map_err(|jj| CwdError::Detection { git, jj }))?;
@ -404,23 +404,23 @@ pub fn cwd() -> Result<(git2::Repository, RepoId), CwdError> {
}
/// Get the repository of project in specified directory
pub fn at(path: impl AsRef<Path>) -> Result<(git2::Repository, RepoId), RemoteError> {
let repo = git2::Repository::open(path)?;
pub fn at(path: impl AsRef<Path>) -> Result<(git::raw::Repository, RepoId), RemoteError> {
let repo = git::raw::Repository::open(path)?;
let (_, id) = remote(&repo)?;
Ok((repo, id))
}
/// Get the current Git repository.
pub fn repo() -> Result<git2::Repository, git2::Error> {
let mut flags = git2::RepositoryOpenFlags::empty();
pub fn repo() -> Result<git::raw::Repository, git::raw::Error> {
let mut flags = git::raw::RepositoryOpenFlags::empty();
// Allow to search upwards.
flags.set(git2::RepositoryOpenFlags::NO_SEARCH, false);
flags.set(git::raw::RepositoryOpenFlags::NO_SEARCH, false);
// Allow to use `GIT_DIR` env.
flags.set(git2::RepositoryOpenFlags::FROM_ENV, true);
flags.set(git::raw::RepositoryOpenFlags::FROM_ENV, true);
let ceilings: &[&str] = &[];
let repo = git2::Repository::open_ext(Path::new("."), flags, ceilings)?;
let repo = git::raw::Repository::open_ext(Path::new("."), flags, ceilings)?;
Ok(repo)
}
@ -428,7 +428,7 @@ pub fn repo() -> Result<git2::Repository, git2::Error> {
#[derive(Error, Debug)]
pub enum JujutsuGitRootError {
#[error("git: {0}")]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
#[error("i/o: {0}")]
Io(#[from] io::Error),
@ -438,7 +438,7 @@ pub enum JujutsuGitRootError {
}
/// Get the Git repo underlying the current Jujutsu repository.
pub fn repo_jj_git_root() -> Result<git2::Repository, JujutsuGitRootError> {
pub fn repo_jj_git_root() -> Result<git::raw::Repository, JujutsuGitRootError> {
let output = std::process::Command::new("jj")
.args(["git", "root"])
.output()?;
@ -450,7 +450,7 @@ pub fn repo_jj_git_root() -> Result<git2::Repository, JujutsuGitRootError> {
}
let path = std::path::PathBuf::from(String::from_utf8_lossy(&output.stdout).to_string().trim());
Ok(git2::Repository::open(path)?)
Ok(git::raw::Repository::open(path)?)
}
/// Setup patch upstream branch such that `git push` updates the patch.

View File

@ -94,12 +94,12 @@ pub(crate) mod git {
/// See [`crate::git::Oid`]
/// See [`::git_ext::Oid`]
/// See [`::git2::Oid`]
/// See [`::git::raw::Oid`]
///
/// A Git Object Identifier in hexadecimal encoding.
#[derive(JsonSchema)]
#[schemars(
remote = "git2::Oid",
remote = "git::raw::Oid",
description = "A Git Object Identifier (SHA-1 or SHA-256 hash) in hexadecimal encoding."
)]
pub(crate) struct Oid(

View File

@ -153,7 +153,7 @@ pub enum Error {
#[error(transparent)]
Refs(#[from] refs::Error),
#[error("git: {0}")]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
#[error("git: {0}")]
Ext(#[from] git::ext::Error),
#[error("invalid repository identifier {0:?}")]
@ -179,7 +179,7 @@ impl Error {
#[allow(clippy::large_enum_variant)]
pub enum FetchError {
#[error("git: {0}")]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
#[error("i/o: {0}")]
Io(#[from] io::Error),
#[error(transparent)]
@ -503,16 +503,20 @@ pub trait ReadRepository: Sized + ValidateRepository {
fn id(&self) -> RepoId;
/// Returns `true` if there are no references in the repository.
fn is_empty(&self) -> Result<bool, git2::Error>;
fn is_empty(&self) -> Result<bool, git::raw::Error>;
/// The [`Path`] to the git repository.
fn path(&self) -> &Path;
/// Get a blob in this repository at the given commit and path.
fn blob_at<P: AsRef<Path>>(&self, commit: Oid, path: P) -> Result<git2::Blob, git_ext::Error>;
fn blob_at<P: AsRef<Path>>(
&self,
commit: Oid,
path: P,
) -> Result<git::raw::Blob, git_ext::Error>;
/// Get a blob in this repository, given its id.
fn blob(&self, oid: Oid) -> Result<git2::Blob, git_ext::Error>;
fn blob(&self, oid: Oid) -> Result<git::raw::Blob, git_ext::Error>;
/// Get the head of this repository.
///
@ -572,18 +576,18 @@ pub trait ReadRepository: Sized + ValidateRepository {
&self,
remote: &RemoteId,
reference: &Qualified,
) -> Result<git2::Reference, git_ext::Error>;
) -> Result<git::raw::Reference, git_ext::Error>;
/// Get the [`git2::Commit`] found using its `oid`.
/// Get the [`git::raw::Commit`] found using its `oid`.
///
/// Returns `Err` if the commit did not exist.
fn commit(&self, oid: Oid) -> Result<git2::Commit, git::ext::Error>;
fn commit(&self, oid: Oid) -> Result<git::raw::Commit, git::ext::Error>;
/// Perform a revision walk of a commit history starting from the given head.
fn revwalk(&self, head: Oid) -> Result<git2::Revwalk, git2::Error>;
fn revwalk(&self, head: Oid) -> Result<git::raw::Revwalk, git::raw::Error>;
/// Check if the underlying ODB contains the given `oid`.
fn contains(&self, oid: Oid) -> Result<bool, git2::Error>;
fn contains(&self, oid: Oid) -> Result<bool, git::raw::Error>;
/// Check whether the given commit is an ancestor of another commit.
fn is_ancestor_of(&self, ancestor: Oid, head: Oid) -> Result<bool, git::ext::Error>;
@ -692,7 +696,7 @@ pub trait WriteRepository: ReadRepository + SignRepository {
/// Set the user info of the Git repository.
fn set_user(&self, info: &UserInfo) -> Result<(), Error>;
/// Get the underlying git repository.
fn raw(&self) -> &git2::Repository;
fn raw(&self) -> &git::raw::Repository;
}
/// Allows signing refs.

View File

@ -56,10 +56,10 @@ pub struct Ref {
pub namespace: Option<RemoteId>,
}
impl TryFrom<git2::Reference<'_>> for Ref {
impl TryFrom<git::raw::Reference<'_>> for Ref {
type Error = RefError;
fn try_from(r: git2::Reference) -> Result<Self, Self::Error> {
fn try_from(r: git::raw::Reference) -> Result<Self, Self::Error> {
let name = r.name().ok_or(RefError::InvalidName)?;
let (namespace, name) = match git::parse_ref_namespaced::<RemoteId>(name) {
Ok((namespace, refname)) => (Some(namespace), refname.to_ref_string()),
@ -279,7 +279,7 @@ pub struct Repository {
/// The repository identifier (RID).
pub id: RepoId,
/// The backing Git repository.
pub backend: git2::Repository,
pub backend: git::raw::Repository,
}
impl AsRef<Repository> for Repository {
@ -380,12 +380,12 @@ pub enum Validation {
impl Repository {
/// Open an existing repository.
pub fn open<P: AsRef<Path>>(path: P, id: RepoId) -> Result<Self, RepositoryError> {
let backend = git2::Repository::open_ext(
let backend = git::raw::Repository::open_ext(
path.as_ref(),
git2::RepositoryOpenFlags::empty()
| git2::RepositoryOpenFlags::BARE
| git2::RepositoryOpenFlags::NO_DOTGIT
| git2::RepositoryOpenFlags::NO_SEARCH,
git::raw::RepositoryOpenFlags::empty()
| git::raw::RepositoryOpenFlags::BARE
| git::raw::RepositoryOpenFlags::NO_DOTGIT
| git::raw::RepositoryOpenFlags::NO_SEARCH,
&[] as &[&std::ffi::OsStr],
)?;
@ -394,9 +394,9 @@ impl Repository {
/// Create a new repository.
pub fn create<P: AsRef<Path>>(path: P, id: RepoId, info: &UserInfo) -> Result<Self, Error> {
let backend = git2::Repository::init_opts(
let backend = git::raw::Repository::init_opts(
&path,
git2::RepositoryInitOptions::new()
git::raw::RepositoryInitOptions::new()
.bare(true)
.no_reinit(true)
.external_template(false),
@ -506,7 +506,7 @@ impl Repository {
/// Iterate over all references.
pub fn references(
&self,
) -> Result<impl Iterator<Item = Result<Ref, refs::Error>> + '_, git2::Error> {
) -> Result<impl Iterator<Item = Result<Ref, refs::Error>> + '_, git::raw::Error> {
let refs = self
.backend
.references()?
@ -539,7 +539,7 @@ impl Repository {
pub fn remote_ids(
&self,
) -> Result<impl Iterator<Item = Result<RemoteId, refs::Error>> + '_, git2::Error> {
) -> Result<impl Iterator<Item = Result<RemoteId, refs::Error>> + '_, git::raw::Error> {
let iter = self.backend.references_glob(SIGREFS_GLOB.as_str())?.map(
|reference| -> Result<RemoteId, refs::Error> {
let r = reference?;
@ -556,7 +556,7 @@ impl Repository {
&self,
) -> Result<
impl Iterator<Item = Result<(RemoteId, Remote<Verified>), refs::Error>> + '_,
git2::Error,
git::raw::Error,
> {
let remotes =
self.backend
@ -652,7 +652,7 @@ impl ReadRepository for Repository {
self.id
}
fn is_empty(&self) -> Result<bool, git2::Error> {
fn is_empty(&self) -> Result<bool, git::raw::Error> {
Ok(self.remotes()?.next().is_none())
}
@ -660,7 +660,7 @@ impl ReadRepository for Repository {
self.backend.path()
}
fn blob_at<P: AsRef<Path>>(&self, commit: Oid, path: P) -> Result<git2::Blob, git::Error> {
fn blob_at<P: AsRef<Path>>(&self, commit: Oid, path: P) -> Result<git::raw::Blob, git::Error> {
let commit = self.backend.find_commit(*commit)?;
let tree = commit.tree()?;
let entry = tree.get_path(path.as_ref())?;
@ -674,7 +674,7 @@ impl ReadRepository for Repository {
Ok(blob)
}
fn blob(&self, oid: Oid) -> Result<git2::Blob, git::Error> {
fn blob(&self, oid: Oid) -> Result<git::raw::Blob, git::Error> {
self.backend.find_blob(oid.into()).map_err(git::Error::from)
}
@ -682,7 +682,7 @@ impl ReadRepository for Repository {
&self,
remote: &RemoteId,
name: &git::Qualified,
) -> Result<git2::Reference, git::Error> {
) -> Result<git::raw::Reference, git::Error> {
let name = name.with_namespace(remote.into());
self.backend.find_reference(&name).map_err(git::Error::from)
}
@ -698,13 +698,13 @@ impl ReadRepository for Repository {
Ok(oid.into())
}
fn commit(&self, oid: Oid) -> Result<git2::Commit, git::Error> {
fn commit(&self, oid: Oid) -> Result<git::raw::Commit, git::Error> {
self.backend
.find_commit(oid.into())
.map_err(git::Error::from)
}
fn revwalk(&self, head: Oid) -> Result<git2::Revwalk, git2::Error> {
fn revwalk(&self, head: Oid) -> Result<git::raw::Revwalk, git::raw::Error> {
let mut revwalk = self.backend.revwalk()?;
revwalk.push(head.into())?;
@ -936,7 +936,7 @@ impl WriteRepository for Repository {
Ok(())
}
fn raw(&self) -> &git2::Repository {
fn raw(&self) -> &git::raw::Repository {
&self.backend
}
}
@ -986,7 +986,7 @@ pub mod trailers {
pub fn parse_signatures(msg: &str) -> Result<HashMap<PublicKey, Signature>, Error> {
let trailers =
git2::message_trailers_strs(msg).map_err(|_| Error::SignatureTrailerFormat)?;
git::raw::message_trailers_strs(msg).map_err(|_| Error::SignatureTrailerFormat)?;
let mut signatures = HashMap::with_capacity(trailers.len());
for (key, val) in trailers.iter() {
@ -1097,7 +1097,7 @@ mod tests {
fixtures::project(tmp.path().join("project"), &storage, &signer).unwrap();
let stored = storage.repository(rid).unwrap();
let sig =
git2::Signature::now(&alice.to_string(), "anonymous@radicle.example.com").unwrap();
git::raw::Signature::now(&alice.to_string(), "anonymous@radicle.example.com").unwrap();
let head = working.head().unwrap().peel_to_commit().unwrap();
git::commit(

View File

@ -33,7 +33,7 @@ pub enum ObjectsError {
#[error(transparent)]
Convert(#[from] cob::object::storage::convert::Error),
#[error(transparent)]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
#[error(transparent)]
GitExt(#[from] git_ext::Error),
}
@ -43,7 +43,7 @@ pub enum TypesError {
#[error(transparent)]
Convert(#[from] cob::object::storage::convert::Error),
#[error(transparent)]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
#[error(transparent)]
ParseKey(#[from] crypto::Error),
#[error(transparent)]
@ -55,12 +55,12 @@ pub enum TypesError {
impl cob::Store for Repository {}
impl change::Storage for Repository {
type StoreError = <git2::Repository as change::Storage>::StoreError;
type LoadError = <git2::Repository as change::Storage>::LoadError;
type StoreError = <git::raw::Repository as change::Storage>::StoreError;
type LoadError = <git::raw::Repository as change::Storage>::LoadError;
type ObjectId = <git2::Repository as change::Storage>::ObjectId;
type Parent = <git2::Repository as change::Storage>::Parent;
type Signatures = <git2::Repository as change::Storage>::Signatures;
type ObjectId = <git::raw::Repository as change::Storage>::ObjectId;
type Parent = <git::raw::Repository as change::Storage>::Parent;
type Signatures = <git::raw::Repository as change::Storage>::Signatures;
fn store<Signer>(
&self,
@ -91,8 +91,8 @@ impl change::Storage for Repository {
impl cob::object::Storage for Repository {
type ObjectsError = ObjectsError;
type TypesError = TypesError;
type UpdateError = git2::Error;
type RemoveError = git2::Error;
type UpdateError = git::raw::Error;
type RemoveError = git::raw::Error;
type Namespace = NodeId;
@ -200,12 +200,12 @@ impl<'a, R> DraftStore<'a, R> {
impl<R: storage::WriteRepository> cob::Store for DraftStore<'_, R> {}
impl<R: storage::WriteRepository> change::Storage for DraftStore<'_, R> {
type StoreError = <git2::Repository as change::Storage>::StoreError;
type LoadError = <git2::Repository as change::Storage>::LoadError;
type StoreError = <git::raw::Repository as change::Storage>::StoreError;
type LoadError = <git::raw::Repository as change::Storage>::LoadError;
type ObjectId = <git2::Repository as change::Storage>::ObjectId;
type Parent = <git2::Repository as change::Storage>::Parent;
type Signatures = <git2::Repository as change::Storage>::Signatures;
type ObjectId = <git::raw::Repository as change::Storage>::ObjectId;
type Parent = <git::raw::Repository as change::Storage>::Parent;
type Signatures = <git::raw::Repository as change::Storage>::Signatures;
fn store<Signer>(
&self,
@ -274,7 +274,7 @@ impl<R: storage::ReadRepository> ReadRepository for DraftStore<'_, R> {
self.repo.id()
}
fn is_empty(&self) -> Result<bool, git2::Error> {
fn is_empty(&self) -> Result<bool, git::raw::Error> {
self.repo.is_empty()
}
@ -290,11 +290,11 @@ impl<R: storage::ReadRepository> ReadRepository for DraftStore<'_, R> {
self.repo.path()
}
fn commit(&self, oid: Oid) -> Result<git2::Commit, git_ext::Error> {
fn commit(&self, oid: Oid) -> Result<git::raw::Commit, git_ext::Error> {
self.repo.commit(oid)
}
fn revwalk(&self, head: Oid) -> Result<git2::Revwalk, git2::Error> {
fn revwalk(&self, head: Oid) -> Result<git::raw::Revwalk, git::raw::Error> {
self.repo.revwalk(head)
}
@ -310,7 +310,7 @@ impl<R: storage::ReadRepository> ReadRepository for DraftStore<'_, R> {
&self,
oid: git_ext::Oid,
path: P,
) -> Result<git2::Blob, git_ext::Error> {
) -> Result<git::raw::Blob, git_ext::Error> {
self.repo.blob_at(oid, path)
}
@ -322,7 +322,7 @@ impl<R: storage::ReadRepository> ReadRepository for DraftStore<'_, R> {
&self,
remote: &RemoteId,
reference: &git::Qualified,
) -> Result<git2::Reference, git_ext::Error> {
) -> Result<git::raw::Reference, git_ext::Error> {
self.repo.reference(remote, reference)
}
@ -381,8 +381,8 @@ impl<R: storage::ReadRepository> ReadRepository for DraftStore<'_, R> {
impl<R: storage::WriteRepository> cob::object::Storage for DraftStore<'_, R> {
type ObjectsError = ObjectsError;
type TypesError = git::ext::Error;
type UpdateError = git2::Error;
type RemoveError = git2::Error;
type UpdateError = git::raw::Error;
type RemoveError = git::raw::Error;
type Namespace = NodeId;

View File

@ -7,6 +7,7 @@ use std::process;
use std::str::FromStr;
use std::sync::Once;
use crate::git;
use crate::storage;
use crate::storage::git::Storage;
@ -25,20 +26,19 @@ struct Local {
child: RefCell<Option<process::Child>>,
}
impl git2::transport::SmartSubtransport for Local {
impl crate::git::raw::transport::SmartSubtransport for Local {
fn action(
&self,
url: &str,
service: git2::transport::Service,
) -> Result<Box<dyn git2::transport::SmartSubtransportStream>, git2::Error> {
let url = Url::from_str(url).map_err(|e| git2::Error::from_str(e.to_string().as_str()))?;
service: git::raw::transport::Service,
) -> Result<Box<dyn git::raw::transport::SmartSubtransportStream>, git::raw::Error> {
let url =
Url::from_str(url).map_err(|e| git::raw::Error::from_str(e.to_string().as_str()))?;
let service: &str = match service {
git2::transport::Service::UploadPack | git2::transport::Service::UploadPackLs => {
"upload-pack"
}
git2::transport::Service::ReceivePack | git2::transport::Service::ReceivePackLs => {
"receive-pack"
}
git::raw::transport::Service::UploadPack
| git::raw::transport::Service::UploadPackLs => "upload-pack",
git::raw::transport::Service::ReceivePack
| git::raw::transport::Service::ReceivePackLs => "receive-pack",
};
let git_dir = THREAD_STORAGE
.with(|t| {
@ -46,7 +46,9 @@ impl git2::transport::SmartSubtransport for Local {
.as_ref()
.map(|s| storage::git::paths::repository(&s, &url.repo))
})
.ok_or_else(|| git2::Error::from_str("local transport storage was not registered"))?;
.ok_or_else(|| {
git::raw::Error::from_str("local transport storage was not registered")
})?;
let mut cmd = process::Command::new("git");
@ -61,7 +63,7 @@ impl git2::transport::SmartSubtransport for Local {
.stdout(process::Stdio::piped())
.stderr(process::Stdio::inherit())
.spawn()
.map_err(|e| git2::Error::from_str(e.to_string().as_str()))?;
.map_err(|e| git::raw::Error::from_str(e.to_string().as_str()))?;
let stdin = child.stdin.take().expect("taking stdin is safe");
let stdout = child.stdout.take().expect("taking stdout is safe");
@ -71,19 +73,19 @@ impl git2::transport::SmartSubtransport for Local {
Ok(Box::new(ChildStream { stdout, stdin }))
}
fn close(&self) -> Result<(), git2::Error> {
fn close(&self) -> Result<(), git::raw::Error> {
if let Some(mut child) = self.child.take() {
let result = child
.wait()
.map_err(|e| git2::Error::from_str(e.to_string().as_str()))?;
.map_err(|e| git::raw::Error::from_str(e.to_string().as_str()))?;
if !result.success() {
return if let Some(code) = result.code() {
Err(git2::Error::from_str(
Err(git::raw::Error::from_str(
format!("transport: child process exited with error code {code}").as_str(),
))
} else {
Err(git2::Error::from_str(
Err(git::raw::Error::from_str(
"transport: child process exited with unknown error",
))
};
@ -103,8 +105,8 @@ pub fn register(storage: Storage) {
});
REGISTER.call_once(|| unsafe {
git2::transport::register(Url::SCHEME, move |remote| {
git2::transport::Transport::smart(remote, false, Local::default())
git::raw::transport::register(Url::SCHEME, move |remote| {
git::raw::transport::Transport::smart(remote, false, Local::default())
})
.expect("local transport registration");
});

View File

@ -8,6 +8,7 @@ use std::thread::ThreadId;
use std::{process, thread};
use super::Url;
use crate::git;
use crate::storage::git::transport::ChildStream;
use crate::storage::RemoteId;
@ -19,19 +20,21 @@ static NODES: LazyLock<Mutex<HashMap<(ThreadId, RemoteId), PathBuf>>> =
#[derive(Default)]
struct MockTransport;
impl git2::transport::SmartSubtransport for MockTransport {
impl git::raw::transport::SmartSubtransport for MockTransport {
fn action(
&self,
url: &str,
service: git2::transport::Service,
) -> Result<Box<dyn git2::transport::SmartSubtransportStream>, git2::Error> {
let url = Url::from_str(url).map_err(|e| git2::Error::from_str(e.to_string().as_str()))?;
service: git::raw::transport::Service,
) -> Result<Box<dyn git::raw::transport::SmartSubtransportStream>, git::raw::Error> {
let url =
Url::from_str(url).map_err(|e| git::raw::Error::from_str(e.to_string().as_str()))?;
let id = thread::current().id();
let nodes = NODES.lock().expect("lock cannot be poisoned");
let storage = if let Some(storage) = nodes.get(&(id, url.node)) {
match service {
git2::transport::Service::ReceivePack | git2::transport::Service::ReceivePackLs => {
return Err(git2::Error::from_str(
git::raw::transport::Service::ReceivePack
| git::raw::transport::Service::ReceivePackLs => {
return Err(git::raw::Error::from_str(
"git-receive-pack is not supported with the mock transport",
));
}
@ -39,7 +42,7 @@ impl git2::transport::SmartSubtransport for MockTransport {
}
storage
} else {
return Err(git2::Error::from_str(&format!(
return Err(git::raw::Error::from_str(&format!(
"node {} was not registered with the mock transport",
url.node
)));
@ -76,7 +79,7 @@ impl git2::transport::SmartSubtransport for MockTransport {
Ok(Box::new(ChildStream { stdout, stdin }))
}
fn close(&self) -> Result<(), git2::Error> {
fn close(&self) -> Result<(), git::raw::Error> {
Ok(())
}
}
@ -86,8 +89,8 @@ pub fn register(node: &RemoteId, path: &Path) {
static REGISTER: Once = Once::new();
REGISTER.call_once(|| unsafe {
git2::transport::register(Url::SCHEME, move |remote| {
git2::transport::Transport::smart(remote, false, MockTransport)
git::raw::transport::register(Url::SCHEME, move |remote| {
git::raw::transport::Transport::smart(remote, false, MockTransport)
})
.expect("transport registration is successful");
});

View File

@ -55,7 +55,7 @@ pub enum Error {
#[error("invalid reference: {0}")]
Ref(#[from] git::RefError),
#[error(transparent)]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
#[error(transparent)]
GitExt(#[from] git_ext::Error),
}
@ -322,8 +322,8 @@ impl SignedRefs<Verified> {
env::GIT_COMMITTER_DATE
);
};
let time = git2::Time::new(timestamp, 0);
git2::Signature::new("radicle", remote.to_string().as_str(), &time)?
let time = git::raw::Time::new(timestamp, 0);
git::raw::Signature::new("radicle", remote.to_string().as_str(), &time)?
} else {
raw.signature()?
};
@ -334,13 +334,13 @@ impl SignedRefs<Verified> {
&author,
"Update signed refs\n",
&tree,
&parent.iter().collect::<Vec<&git2::Commit>>(),
&parent.iter().collect::<Vec<&git::raw::Commit>>(),
);
match commit {
Ok(oid) => Ok(Updated::Updated { oid: oid.into() }),
Err(e) => match (e.class(), e.code()) {
(git2::ErrorClass::Object, git2::ErrorCode::Modified) => {
(git::raw::ErrorClass::Object, git::raw::ErrorCode::Modified) => {
log::warn!("Concurrent modification of refs: {e:?}");
Err(Error::Git(e))
@ -471,7 +471,7 @@ pub mod canonical {
#[error(transparent)]
Io(#[from] io::Error),
#[error(transparent)]
Git(#[from] git2::Error),
Git(#[from] git::raw::Error),
}
}
@ -581,7 +581,7 @@ mod tests {
.unwrap();
let paris_head = bob_working.find_commit(paris_head).unwrap();
let bob_sig = git2::Signature::now("bob", "bob@example.com").unwrap();
let bob_sig = git::raw::Signature::now("bob", "bob@example.com").unwrap();
let bob_head = git::empty_commit(
&bob_working,
&paris_head,

View File

@ -6,6 +6,7 @@ pub mod storage;
use super::storage::{Namespaces, RefUpdate};
use crate::git;
use crate::prelude::NodeId;
use crate::storage::WriteRepository;
@ -22,13 +23,13 @@ pub fn fetch<W: WriteRepository>(
Namespaces::Followed(followed) => followed.into_iter().next(),
};
let mut updates = Vec::new();
let mut callbacks = git2::RemoteCallbacks::new();
let mut opts = git2::FetchOptions::default();
let mut callbacks = git::raw::RemoteCallbacks::new();
let mut opts = git::raw::FetchOptions::default();
let refspec = if let Some(namespace) = namespace {
opts.prune(git2::FetchPrune::On);
opts.prune(git::raw::FetchPrune::On);
format!("refs/namespaces/{namespace}/refs/*:refs/namespaces/{namespace}/refs/*")
} else {
opts.prune(git2::FetchPrune::Off);
opts.prune(git::raw::FetchPrune::Off);
"refs/namespaces/*:refs/namespaces/*".to_owned()
};
@ -295,22 +296,22 @@ pub mod setup {
}
pub fn commit<S: AsRef<Path>, T: AsRef<[u8]>>(
repo: &git2::Repository,
repo: &git::raw::Repository,
refname: &git::Qualified,
blobs: impl IntoIterator<Item = (S, T)>,
parents: &[&git2::Commit<'_>],
parents: &[&git::raw::Commit<'_>],
) -> git::Oid {
let tree = {
let mut tb = repo.treebuilder(None).unwrap();
for (name, blob) in blobs.into_iter() {
let oid = repo.blob(blob.as_ref()).unwrap();
tb.insert(name.as_ref(), oid, git2::FileMode::Blob.into())
tb.insert(name.as_ref(), oid, git::raw::FileMode::Blob.into())
.unwrap();
}
tb.write().unwrap()
};
let tree = repo.find_tree(tree).unwrap();
let author = git2::Signature::now("anonymous", "anonymous@example.com").unwrap();
let author = git::raw::Signature::now("anonymous", "anonymous@example.com").unwrap();
repo.commit(
Some(refname.as_str()),

View File

@ -72,7 +72,15 @@ pub fn project<P, G>(
path: P,
storage: &Storage,
signer: &Device<G>,
) -> Result<(RepoId, SignedRefs<Verified>, git2::Repository, git2::Oid), rad::InitError>
) -> Result<
(
RepoId,
SignedRefs<Verified>,
git::raw::Repository,
git::raw::Oid,
),
rad::InitError,
>
where
P: AsRef<Path>,
G: crypto::signature::Signer<crypto::Signature>,
@ -94,19 +102,19 @@ where
}
/// Creates a regular repository at the given path with a couple of commits.
pub fn repository<P: AsRef<Path>>(path: P) -> (git2::Repository, git2::Oid) {
pub fn repository<P: AsRef<Path>>(path: P) -> (git::raw::Repository, git::raw::Oid) {
let (repo, oid) = repository_with(
path,
git2::RepositoryInitOptions::new().external_template(false),
git::raw::RepositoryInitOptions::new().external_template(false),
);
repo.checkout_head(None).unwrap();
(repo, oid)
}
pub fn bare_repository<P: AsRef<Path>>(path: P) -> (git2::Repository, git2::Oid) {
pub fn bare_repository<P: AsRef<Path>>(path: P) -> (git::raw::Repository, git::raw::Oid) {
repository_with(
path,
git2::RepositoryInitOptions::new()
git::raw::RepositoryInitOptions::new()
.external_template(false)
.bare(true),
)
@ -114,17 +122,21 @@ pub fn bare_repository<P: AsRef<Path>>(path: P) -> (git2::Repository, git2::Oid)
fn repository_with<P: AsRef<Path>>(
path: P,
opts: &mut git2::RepositoryInitOptions,
) -> (git2::Repository, git2::Oid) {
let repo = git2::Repository::init_opts(path, opts).unwrap();
opts: &mut git::raw::RepositoryInitOptions,
) -> (git::raw::Repository, git::raw::Oid) {
let repo = git::raw::Repository::init_opts(path, opts).unwrap();
{
let mut config = repo.config().unwrap();
config.set_str("user.name", USER_NAME).unwrap();
config.set_str("user.email", USER_EMAIL).unwrap();
}
let sig =
git2::Signature::new(USER_NAME, USER_EMAIL, &git2::Time::new(RADICLE_EPOCH, 0)).unwrap();
let sig = git::raw::Signature::new(
USER_NAME,
USER_EMAIL,
&git::raw::Time::new(RADICLE_EPOCH, 0),
)
.unwrap();
let head = git::initial_commit(&repo, &sig).unwrap();
let tree = git::write_tree(Path::new("README"), "Hello World!\n".as_bytes(), &repo).unwrap();
let oid = {
@ -149,10 +161,14 @@ fn repository_with<P: AsRef<Path>>(
}
/// Create an empty commit on the current branch.
pub fn commit(msg: &str, parents: &[git2::Oid], repo: &git2::Repository) -> git::Oid {
pub fn commit(msg: &str, parents: &[git::raw::Oid], repo: &git::raw::Repository) -> git::Oid {
let head = repo.head().unwrap();
let sig =
git2::Signature::new(USER_NAME, USER_EMAIL, &git2::Time::new(RADICLE_EPOCH, 0)).unwrap();
let sig = git::raw::Signature::new(
USER_NAME,
USER_EMAIL,
&git::raw::Time::new(RADICLE_EPOCH, 0),
)
.unwrap();
let tree = head.peel_to_commit().unwrap().tree().unwrap();
let parents = parents
.iter()
@ -166,19 +182,28 @@ pub fn commit(msg: &str, parents: &[git2::Oid], repo: &git2::Repository) -> git:
}
/// Create an (annotated) tag of the given commit.
pub fn tag(name: &str, message: &str, commit: git2::Oid, repo: &git2::Repository) -> git::Oid {
pub fn tag(
name: &str,
message: &str,
commit: git::raw::Oid,
repo: &git::raw::Repository,
) -> git::Oid {
let target = repo
.find_object(commit, Some(git2::ObjectType::Commit))
.find_object(commit, Some(git::raw::ObjectType::Commit))
.unwrap();
let tagger =
git2::Signature::new(USER_NAME, USER_EMAIL, &git2::Time::new(RADICLE_EPOCH, 0)).unwrap();
let tagger = git::raw::Signature::new(
USER_NAME,
USER_EMAIL,
&git::raw::Time::new(RADICLE_EPOCH, 0),
)
.unwrap();
repo.tag(name, &target, &tagger, message, false)
.unwrap()
.into()
}
/// Populate a repository with commits, branches and blobs.
pub fn populate(repo: &git2::Repository, scale: usize) -> Vec<git::Qualified> {
pub fn populate(repo: &git::raw::Repository, scale: usize) -> Vec<git::Qualified> {
assert!(
scale <= 8,
"Scale parameter must be less than or equal to 8"
@ -198,7 +223,7 @@ pub fn populate(repo: &git2::Repository, scale: usize) -> Vec<git::Qualified> {
.to_lowercase();
let name =
git::refname!("feature").join(git::RefString::try_from(random.as_str()).unwrap());
let signature = git2::Signature::now("Radicle", "radicle@radicle.xyz").unwrap();
let signature = git::raw::Signature::now("Radicle", "radicle@radicle.xyz").unwrap();
rng.fill(&mut buffer);
@ -241,13 +266,13 @@ pub mod gen {
}
/// Creates a regular repository at the given path with a couple of commits.
pub fn repository<P: AsRef<Path>>(path: P) -> (git2::Repository, git2::Oid) {
let repo = git2::Repository::init_opts(
pub fn repository<P: AsRef<Path>>(path: P) -> (git::raw::Repository, git::raw::Oid) {
let repo = git::raw::Repository::init_opts(
path,
git2::RepositoryInitOptions::new().external_template(false),
git::raw::RepositoryInitOptions::new().external_template(false),
)
.unwrap();
let sig = git2::Signature::now(string(6).as_str(), email().as_str()).unwrap();
let sig = git::raw::Signature::now(string(6).as_str(), email().as_str()).unwrap();
let head = git::initial_commit(&repo, &sig).unwrap();
let tree =
git::write_tree(Path::new("README"), "Hello World!\n".as_bytes(), &repo).unwrap();

View File

@ -199,7 +199,7 @@ impl ReadRepository for MockRepository {
self.id
}
fn is_empty(&self) -> Result<bool, git2::Error> {
fn is_empty(&self) -> Result<bool, git::raw::Error> {
Ok(self.remotes.is_empty())
}
@ -215,17 +215,17 @@ impl ReadRepository for MockRepository {
todo!()
}
fn commit(&self, oid: Oid) -> Result<git2::Commit, git_ext::Error> {
fn commit(&self, oid: Oid) -> Result<git::raw::Commit, git_ext::Error> {
Err(git_ext::Error::NotFound(git_ext::NotFound::NoSuchObject(
*oid,
)))
}
fn revwalk(&self, _head: Oid) -> Result<git2::Revwalk, git2::Error> {
fn revwalk(&self, _head: Oid) -> Result<git::raw::Revwalk, git::raw::Error> {
todo!()
}
fn contains(&self, oid: Oid) -> Result<bool, git2::Error> {
fn contains(&self, oid: Oid) -> Result<bool, git::raw::Error> {
Ok(self
.remotes
.values()
@ -236,7 +236,7 @@ impl ReadRepository for MockRepository {
Ok(true)
}
fn blob(&self, _oid: Oid) -> Result<git2::Blob, git_ext::Error> {
fn blob(&self, _oid: Oid) -> Result<git::raw::Blob, git_ext::Error> {
todo!()
}
@ -244,7 +244,7 @@ impl ReadRepository for MockRepository {
&self,
_oid: git_ext::Oid,
_path: P,
) -> Result<git2::Blob, git_ext::Error> {
) -> Result<git::raw::Blob, git_ext::Error> {
todo!()
}
@ -252,7 +252,7 @@ impl ReadRepository for MockRepository {
&self,
_remote: &RemoteId,
_reference: &git::Qualified,
) -> Result<git2::Reference, git_ext::Error> {
) -> Result<git::raw::Reference, git_ext::Error> {
todo!()
}
@ -322,7 +322,7 @@ impl ReadRepository for MockRepository {
}
impl WriteRepository for MockRepository {
fn raw(&self) -> &git2::Repository {
fn raw(&self) -> &git::raw::Repository {
todo!()
}