From 16b22d9178fa6a1aaf2ecb01ec97e067399c5286 Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Sat, 29 Oct 2022 11:53:10 +0200 Subject: [PATCH] Move `radicle/id` and `radicle/signature` We move the identity branch out of `heads/` and to the old location: refs/rad/id We move the signed refs branch to: refs/rad/sigrefs Keeping both "special" branches under the same hierarchy makes things a bit easier to work with, and tells the user that they should be updated with special tooling. We also revert to `rad/` because we no longer have the issue of having `rad/rad/id` when doing a checkout of the remote branch in a working copy. Signed-off-by: Alexis Sellier --- radicle/src/git.rs | 30 ++++++++++++++++++------ radicle/src/identity/project.rs | 13 ++++------- radicle/src/rad.rs | 2 +- radicle/src/storage/git.rs | 41 +++++++++++++++++---------------- radicle/src/storage/refs.rs | 20 +++++++--------- radicle/src/test/arbitrary.rs | 2 +- 6 files changed, 59 insertions(+), 49 deletions(-) diff --git a/radicle/src/git.rs b/radicle/src/git.rs index 9cf1cf84..08d8bf82 100644 --- a/radicle/src/git.rs +++ b/radicle/src/git.rs @@ -19,7 +19,7 @@ pub use ext::Oid; pub use git2 as raw; pub use git_ref_format as fmt; pub use git_ref_format::{ - lit, name, qualified, refname, Component, Namespaced, Qualified, RefStr, RefString, + component, lit, name, qualified, refname, Component, Namespaced, Qualified, RefStr, RefString, }; pub use radicle_git_ext as ext; pub use storage::git::transport::local::Url; @@ -59,9 +59,6 @@ pub enum ListRefsError { pub mod refs { use super::*; - /// Where project information is kept. - pub static IDENTITY_BRANCH: Lazy = Lazy::new(|| refname!("radicle/id")); - /// Try to get a qualified reference from a generic reference. pub fn qualified_from<'a>(r: &'a git2::Reference) -> Result<(Qualified<'a>, Oid), RefError> { let name = r.name().ok_or(RefError::InvalidName)?; @@ -78,17 +75,36 @@ pub mod refs { pub mod storage { use super::*; + /// Where the project's identity document is stored. + /// + /// `refs/rad/id` + /// + pub static IDENTITY_BRANCH: Lazy = Lazy::new(|| { + Qualified::from_components(name::component!("rad"), name::component!("id"), None) + }); + + /// Where the project's signed references are stored. + /// + /// `refs/rad/sigrefs` + /// + pub static SIGREFS_BRANCH: Lazy = Lazy::new(|| { + Qualified::from_components(name::component!("rad"), name::component!("sigrefs"), None) + }); + /// Create the [`Namespaced`] `branch` under the `remote` namespace, i.e. + /// /// `refs/namespaces//refs/heads/` + /// pub fn branch<'a>(remote: &RemoteId, branch: &RefStr) -> Namespaced<'a> { Qualified::from(git_ref_format::lit::refs_heads(branch)).with_namespace(remote.into()) } - /// Get the branch used to track project information. + /// Get the branch where the project's identity document is stored. + /// + /// `refs/namespaces//refs/rad/id` /// - /// `refs/namespaces//refs/heads/radicle/id` pub fn id(remote: &RemoteId) -> Namespaced { - branch(remote, &IDENTITY_BRANCH) + IDENTITY_BRANCH.with_namespace(remote.into()) } } diff --git a/radicle/src/identity/project.rs b/radicle/src/identity/project.rs index 3b880231..a2337b8d 100644 --- a/radicle/src/identity/project.rs +++ b/radicle/src/identity/project.rs @@ -31,9 +31,11 @@ pub struct Untrusted; #[derive(Clone, Copy, Debug)] pub struct Trusted; +/// Path to the identity document in the identity branch. pub static PATH: Lazy<&Path> = Lazy::new(|| Path::new("radicle.json")); - +/// Maximum length of a string in the identity document. pub const MAX_STRING_LENGTH: usize = 255; +/// Maximum number of a delegates in the identity document. pub const MAX_DELEGATES: usize = 255; #[derive(Error, Debug)] @@ -148,11 +150,6 @@ impl Doc { msg: &str, storage: &S, ) -> Result<(Id, git::Oid, S::Repository), DocError> { - // You can checkout this branch in your working copy with: - // - // git fetch rad - // git checkout -b radicle/id remotes/rad/radicle/id - // let (doc_oid, doc) = self.encode()?; let id = Id::from(doc_oid); let repo = storage.repository(id)?; @@ -358,8 +355,8 @@ impl Doc { impl Doc { pub fn head(remote: &RemoteId, repo: &R) -> Result { - let head = git::Qualified::from(git::lit::refs_heads(&*git::refs::IDENTITY_BRANCH)); - repo.reference_oid(remote, &head).map_err(DocError::from) + repo.reference_oid(remote, &git::refs::storage::IDENTITY_BRANCH) + .map_err(DocError::from) } } diff --git a/radicle/src/rad.rs b/radicle/src/rad.rs index 7ac4993c..0049217a 100644 --- a/radicle/src/rad.rs +++ b/radicle/src/rad.rs @@ -122,7 +122,7 @@ pub fn fork_remote( // Creates or copies the following references: // // refs/remotes//heads/master - // refs/remotes//heads/radicle/id + // refs/remotes//rad/id // refs/remotes//tags/* // refs/remotes//rad/signature diff --git a/radicle/src/storage/git.rs b/radicle/src/storage/git.rs index 6f21948e..6440d2aa 100644 --- a/radicle/src/storage/git.rs +++ b/radicle/src/storage/git.rs @@ -24,10 +24,10 @@ pub use crate::git::*; use super::{Namespaces, RefUpdate, RemoteId}; use transport::remote; -pub static REMOTES_GLOB: Lazy = +pub static NAMESPACES_GLOB: Lazy = Lazy::new(|| refspec::pattern!("refs/namespaces/*")); -pub static SIGNATURES_GLOB: Lazy = - Lazy::new(|| refspec::pattern!("refs/namespaces/*/radicle/signature")); +pub static SIGREFS_GLOB: Lazy = + Lazy::new(|| refspec::pattern!("refs/namespaces/*/rad/sigrefs")); // TODO: Is this is the wrong place for this type? #[derive(Error, Debug)] @@ -309,7 +309,7 @@ impl Repository { pub fn remote_ids( &self, ) -> Result> + '_, git2::Error> { - let iter = self.backend.references_glob(SIGNATURES_GLOB.as_str())?.map( + let iter = self.backend.references_glob(SIGREFS_GLOB.as_str())?.map( |reference| -> Result { let r = reference?; let name = r.name().ok_or(refs::Error::InvalidRef)?; @@ -327,16 +327,17 @@ impl Repository { impl Iterator), refs::Error>> + '_, git2::Error, > { - let remotes = self.backend.references_glob(SIGNATURES_GLOB.as_str())?.map( - |reference| -> Result<_, _> { - let r = reference?; - let name = r.name().ok_or(refs::Error::InvalidRef)?; - let (id, _) = git::parse_ref_namespaced::(name)?; - let remote = self.remote(&id)?; + let remotes = + self.backend + .references_glob(SIGREFS_GLOB.as_str())? + .map(|reference| -> Result<_, _> { + let r = reference?; + let name = r.name().ok_or(refs::Error::InvalidRef)?; + let (id, _) = git::parse_ref_namespaced::(name)?; + let remote = self.remote(&id)?; - Ok((id, remote)) - }, - ); + Ok((id, remote)) + }); Ok(remotes) } @@ -358,7 +359,7 @@ impl Repository { return Ok(None); }; - if refname == *refs::SIGNATURE_REF { + if refname == *refs::SIGREFS_BRANCH { // Ignore the signed-refs reference, as this is what we're verifying. return Ok(None); } @@ -714,7 +715,7 @@ mod tests { use crate::assert_matches; use crate::git; use crate::rad; - use crate::storage::refs::SIGNATURE_REF; + use crate::storage::refs::SIGREFS_BRANCH; use crate::storage::{ReadRepository, ReadStorage, RefUpdate, WriteRepository}; use crate::test::arbitrary; use crate::test::fixtures; @@ -733,7 +734,7 @@ mod tests { // Strip the remote refs of sigrefs so we can compare them. for remote in refs.values_mut() { - let sigref = (*SIGNATURE_REF).to_ref_string(); + let sigref = (*SIGREFS_BRANCH).to_ref_string(); remote.remove(&sigref).unwrap(); } @@ -866,7 +867,7 @@ mod tests { .collect::>(); refs.sort(); - assert_eq!(refs, vec!["refs/heads/master", "refs/heads/radicle/id"]); + assert_eq!(refs, vec!["refs/heads/master", "refs/rad/id"]); } #[test] @@ -972,8 +973,8 @@ mod tests { updates, vec![ format!("refs/namespaces/{remote}/refs/heads/master"), - format!("refs/namespaces/{remote}/refs/heads/radicle/id"), - format!("refs/namespaces/{remote}/refs/radicle/signature") + format!("refs/namespaces/{remote}/refs/rad/id"), + format!("refs/namespaces/{remote}/refs/rad/sigrefs") ] ); } @@ -1005,7 +1006,7 @@ mod tests { let mut unsigned = project.references(&alice).unwrap(); // The signed refs doesn't contain the signature ref itself. - let sigref = (*SIGNATURE_REF).to_ref_string(); + let sigref = (*SIGREFS_BRANCH).to_ref_string(); unsigned.remove(&sigref).unwrap(); assert_eq!(remote.refs, signed); diff --git a/radicle/src/storage/refs.rs b/radicle/src/storage/refs.rs index 563a2073..a498e146 100644 --- a/radicle/src/storage/refs.rs +++ b/radicle/src/storage/refs.rs @@ -8,23 +8,19 @@ use std::path::Path; use std::str::FromStr; use crypto::{PublicKey, Signature, Signer, Unverified, Verified}; -use once_cell::sync::Lazy; -use radicle_git_ext as git_ext; use thiserror::Error; use crate::git; +use crate::git::ext as git_ext; use crate::git::Oid; use crate::storage; use crate::storage::{ReadRepository, RemoteId, WriteRepository}; -pub static SIGNATURE_REF: Lazy = Lazy::new(|| { - git::Qualified::from_components( - git::name::component!("radicle"), - git::name::component!("signature"), - None, - ) -}); +pub use crate::git::refs::storage::*; + +/// File in which the signed references are stored, in the `refs/rad/sigrefs` branch. pub const REFS_BLOB_PATH: &str = "refs"; +/// File in which the signature over the references is stored in the `refs/rad/sigrefs` branch. pub const SIGNATURE_BLOB_PATH: &str = "signature"; #[derive(Debug)] @@ -129,7 +125,7 @@ impl Refs { let mut buf = String::new(); let refs = self .iter() - .filter(|(name, oid)| name.as_refstr() != (*SIGNATURE_REF).as_ref() && !oid.is_zero()); + .filter(|(name, oid)| name.as_refstr() != SIGREFS_BRANCH.as_ref() && !oid.is_zero()); for (name, oid) in refs { buf.push_str(&oid.to_string()); @@ -231,7 +227,7 @@ impl SignedRefs { where S: ReadRepository, { - let oid = repo.reference_oid(remote, &SIGNATURE_REF)?; + let oid = repo.reference_oid(remote, &SIGREFS_BRANCH)?; SignedRefs::load_at(oid, remote, repo) } @@ -266,7 +262,7 @@ impl SignedRefs { remote: &RemoteId, repo: &S, ) -> Result { - let sigref = &*SIGNATURE_REF; + let sigref = &SIGREFS_BRANCH; let parent = match repo.reference(remote, sigref) { Ok(r) => Some(r.peel_to_commit()?), Err(git_ext::Error::Git(e)) if git_ext::is_not_found_err(&e) => None, diff --git a/radicle/src/test/arbitrary.rs b/radicle/src/test/arbitrary.rs index f536e24e..0e6c4d43 100644 --- a/radicle/src/test/arbitrary.rs +++ b/radicle/src/test/arbitrary.rs @@ -152,7 +152,7 @@ impl Arbitrary for Refs { "heads/feature/1", "heads/feature/2", "heads/feature/3", - "heads/radicle/id", + "rad/id", "tags/v1.0", "tags/v2.0", "notes/1",