From 880634acd4d5bf6f0182d5718f2af912cbda17c0 Mon Sep 17 00:00:00 2001 From: Lorenz Leutgeb Date: Sat, 4 Oct 2025 11:59:26 +0200 Subject: [PATCH] radicle/git/raw: Capture all `git2` re-exports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- crates/radicle/src/cob/identity.rs | 2 +- crates/radicle/src/cob/op.rs | 2 +- crates/radicle/src/cob/stream.rs | 9 +-- crates/radicle/src/cob/stream/error.rs | 2 +- crates/radicle/src/cob/stream/iter.rs | 10 +-- crates/radicle/src/git.rs | 70 +++++++++--------- crates/radicle/src/git/canonical/effects.rs | 6 +- crates/radicle/src/git/canonical/rules.rs | 2 +- crates/radicle/src/git/raw.rs | 34 +++++++++ crates/radicle/src/identity/doc.rs | 10 +-- crates/radicle/src/identity/doc/id.rs | 6 +- crates/radicle/src/profile.rs | 2 +- crates/radicle/src/rad.rs | 50 ++++++------- crates/radicle/src/schemars_ext.rs | 4 +- crates/radicle/src/storage.rs | 26 ++++--- crates/radicle/src/storage/git.rs | 44 ++++++------ crates/radicle/src/storage/git/cob.rs | 42 +++++------ .../src/storage/git/transport/local.rs | 38 +++++----- .../src/storage/git/transport/remote/mock.rs | 23 +++--- crates/radicle/src/storage/refs.rs | 14 ++-- crates/radicle/src/test.rs | 17 ++--- crates/radicle/src/test/fixtures.rs | 71 +++++++++++++------ crates/radicle/src/test/storage.rs | 16 ++--- 23 files changed, 285 insertions(+), 215 deletions(-) create mode 100644 crates/radicle/src/git/raw.rs diff --git a/crates/radicle/src/cob/identity.rs b/crates/radicle/src/cob/identity.rs index 938936fd..549a1ae5 100644 --- a/crates/radicle/src/cob/identity.rs +++ b/crates/radicle/src/cob/identity.rs @@ -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}")] diff --git a/crates/radicle/src/cob/op.rs b/crates/radicle/src/cob/op.rs index c253e94c..bd6cd02e 100644 --- a/crates/radicle/src/cob/op.rs +++ b/crates/radicle/src/cob/op.rs @@ -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)] diff --git a/crates/radicle/src/cob/stream.rs b/crates/radicle/src/cob/stream.rs index 2e0a4345..8772b142 100644 --- a/crates/radicle/src/cob/stream.rs +++ b/crates/radicle/src/cob/stream.rs @@ -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, @@ -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::().unwrap() } - fn gen_ops(repo: &git2::Repository, signer: &MockSigner) -> Vec { + fn gen_ops(repo: &git::raw::Repository, signer: &MockSigner) -> Vec { // Number of ops let n = gen::(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>, parent: Option, diff --git a/crates/radicle/src/cob/stream/error.rs b/crates/radicle/src/cob/stream/error.rs index 3cea5bb5..0ac15c71 100644 --- a/crates/radicle/src/cob/stream/error.rs +++ b/crates/radicle/src/cob/stream/error.rs @@ -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}")] diff --git a/crates/radicle/src/cob/stream/iter.rs b/crates/radicle/src/cob/stream/iter.rs index 6f986e4c..66d3d7ae 100644 --- a/crates/radicle/src/cob/stream/iter.rs +++ b/crates/radicle/src/cob/stream/iter.rs @@ -39,7 +39,7 @@ impl From 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, /// The revwalk that is being iterated over. - inner: git2::Revwalk<'a>, + inner: git::raw::Revwalk<'a>, } impl From for Walk { @@ -76,10 +76,10 @@ impl Walk { } /// Get the iterator for the walk. - pub(super) fn iter(self, repo: &git2::Repository) -> Result, git2::Error> { + pub(super) fn iter(self, repo: &git::raw::Repository) -> Result, 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::Error>; + type Item = Result, git::raw::Error>; fn next(&mut self) -> Option { // N.b. ensure that we start using the `from` commit and use the revwalk diff --git a/crates/radicle/src/git.rs b/crates/radicle/src/git.rs index 9c1769dc..9b70c81d 100644 --- a/crates/radicle/src/git.rs +++ b/crates/radicle/src/git.rs @@ -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, }, #[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, 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::Error> { + repo: &'a raw::Repository, + sig: &raw::Signature, +) -> Result, 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::Error> { + sig: &raw::Signature, + tree: &raw::Tree, +) -> Result, 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::Error> { + sig: &raw::Signature, +) -> Result, 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 { +pub fn head(repo: &raw::Repository) -> Result { let head = repo.head()?.peel_to_commit()?; Ok(head) @@ -609,8 +609,8 @@ pub fn head(repo: &git2::Repository) -> Result { pub fn write_tree<'r>( path: &Path, bytes: &[u8], - repo: &'r git2::Repository, -) -> Result, Error> { + repo: &'r raw::Repository, +) -> Result, 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::Error> { +) -> Result, 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, &'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, branch: impl AsRef, merge: impl AsRef, -) -> 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, git2::Error> { +pub fn init_default_branch(repo: &raw::Repository) -> Result, 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, git2::Error> { +pub fn head_refname(repo: &raw::Repository) -> Result, raw::Error> { let head = repo.head()?; match head.shorthand() { Some("HEAD") => Ok(None), diff --git a/crates/radicle/src/git/canonical/effects.rs b/crates/radicle/src/git/canonical/effects.rs index c985f7c6..65c95bea 100644 --- a/crates/radicle/src/git/canonical/effects.rs +++ b/crates/radicle/src/git/canonical/effects.rs @@ -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 { 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, diff --git a/crates/radicle/src/git/canonical/rules.rs b/crates/radicle/src/git/canonical/rules.rs index ae0a2ed3..abfbb12a 100644 --- a/crates/radicle/src/git/canonical/rules.rs +++ b/crates/radicle/src/git/canonical/rules.rs @@ -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(); diff --git a/crates/radicle/src/git/raw.rs b/crates/radicle/src/git/raw.rs new file mode 100644 index 00000000..3a9c0522 --- /dev/null +++ b/crates/radicle/src/git/raw.rs @@ -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, + }; +} diff --git a/crates/radicle/src/identity/doc.rs b/crates/radicle/src/identity/doc.rs index db27c47d..305766c2 100644 --- a/crates/radicle/src/identity/doc.rs +++ b/crates/radicle/src/identity/doc.rs @@ -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 { + pub fn from_blob(blob: &git::raw::Blob) -> Result { RawDoc::from_json(blob.content())?.verified() } @@ -830,7 +830,7 @@ impl Doc { pub(crate) fn blob_at( commit: Oid, repo: &R, - ) -> Result { + ) -> Result { 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::(1); let proj = arbitrary::gen::(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(_)); diff --git a/crates/radicle/src/identity/doc/id.rs b/crates/radicle/src/identity/doc/id.rs index 237d5cdd..46eb0c87 100644 --- a/crates/radicle/src/identity/doc/id.rs +++ b/crates/radicle/src/identity/doc/id.rs @@ -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 for RepoId { } } -impl From for RepoId { - fn from(oid: git2::Oid) -> Self { +impl From for RepoId { + fn from(oid: git::raw::Oid) -> Self { Self(oid.into()) } } diff --git a/crates/radicle/src/profile.rs b/crates/radicle/src/profile.rs index 739a6f42..cf3925c4 100644 --- a/crates/radicle/src/profile.rs +++ b/crates/radicle/src/profile.rs @@ -88,7 +88,7 @@ pub mod env { /// Get the configured pager program from the environment. pub fn pager() -> Option { - 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); } diff --git a/crates/radicle/src/rad.rs b/crates/radicle/src/rad.rs index 8497f1dd..505a0d64 100644 --- a/crates/radicle/src/rad.rs +++ b/crates/radicle/src/rad.rs @@ -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( - repo: &git2::Repository, + repo: &git::raw::Repository, name: ProjectName, description: &str, default_branch: BranchName, @@ -96,7 +96,7 @@ where } fn init_configure( - 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, S: storage::ReadStorage>( path: P, storage: &S, bare: bool, -) -> Result { +) -> Result { // 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, 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) -> Result<(git2::Repository, RepoId), RemoteError> { - let repo = git2::Repository::open(path)?; +pub fn at(path: impl AsRef) -> 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 { - let mut flags = git2::RepositoryOpenFlags::empty(); +pub fn repo() -> Result { + 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 { #[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 { +pub fn repo_jj_git_root() -> Result { let output = std::process::Command::new("jj") .args(["git", "root"]) .output()?; @@ -450,7 +450,7 @@ pub fn repo_jj_git_root() -> Result { } 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. diff --git a/crates/radicle/src/schemars_ext.rs b/crates/radicle/src/schemars_ext.rs index 9157c729..07b125f2 100644 --- a/crates/radicle/src/schemars_ext.rs +++ b/crates/radicle/src/schemars_ext.rs @@ -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( diff --git a/crates/radicle/src/storage.rs b/crates/radicle/src/storage.rs index 92892959..7fbe5e13 100644 --- a/crates/radicle/src/storage.rs +++ b/crates/radicle/src/storage.rs @@ -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; + fn is_empty(&self) -> Result; /// 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>(&self, commit: Oid, path: P) -> Result; + fn blob_at>( + &self, + commit: Oid, + path: P, + ) -> Result; /// Get a blob in this repository, given its id. - fn blob(&self, oid: Oid) -> Result; + fn blob(&self, oid: Oid) -> Result; /// Get the head of this repository. /// @@ -572,18 +576,18 @@ pub trait ReadRepository: Sized + ValidateRepository { &self, remote: &RemoteId, reference: &Qualified, - ) -> Result; + ) -> Result; - /// 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; + fn commit(&self, oid: Oid) -> Result; /// Perform a revision walk of a commit history starting from the given head. - fn revwalk(&self, head: Oid) -> Result; + fn revwalk(&self, head: Oid) -> Result; /// Check if the underlying ODB contains the given `oid`. - fn contains(&self, oid: Oid) -> Result; + fn contains(&self, oid: Oid) -> Result; /// Check whether the given commit is an ancestor of another commit. fn is_ancestor_of(&self, ancestor: Oid, head: Oid) -> Result; @@ -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. diff --git a/crates/radicle/src/storage/git.rs b/crates/radicle/src/storage/git.rs index 00e04c9f..2e11130a 100644 --- a/crates/radicle/src/storage/git.rs +++ b/crates/radicle/src/storage/git.rs @@ -56,10 +56,10 @@ pub struct Ref { pub namespace: Option, } -impl TryFrom> for Ref { +impl TryFrom> for Ref { type Error = RefError; - fn try_from(r: git2::Reference) -> Result { + fn try_from(r: git::raw::Reference) -> Result { let name = r.name().ok_or(RefError::InvalidName)?; let (namespace, name) = match git::parse_ref_namespaced::(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 for Repository { @@ -380,12 +380,12 @@ pub enum Validation { impl Repository { /// Open an existing repository. pub fn open>(path: P, id: RepoId) -> Result { - 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>(path: P, id: RepoId, info: &UserInfo) -> Result { - 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> + '_, git2::Error> { + ) -> Result> + '_, git::raw::Error> { let refs = self .backend .references()? @@ -539,7 +539,7 @@ impl Repository { pub fn remote_ids( &self, - ) -> Result> + '_, git2::Error> { + ) -> Result> + '_, git::raw::Error> { let iter = self.backend.references_glob(SIGREFS_GLOB.as_str())?.map( |reference| -> Result { let r = reference?; @@ -556,7 +556,7 @@ impl Repository { &self, ) -> Result< impl Iterator), 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 { + fn is_empty(&self) -> Result { Ok(self.remotes()?.next().is_none()) } @@ -660,7 +660,7 @@ impl ReadRepository for Repository { self.backend.path() } - fn blob_at>(&self, commit: Oid, path: P) -> Result { + fn blob_at>(&self, commit: Oid, path: P) -> Result { 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 { + fn blob(&self, oid: Oid) -> Result { 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 { + ) -> Result { 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 { + fn commit(&self, oid: Oid) -> Result { self.backend .find_commit(oid.into()) .map_err(git::Error::from) } - fn revwalk(&self, head: Oid) -> Result { + fn revwalk(&self, head: Oid) -> Result { 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, 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( diff --git a/crates/radicle/src/storage/git/cob.rs b/crates/radicle/src/storage/git/cob.rs index 6f8fee88..f35a4509 100644 --- a/crates/radicle/src/storage/git/cob.rs +++ b/crates/radicle/src/storage/git/cob.rs @@ -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 = ::StoreError; - type LoadError = ::LoadError; + type StoreError = ::StoreError; + type LoadError = ::LoadError; - type ObjectId = ::ObjectId; - type Parent = ::Parent; - type Signatures = ::Signatures; + type ObjectId = ::ObjectId; + type Parent = ::Parent; + type Signatures = ::Signatures; fn store( &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 cob::Store for DraftStore<'_, R> {} impl change::Storage for DraftStore<'_, R> { - type StoreError = ::StoreError; - type LoadError = ::LoadError; + type StoreError = ::StoreError; + type LoadError = ::LoadError; - type ObjectId = ::ObjectId; - type Parent = ::Parent; - type Signatures = ::Signatures; + type ObjectId = ::ObjectId; + type Parent = ::Parent; + type Signatures = ::Signatures; fn store( &self, @@ -274,7 +274,7 @@ impl ReadRepository for DraftStore<'_, R> { self.repo.id() } - fn is_empty(&self) -> Result { + fn is_empty(&self) -> Result { self.repo.is_empty() } @@ -290,11 +290,11 @@ impl ReadRepository for DraftStore<'_, R> { self.repo.path() } - fn commit(&self, oid: Oid) -> Result { + fn commit(&self, oid: Oid) -> Result { self.repo.commit(oid) } - fn revwalk(&self, head: Oid) -> Result { + fn revwalk(&self, head: Oid) -> Result { self.repo.revwalk(head) } @@ -310,7 +310,7 @@ impl ReadRepository for DraftStore<'_, R> { &self, oid: git_ext::Oid, path: P, - ) -> Result { + ) -> Result { self.repo.blob_at(oid, path) } @@ -322,7 +322,7 @@ impl ReadRepository for DraftStore<'_, R> { &self, remote: &RemoteId, reference: &git::Qualified, - ) -> Result { + ) -> Result { self.repo.reference(remote, reference) } @@ -381,8 +381,8 @@ impl ReadRepository for DraftStore<'_, R> { impl 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; diff --git a/crates/radicle/src/storage/git/transport/local.rs b/crates/radicle/src/storage/git/transport/local.rs index 086229f6..4a5ecd00 100644 --- a/crates/radicle/src/storage/git/transport/local.rs +++ b/crates/radicle/src/storage/git/transport/local.rs @@ -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>, } -impl git2::transport::SmartSubtransport for Local { +impl crate::git::raw::transport::SmartSubtransport for Local { fn action( &self, url: &str, - service: git2::transport::Service, - ) -> Result, 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, 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"); }); diff --git a/crates/radicle/src/storage/git/transport/remote/mock.rs b/crates/radicle/src/storage/git/transport/remote/mock.rs index c4585cde..76066c26 100644 --- a/crates/radicle/src/storage/git/transport/remote/mock.rs +++ b/crates/radicle/src/storage/git/transport/remote/mock.rs @@ -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>> = #[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, 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, 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"); }); diff --git a/crates/radicle/src/storage/refs.rs b/crates/radicle/src/storage/refs.rs index 7a850440..74ac32c6 100644 --- a/crates/radicle/src/storage/refs.rs +++ b/crates/radicle/src/storage/refs.rs @@ -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 { 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 { &author, "Update signed refs\n", &tree, - &parent.iter().collect::>(), + &parent.iter().collect::>(), ); 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, diff --git a/crates/radicle/src/test.rs b/crates/radicle/src/test.rs index 9a9e8eec..b21ee03e 100644 --- a/crates/radicle/src/test.rs +++ b/crates/radicle/src/test.rs @@ -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( 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, T: AsRef<[u8]>>( - repo: &git2::Repository, + repo: &git::raw::Repository, refname: &git::Qualified, blobs: impl IntoIterator, - 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()), diff --git a/crates/radicle/src/test/fixtures.rs b/crates/radicle/src/test/fixtures.rs index 67da9412..f30d92e7 100644 --- a/crates/radicle/src/test/fixtures.rs +++ b/crates/radicle/src/test/fixtures.rs @@ -72,7 +72,15 @@ pub fn project( path: P, storage: &Storage, signer: &Device, -) -> Result<(RepoId, SignedRefs, git2::Repository, git2::Oid), rad::InitError> +) -> Result< + ( + RepoId, + SignedRefs, + git::raw::Repository, + git::raw::Oid, + ), + rad::InitError, +> where P: AsRef, G: crypto::signature::Signer, @@ -94,19 +102,19 @@ where } /// Creates a regular repository at the given path with a couple of commits. -pub fn repository>(path: P) -> (git2::Repository, git2::Oid) { +pub fn repository>(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>(path: P) -> (git2::Repository, git2::Oid) { +pub fn bare_repository>(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>(path: P) -> (git2::Repository, git2::Oid) fn repository_with>( 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>( } /// 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 { +pub fn populate(repo: &git::raw::Repository, scale: usize) -> Vec { 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 { .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>(path: P) -> (git2::Repository, git2::Oid) { - let repo = git2::Repository::init_opts( + pub fn repository>(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(); diff --git a/crates/radicle/src/test/storage.rs b/crates/radicle/src/test/storage.rs index a2ea5db6..54c02f36 100644 --- a/crates/radicle/src/test/storage.rs +++ b/crates/radicle/src/test/storage.rs @@ -199,7 +199,7 @@ impl ReadRepository for MockRepository { self.id } - fn is_empty(&self) -> Result { + fn is_empty(&self) -> Result { Ok(self.remotes.is_empty()) } @@ -215,17 +215,17 @@ impl ReadRepository for MockRepository { todo!() } - fn commit(&self, oid: Oid) -> Result { + fn commit(&self, oid: Oid) -> Result { Err(git_ext::Error::NotFound(git_ext::NotFound::NoSuchObject( *oid, ))) } - fn revwalk(&self, _head: Oid) -> Result { + fn revwalk(&self, _head: Oid) -> Result { todo!() } - fn contains(&self, oid: Oid) -> Result { + fn contains(&self, oid: Oid) -> Result { Ok(self .remotes .values() @@ -236,7 +236,7 @@ impl ReadRepository for MockRepository { Ok(true) } - fn blob(&self, _oid: Oid) -> Result { + fn blob(&self, _oid: Oid) -> Result { todo!() } @@ -244,7 +244,7 @@ impl ReadRepository for MockRepository { &self, _oid: git_ext::Oid, _path: P, - ) -> Result { + ) -> Result { todo!() } @@ -252,7 +252,7 @@ impl ReadRepository for MockRepository { &self, _remote: &RemoteId, _reference: &git::Qualified, - ) -> Result { + ) -> Result { 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!() }