Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
radicle: canoncial refs/rad/id
Fintan Halpenny committed 3 years ago
commit a32101ab75c10defdd3f8854f44a6c362bbf3ccd
parent b030e9ea80763b8120a264288da32af7cdbdabd9
4 files changed +71 -0
modified radicle/src/identity/doc.rs
@@ -18,6 +18,7 @@ use crate::crypto;
use crate::crypto::{Signature, Unverified, Verified};
use crate::git;
use crate::identity::{project::Project, Did};
+
use crate::storage;
use crate::storage::git::trailers;
use crate::storage::{ReadRepository, RemoteId};

@@ -142,6 +143,13 @@ pub struct Doc<V> {
}

impl<V> Doc<V> {
+
    pub fn canonical_head(repo: &storage::git::Repository) -> Result<Oid, DocError> {
+
        repo.backend
+
            .refname_to_id(storage::git::CANONICAL_IDENTITY.as_str())
+
            .map(Oid::from)
+
            .map_err(DocError::from)
+
    }
+

    pub fn head<R: ReadRepository>(remote: &RemoteId, repo: &R) -> Result<Oid, DocError> {
        repo.reference_oid(remote, &git::refs::storage::IDENTITY_BRANCH)
            .map_err(DocError::from)
@@ -215,6 +223,11 @@ impl Doc<Verified> {
        Ok((oid, sig))
    }

+
    pub fn canonical(repo: &storage::git::Repository) -> Result<DocAt, DocError> {
+
        let oid = Self::canonical_head(repo)?;
+
        Self::load_at(oid, repo)
+
    }
+

    pub fn load_at<R: ReadRepository>(oid: Oid, repo: &R) -> Result<DocAt, DocError> {
        let blob = Self::blob_at(oid, repo)?;
        let doc = Doc::from_json(blob.content())?.verified()?;
modified radicle/src/storage.rs
@@ -353,6 +353,17 @@ pub trait ReadRepository {
    /// Returns the [`Oid`] as well as the qualified reference name.
    fn canonical_head(&self) -> Result<(Qualified, Oid), IdentityError>;

+
    /// Get the head of the `rad/id` reference in this repository.
+
    ///
+
    /// Returns the reference pointed to by `rad/id` if it is set. Otherwise, computes the canonical
+
    /// `rad/id` using [`ReadRepository::canonical_identity_head`].
+
    fn identity_head(&self) -> Result<Oid, IdentityError>;
+

+
    /// Compute the canonical `rad/id` of this repository.
+
    ///
+
    /// Ignores any existing `rad/id` reference.
+
    fn canonical_identity_head(&self) -> Result<Oid, IdentityError>;
+

    /// Get the `reference` for the given `remote`.
    ///
    /// Returns `None` is the reference did not exist.
@@ -403,6 +414,8 @@ pub trait WriteRepository: ReadRepository {
    /// Set the repository head to the canonical branch.
    /// This computes the head based on the delegate set.
    fn set_head(&self) -> Result<Oid, IdentityError>;
+
    /// Set the repository 'rad/id' to the canonical commit, agreed by quorum.
+
    fn set_identity_head(&self) -> Result<Oid, IdentityError>;
    /// Sign the repository's refs under the `refs/rad/sigrefs` branch.
    fn sign_refs<G: Signer>(&self, signer: &G) -> Result<SignedRefs<Verified>, Error>;
    /// Get the underlying git repository.
modified radicle/src/storage/git.rs
@@ -28,6 +28,13 @@ pub static NAMESPACES_GLOB: Lazy<refspec::PatternString> =
    Lazy::new(|| refspec::pattern!("refs/namespaces/*"));
pub static SIGREFS_GLOB: Lazy<refspec::PatternString> =
    Lazy::new(|| refspec::pattern!("refs/namespaces/*/rad/sigrefs"));
+
pub static CANONICAL_IDENTITY: Lazy<git::Qualified> = Lazy::new(|| {
+
    git::Qualified::from_components(
+
        git::name::component!("rad"),
+
        git::name::component!("id"),
+
        None,
+
    )
+
});

/// A parsed Git reference.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -584,6 +591,18 @@ impl ReadRepository for Repository {

        Ok((branch_ref, oid.into()))
    }
+

+
    fn identity_head(&self) -> Result<Oid, IdentityError> {
+
        match Doc::<Verified>::canonical_head(self) {
+
            Ok(oid) => Ok(oid),
+
            Err(err) if err.is_not_found() => self.canonical_identity_head(),
+
            Err(err) => Err(err.into()),
+
        }
+
    }
+

+
    fn canonical_identity_head(&self) -> Result<Oid, IdentityError> {
+
        Repository::identity_head(self)
+
    }
}

impl WriteRepository for Repository {
@@ -602,6 +621,20 @@ impl WriteRepository for Repository {
        Ok(head)
    }

+
    fn set_identity_head(&self) -> Result<Oid, IdentityError> {
+
        let head = self.canonical_identity_head()?;
+

+
        log::debug!(target: "storage", "Setting ref: {} -> {}", *CANONICAL_IDENTITY, head);
+
        self.raw().reference(
+
            CANONICAL_IDENTITY.as_str(),
+
            *head,
+
            true,
+
            "set-local-branch (radicle)",
+
        )?;
+

+
        Ok(head)
+
    }
+

    fn sign_refs<G: Signer>(&self, signer: &G) -> Result<SignedRefs<Verified>, Error> {
        let remote = signer.public_key();
        let refs = self.references_of(remote)?;
modified radicle/src/test/storage.rs
@@ -194,6 +194,14 @@ impl ReadRepository for MockRepository {
    ) -> Result<(Oid, crate::identity::Doc<crate::crypto::Unverified>), IdentityError> {
        Ok((git2::Oid::zero().into(), self.doc.clone().unverified()))
    }
+

+
    fn identity_head(&self) -> Result<Oid, IdentityError> {
+
        todo!()
+
    }
+

+
    fn canonical_identity_head(&self) -> Result<Oid, IdentityError> {
+
        todo!()
+
    }
}

impl WriteRepository for MockRepository {
@@ -211,4 +219,8 @@ impl WriteRepository for MockRepository {
    ) -> Result<crate::storage::refs::SignedRefs<Verified>, Error> {
        todo!()
    }
+

+
    fn set_identity_head(&self) -> Result<Oid, IdentityError> {
+
        todo!()
+
    }
}