From 07011233eb9cb4427f689e285a7eabe1eddd690d Mon Sep 17 00:00:00 2001 From: Lorenz Leutgeb Date: Tue, 24 Mar 2026 21:23:05 +0100 Subject: [PATCH] radicle/sigrefs: Use `SignedRefsAt` everywhere To make more information available to callers, prefer returning `SignedRefsAt` everywhere. --- crates/radicle-fetch/src/sigrefs.rs | 2 +- crates/radicle-fetch/src/state.rs | 2 +- crates/radicle/src/rad.rs | 6 +++--- crates/radicle/src/storage.rs | 16 ++++++++-------- crates/radicle/src/storage/git.rs | 21 +++++++++++++-------- crates/radicle/src/storage/git/cob.rs | 4 ++-- crates/radicle/src/storage/refs.rs | 2 +- crates/radicle/src/test/fixtures.rs | 4 ++-- crates/radicle/src/test/storage.rs | 17 ++++------------- 9 files changed, 35 insertions(+), 39 deletions(-) diff --git a/crates/radicle-fetch/src/sigrefs.rs b/crates/radicle-fetch/src/sigrefs.rs index 71af28de..ab5dc2b6 100644 --- a/crates/radicle-fetch/src/sigrefs.rs +++ b/crates/radicle-fetch/src/sigrefs.rs @@ -23,7 +23,7 @@ pub mod error { pub(crate) fn validate( repo: &impl ValidateRepository, - SignedRefsAt { sigrefs, .. }: SignedRefsAt, + sigrefs: SignedRefsAt, ) -> Result, radicle::storage::Error> { let remote = radicle::storage::Remote::new(sigrefs); let validations = repo.validate_remote(&remote)?; diff --git a/crates/radicle-fetch/src/state.rs b/crates/radicle-fetch/src/state.rs index d00b5f15..a9c52499 100644 --- a/crates/radicle-fetch/src/state.rs +++ b/crates/radicle-fetch/src/state.rs @@ -799,7 +799,7 @@ where // with it. fn validate_remote(&self, remote: &Remote) -> Result { // Contains a copy of the signed refs of this remote. - let mut signed = BTreeMap::from((*remote.refs).clone()); + let mut signed = BTreeMap::from((*remote.refs.sigrefs).clone()); let mut validations = Validations::default(); let mut has_sigrefs = false; diff --git a/crates/radicle/src/rad.rs b/crates/radicle/src/rad.rs index ca2994fd..816e1ada 100644 --- a/crates/radicle/src/rad.rs +++ b/crates/radicle/src/rad.rs @@ -15,7 +15,7 @@ use crate::identity::project::{Project, ProjectName}; use crate::node::device::Device; use crate::storage::git::transport; use crate::storage::git::Repository; -use crate::storage::refs::SignedRefs; +use crate::storage::refs::SignedRefsAt; use crate::storage::RepositoryError; use crate::storage::{ReadRepository as _, RemoteId, SignRepository as _}; use crate::storage::{WriteRepository, WriteStorage}; @@ -55,7 +55,7 @@ pub fn init( visibility: Visibility, signer: &Device, storage: S, -) -> Result<(RepoId, identity::Doc, SignedRefs), InitError> +) -> Result<(RepoId, identity::Doc, SignedRefsAt), InitError> where G: crypto::signature::Signer, S: WriteStorage, @@ -102,7 +102,7 @@ fn init_configure( url: &git::Url, identity: git::Oid, signer: &Device, -) -> Result +) -> Result where G: crypto::signature::Signer, { diff --git a/crates/radicle/src/storage.rs b/crates/radicle/src/storage.rs index e8641542..83740539 100644 --- a/crates/radicle/src/storage.rs +++ b/crates/radicle/src/storage.rs @@ -28,7 +28,7 @@ use crate::node::SyncedAt; use crate::storage::git::NAMESPACES_GLOB; use crate::storage::refs::{FeatureLevel, Refs, SignedRefsAt}; -use self::refs::{RefsAt, SignedRefs}; +use self::refs::RefsAt; use crate::git::UserInfo; #[derive(Debug, Clone, PartialEq, Eq)] @@ -385,12 +385,12 @@ impl IntoIterator for Remotes { } } -impl From for RandomMap { +impl From for RandomMap { fn from(other: Remotes) -> Self { let mut remotes = RandomMap::with_hasher(fastrand::Rng::new().into()); for (k, v) in other.into_iter() { - remotes.insert(k, v.refs.into()); + remotes.insert(k, v.refs); } remotes } @@ -401,12 +401,12 @@ impl From for RandomMap { pub struct Remote { /// Git references published under this remote, and their hashes. #[serde(flatten)] - pub refs: SignedRefs, + pub refs: SignedRefsAt, } impl Remote { /// Create a new remotes object. - pub fn new(refs: impl Into) -> Self { + pub fn new(refs: impl Into) -> Self { Self { refs: refs.into() } } @@ -428,7 +428,7 @@ impl Remote { } impl Deref for Remote { - type Target = SignedRefs; + type Target = SignedRefsAt; fn deref(&self) -> &Self::Target { &self.refs @@ -697,14 +697,14 @@ pub trait WriteRepository: ReadRepository + SignRepository { /// Allows signing refs. pub trait SignRepository { /// Sign the repository's refs under the `refs/rad/sigrefs` branch. - fn sign_refs(&self, signer: &Device) -> Result + fn sign_refs(&self, signer: &Device) -> Result where G: crypto::signature::Signer; /// Sign the repository's refs under the `refs/rad/sigrefs` branch, even if unchanged. /// /// Most users will prefer [`Self::sign_refs`]. - fn force_sign_refs(&self, signer: &Device) -> Result + fn force_sign_refs(&self, signer: &Device) -> Result where G: crypto::signature::Signer; } diff --git a/crates/radicle/src/storage/git.rs b/crates/radicle/src/storage/git.rs index e4b00507..e405fc27 100644 --- a/crates/radicle/src/storage/git.rs +++ b/crates/radicle/src/storage/git.rs @@ -18,7 +18,7 @@ use crate::identity::doc::DocError; use crate::identity::{CanonicalRefs, Doc, DocAt, RepoId}; use crate::identity::{Identity, Project}; use crate::node::device::Device; -use crate::storage::refs::{FeatureLevel, Refs, SignedRefs, SignedRefsAt}; +use crate::storage::refs::{FeatureLevel, Refs, SignedRefsAt}; use crate::storage::{refs, SignedRefsInfo}; use crate::storage::{ ReadRepository, ReadStorage, Remote, Remotes, RepositoryInfo, SetHead, SignRepository, @@ -631,7 +631,12 @@ impl RemoteRepository for Repository { } fn remote(&self, remote: &RemoteId) -> Result { - let refs = SignedRefs::load(*remote, self)?; + let refs = SignedRefsAt::load(*remote, self)?; + let refs = refs.ok_or_else(|| { + refs::Error::Read(refs::sigrefs::read::error::Read::MissingSigrefs { + namespace: *remote, + }) + })?; Ok(Remote::new(refs)) } @@ -651,7 +656,7 @@ impl RemoteRepository for Repository { impl ValidateRepository for Repository { fn validate_remote(&self, remote: &Remote) -> Result { // Contains a copy of the signed refs of this remote. - let mut signed = BTreeMap::from((*remote.refs).clone()); + let mut signed = BTreeMap::from((*remote.refs.sigrefs).clone()); let mut failures = Validations::default(); let mut has_sigrefs = false; @@ -1002,14 +1007,14 @@ impl SignRepository for Repository { fn sign_refs>( &self, signer: &Device, - ) -> Result { + ) -> Result { self.sign_refs_with(signer, false) } fn force_sign_refs>( &self, signer: &Device, - ) -> Result { + ) -> Result { self.sign_refs_with(signer, true) } } @@ -1019,7 +1024,7 @@ impl Repository { &self, signer: &Device, force: bool, - ) -> Result { + ) -> Result { let remote = signer.public_key(); // Ensure the root reference is set, which is checked during sigref verification. if self @@ -1038,7 +1043,7 @@ impl Repository { refs.save(*remote, committer, self, signer)? }; - Ok(signed.sigrefs) + Ok(signed) } } @@ -1224,6 +1229,6 @@ mod tests { unsigned.remove_sigrefs().unwrap(); assert_eq!(remote.refs.refs(), signed.refs()); - assert_eq!(*remote.refs, unsigned); + assert_eq!(*remote.refs.refs(), unsigned); } } diff --git a/crates/radicle/src/storage/git/cob.rs b/crates/radicle/src/storage/git/cob.rs index 889c9c2a..5b3687b1 100644 --- a/crates/radicle/src/storage/git/cob.rs +++ b/crates/radicle/src/storage/git/cob.rs @@ -239,7 +239,7 @@ where fn sign_refs>( &self, signer: &Device, - ) -> Result { + ) -> Result { // Since this is a draft store, we do not actually want to sign the refs. // Instead, we just return the existing signed refs. let remote = self.repo.remote(signer.public_key())?; @@ -250,7 +250,7 @@ where fn force_sign_refs>( &self, signer: &Device, - ) -> Result { + ) -> Result { self.sign_refs(signer) } } diff --git a/crates/radicle/src/storage/refs.rs b/crates/radicle/src/storage/refs.rs index fa83cbf6..445fc080 100644 --- a/crates/radicle/src/storage/refs.rs +++ b/crates/radicle/src/storage/refs.rs @@ -471,7 +471,7 @@ impl std::fmt::Display for RefsAt { /// Verified [`SignedRefs`] that keeps track of their content address /// [`Oid`]. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub struct SignedRefsAt { pub sigrefs: SignedRefs, pub at: Oid, diff --git a/crates/radicle/src/test/fixtures.rs b/crates/radicle/src/test/fixtures.rs index bb80e6bc..eb9d1c2b 100644 --- a/crates/radicle/src/test/fixtures.rs +++ b/crates/radicle/src/test/fixtures.rs @@ -10,7 +10,7 @@ use crate::node::Alias; use crate::rad; use crate::storage::git::transport; use crate::storage::git::Storage; -use crate::storage::refs::SignedRefs; +use crate::storage::refs::SignedRefsAt; /// The birth of the radicle project, January 1st, 2018. pub const RADICLE_EPOCH: i64 = 1514817556; @@ -72,7 +72,7 @@ pub fn project( path: P, storage: &Storage, signer: &Device, -) -> Result<(RepoId, SignedRefs, git::raw::Repository, git::raw::Oid), rad::InitError> +) -> Result<(RepoId, SignedRefsAt, git::raw::Repository, git::raw::Oid), rad::InitError> where P: AsRef, G: crypto::signature::Signer, diff --git a/crates/radicle/src/test/storage.rs b/crates/radicle/src/test/storage.rs index 45eb6026..c41e0dc4 100644 --- a/crates/radicle/src/test/storage.rs +++ b/crates/radicle/src/test/storage.rs @@ -181,9 +181,7 @@ impl RemoteRepository for MockRepository { fn remote(&self, id: &RemoteId) -> Result { self.remotes .get(id) - .map(|refs| Remote { - refs: refs.sigrefs.clone(), - }) + .map(|refs| Remote { refs: refs.clone() }) .ok_or(refs::Error::InvalidRef) } @@ -191,14 +189,7 @@ impl RemoteRepository for MockRepository { Ok(self .remotes .iter() - .map(|(id, refs)| { - ( - *id, - Remote { - refs: refs.sigrefs.clone(), - }, - ) - }) + .map(|(id, refs)| (*id, Remote { refs: refs.clone() })) .collect()) } @@ -379,14 +370,14 @@ impl SignRepository for MockRepository { fn sign_refs>( &self, _signer: &Device, - ) -> Result { + ) -> Result { todo!() } fn force_sign_refs>( &self, _signer: &Device, - ) -> Result { + ) -> Result { todo!() } }