Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
radicle: Modifying `radicle::cob::stream::Stream` to accept not only `git2` repos
✗ CI failure Sebastian Martinez committed 4 months ago
commit b773bbacdc3d482e44a71b13acefc0afa65e7ce9
parent cf023f750dee2681eb73e4e0704da137ea2195ef
1 failed (1 total) View logs
5 files changed +130 -28
modified crates/radicle/src/cob/identity.rs
@@ -39,7 +39,7 @@ pub type Op = cob::Op<Action>;
/// Identifier for an identity revision.
pub type RevisionId = EntryId;

-
pub type IdentityStream<'a> = cob::stream::Stream<'a, Action>;
+
pub type IdentityStream<'a> = cob::stream::Stream<'a, Action, git::raw::Repository>;

impl<'a> IdentityStream<'a> {
    pub fn init(identity: ObjectId, store: &'a storage::git::Repository) -> Self {
modified crates/radicle/src/cob/issue.rs
@@ -8,7 +8,6 @@ use std::sync::LazyLock;
use serde::{Deserialize, Serialize};
use thiserror::Error;

-
use crate::cob;
use crate::cob::common::{Author, Authorization, Label, Reaction, Timestamp, Uri};
use crate::cob::store::Transaction;
use crate::cob::store::{Cob, CobAction};
@@ -21,6 +20,7 @@ use crate::node::NodeId;
use crate::prelude::{Did, Doc, ReadRepository, RepoId};
use crate::storage;
use crate::storage::{HasRepoId, RepositoryError, WriteRepository};
+
use crate::{cob, git};

pub use cache::Cache;

@@ -34,7 +34,7 @@ pub static TYPENAME: LazyLock<TypeName> =
/// Identifier for an issue.
pub type IssueId = ObjectId;

-
pub type IssueStream<'a> = cob::stream::Stream<'a, Action>;
+
pub type IssueStream<'a> = cob::stream::Stream<'a, Action, git::raw::Repository>;

impl<'a> IssueStream<'a> {
    pub fn init(issue: IssueId, store: &'a storage::git::Repository) -> Self {
modified crates/radicle/src/cob/patch.rs
@@ -46,7 +46,7 @@ pub type Op = cob::Op<Action>;
/// Identifier for a patch.
pub type PatchId = ObjectId;

-
pub type PatchStream<'a> = cob::stream::Stream<'a, Action>;
+
pub type PatchStream<'a> = cob::stream::Stream<'a, Action, git::raw::Repository>;

impl<'a> PatchStream<'a> {
    pub fn init(patch: PatchId, store: &'a storage::git::Repository) -> Self {
modified crates/radicle/src/cob/stream.rs
@@ -1,8 +1,10 @@
pub mod error;

mod iter;
+
use crypto::ssh::ExtendedSignature;
pub use iter::OpsIter;
use iter::Walk;
+
use radicle_cob::change::Storage;

use std::marker::PhantomData;

@@ -20,6 +22,65 @@ pub trait HasRoot {
    fn root(&self) -> Oid;
}

+
pub trait Revwalk<'a> {
+
    type Error: std::error::Error;
+
    type Sort;
+

+
    fn set_sorting(&mut self, sorting: Self::Sort) -> Result<(), Self::Error>;
+
    fn push_range(&mut self, range: &str) -> Result<(), Self::Error>;
+
    fn push(&mut self, oid: Oid) -> Result<(), Self::Error>;
+
    fn push_glob(&mut self, glob: &str) -> Result<(), Self::Error>;
+
    fn hide(&mut self, oid: Oid) -> Result<(), Self::Error>;
+
}
+

+
impl<'a> Revwalk<'a> for git::raw::Revwalk<'a> {
+
    type Error = git::raw::Error;
+
    type Sort = git::raw::Sort;
+

+
    fn set_sorting(&mut self, sorting: Self::Sort) -> Result<(), Self::Error> {
+
        self.set_sorting(sorting)
+
    }
+

+
    fn push_range(&mut self, range: &str) -> Result<(), Self::Error> {
+
        self.push_range(range)
+
    }
+

+
    fn push(&mut self, oid: Oid) -> Result<(), Self::Error> {
+
        self.push(oid.into())
+
    }
+

+
    fn push_glob(&mut self, glob: &str) -> Result<(), Self::Error> {
+
        self.push_glob(glob)
+
    }
+

+
    fn hide(&mut self, oid: Oid) -> Result<(), Self::Error> {
+
        self.hide(oid.into())
+
    }
+
}
+

+
pub trait Repo<'a> {
+
    type Revwalk;
+
    type Error: std::error::Error;
+
    type Commit;
+

+
    fn revwalk(&'a self) -> Result<Self::Revwalk, Self::Error>;
+
    fn find_commit(&'a self, oid: Oid) -> Result<Self::Commit, Self::Error>;
+
}
+

+
impl<'a> Repo<'a> for git::raw::Repository {
+
    type Revwalk = git::raw::Revwalk<'a>;
+
    type Error = git::raw::Error;
+
    type Commit = git::raw::Commit<'a>;
+

+
    fn revwalk(&'a self) -> Result<Self::Revwalk, Self::Error> {
+
        self.revwalk()
+
    }
+

+
    fn find_commit(&'a self, oid: Oid) -> Result<Self::Commit, Self::Error> {
+
        self.find_commit(oid.into())
+
    }
+
}
+

/// Provide the stream of operations that are related to a given COB.
///
/// The whole history of operations can be retrieved via [`CobStream::all`].
@@ -92,17 +153,20 @@ impl HasRoot for CobRange {
/// constructed via the [`CobStream`] methods.
///
/// To construct a `Stream`, use [`Stream::new`].
-
pub struct Stream<'a, A> {
-
    repo: &'a git::raw::Repository,
+
pub struct Stream<'a, A, R: Repo<'a>> {
+
    repo: &'a R,
    range: CobRange,
    typename: TypeName,
    marker: PhantomData<A>,
}

-
impl<'a, A> Stream<'a, A> {
+
impl<'a, A, R> Stream<'a, A, R>
+
where
+
    R: Repo<'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 git::raw::Repository, range: CobRange, typename: TypeName) -> Self {
+
    pub fn new(repo: &'a R, range: CobRange, typename: TypeName) -> Self {
        Self {
            repo,
            range,
@@ -112,19 +176,28 @@ impl<'a, A> Stream<'a, A> {
    }
}

-
impl<A> HasRoot for Stream<'_, A> {
+
impl<'a, A, R> HasRoot for Stream<'a, A, R>
+
where
+
    R: Repo<'a>,
+
{
    fn root(&self) -> Oid {
        self.range.root()
    }
}

-
impl<'a, A> CobStream for Stream<'a, A>
+
impl<'a, A, R> CobStream for Stream<'a, A, R>
where
    A: for<'de> Deserialize<'de>,
+
    R: Repo<
+
            'a,
+
            Revwalk = git::raw::Revwalk<'a>,
+
            Error = git::raw::Error,
+
            Commit = git::raw::Commit<'a>,
+
        > + Storage<ObjectId = Oid, Parent = Oid, Signatures = ExtendedSignature>,
{
    type IterError = error::Ops;
    type Action = A;
-
    type Iter = OpsIter<'a, Self::Action>;
+
    type Iter = OpsIter<'a, Self::Action, R>;

    fn all(&self) -> Result<Self::Iter, error::Stream> {
        Ok(OpsIter::new(
@@ -338,7 +411,7 @@ mod tests {
            root: ops.first().unwrap().id,
            until: ops.last().unwrap().id.into(),
        };
-
        let stream = Stream::<json::Value>::new(&repo, history, typename());
+
        let stream = Stream::<json::Value, _>::new(&repo, history, typename());
        prop_all_from(&stream)
    }

@@ -353,7 +426,7 @@ mod tests {
            root: ops.first().unwrap().id,
            until: tip.into(),
        };
-
        let stream = Stream::<json::Value>::new(&repo, history, typename());
+
        let stream = Stream::<json::Value, _>::new(&repo, history, typename());
        prop_all_until(&stream, tip)
    }

@@ -368,7 +441,7 @@ mod tests {
            root: ops.first().unwrap().id,
            until: tip.into(),
        };
-
        let stream = Stream::<json::Value>::new(&repo, history, typename());
+
        let stream = Stream::<json::Value, _>::new(&repo, history, typename());
        prop_all_from_until(&stream, tip)
    }

@@ -391,7 +464,7 @@ mod tests {
        } else {
            (ops[y].id, ops[x].id)
        };
-
        let stream = Stream::<json::Value>::new(&repo, history, typename());
+
        let stream = Stream::<json::Value, _>::new(&repo, history, typename());
        prop_from_until(&stream, from, until)
    }

@@ -425,7 +498,7 @@ mod tests {
            root: op1.id,
            until: op3.id.into(),
        };
-
        let stream = Stream::<json::Value>::new(&repo, history, typename());
+
        let stream = Stream::<json::Value, _>::new(&repo, history, typename());
        eprintln!("Op 1: {}", op1.id);
        eprintln!("Op 2: {}", op2.id);
        eprintln!("Op 3: {}", op3.id);
modified crates/radicle/src/cob/stream/iter.rs
@@ -1,7 +1,10 @@
use std::marker::PhantomData;

+
use crypto::ssh::ExtendedSignature;
+
use radicle_cob::change::Storage;
use serde::Deserialize;

+
use crate::cob::stream;
use crate::cob::{Op, TypeName};
use crate::git;
use crate::git::fmt::refspec::PatternString;
@@ -39,9 +42,9 @@ impl From<PatternString> for Until {

/// A revwalk over a set of commits, including the commit that is being walked
/// from.
-
pub(super) struct WalkIter<'a> {
+
pub(super) struct WalkIter<'a, R: stream::Repo<'a, Revwalk = git::raw::Revwalk<'a>>> {
    /// Git repository for looking up the commit object during the revwalk.
-
    repo: &'a git::raw::Repository,
+
    repo: &'a R,
    /// The root commit that is being walked from.
    ///
    /// N.b. This is required since ranges are non-inclusive in Git, and if the
@@ -49,7 +52,7 @@ pub(super) struct WalkIter<'a> {
    /// error.
    from: Option<Oid>,
    /// The revwalk that is being iterated over.
-
    inner: git::raw::Revwalk<'a>,
+
    inner: R::Revwalk,
}

impl From<CobRange> for Walk {
@@ -78,7 +81,13 @@ impl Walk {
    }

    /// Get the iterator for the walk.
-
    pub(super) fn iter(self, repo: &git::raw::Repository) -> Result<WalkIter<'_>, git::raw::Error> {
+
    pub(super) fn iter<
+
        'a,
+
        R: stream::Repo<'a, Revwalk = git::raw::Revwalk<'a>, Error = git::raw::Error>,
+
    >(
+
        self,
+
        repo: &'a R,
+
    ) -> Result<WalkIter<'a, R>, git::raw::Error> {
        let mut walk = repo.revwalk()?;
        // N.b. ensure that we start from the `self.from` commit.
        walk.set_sorting(git::raw::Sort::TOPOLOGICAL.union(git::raw::Sort::REVERSE))?;
@@ -98,7 +107,16 @@ impl Walk {
    }
}

-
impl<'a> Iterator for WalkIter<'a> {
+
impl<
+
        'a,
+
        R: stream::Repo<
+
            'a,
+
            Revwalk = git::raw::Revwalk<'a>,
+
            Commit = git::raw::Commit<'a>,
+
            Error = git::raw::Error,
+
        >,
+
    > Iterator for WalkIter<'a, R>
+
{
    type Item = Result<git::raw::Commit<'a>, git::raw::Error>;

    fn next(&mut self) -> Option<Self::Item> {
@@ -108,15 +126,15 @@ impl<'a> Iterator for WalkIter<'a> {
            return Some(self.repo.find_commit(from.into()));
        }
        let oid = self.inner.next()?;
-
        Some(oid.and_then(|oid| self.repo.find_commit(oid)))
+
        Some(oid.and_then(|oid| self.repo.find_commit(oid.into())))
    }
}

/// Iterate over all operations for a given range of commits.
-
pub struct OpsIter<'a, A> {
+
pub struct OpsIter<'a, A, R: stream::Repo<'a, Revwalk = git::raw::Revwalk<'a>>> {
    /// The [`WalkIter`] provides each commit that it is being walked over for a
    /// given range.
-
    walk: WalkIter<'a>,
+
    walk: WalkIter<'a, R>,
    /// The walk can iterate over other COBs, e.g. an Identity COB, so this is
    /// used to filter for the correct type.
    typename: TypeName,
@@ -124,9 +142,15 @@ pub struct OpsIter<'a, A> {
    action: PhantomData<A>,
}

-
impl<A> Iterator for OpsIter<'_, A>
+
impl<'a, A, R> Iterator for OpsIter<'a, A, R>
where
    A: for<'de> Deserialize<'de>,
+
    R: stream::Repo<
+
            'a,
+
            Revwalk = git::raw::Revwalk<'a>,
+
            Commit = git::raw::Commit<'a>,
+
            Error = git::raw::Error,
+
        > + Storage<ObjectId = Oid, Parent = Oid, Signatures = ExtendedSignature>,
{
    type Item = Result<Op<A>, error::Ops>;

@@ -136,7 +160,7 @@ where
            Ok(commit) => {
                let entry = crate::git::Oid::from(commit.id());
                // N.b. mark this commit as seen, so that it is not walked again
-
                self.walk.inner.hide(commit.id()).ok();
+
                self.walk.inner.hide(commit.id().into()).ok();
                // Skip any Op that do not match the manifest
                self.load(entry).transpose().or_else(|| self.next())
            }
@@ -146,8 +170,13 @@ where
    }
}

-
impl<'a, A> OpsIter<'a, A> {
-
    pub(super) fn new(walk: WalkIter<'a>, typename: TypeName) -> Self {
+
impl<'a, A, R> OpsIter<'a, A, R>
+
where
+
    A: for<'de> Deserialize<'de>,
+
    R: stream::Repo<'a, Revwalk = git::raw::Revwalk<'a>>
+
        + Storage<ObjectId = Oid, Parent = Oid, Signatures = ExtendedSignature>,
+
{
+
    pub(super) fn new(walk: WalkIter<'a, R>, typename: TypeName) -> Self {
        Self {
            walk,
            typename,