diff --git a/crates/radicle-cli/src/commands/ls.rs b/crates/radicle-cli/src/commands/ls.rs index 387f4c81..478401c0 100644 --- a/crates/radicle-cli/src/commands/ls.rs +++ b/crates/radicle-cli/src/commands/ls.rs @@ -2,7 +2,7 @@ mod args; pub use args::Args; -use radicle::storage::{ReadStorage, RepositoryInfo}; +use radicle::storage::{ReadStorage, RepositoryInfo, SignedRefsInfo}; use crate::terminal as term; @@ -34,7 +34,7 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> { if !doc.is_public() && args.public { continue; } - if refs.is_none() && !args.all && !args.seeded { + if matches!(refs, SignedRefsInfo::None) && !args.all && !args.seeded { continue; } let seeded = policy.is_seeding(&rid)?; diff --git a/crates/radicle-protocol/src/service.rs b/crates/radicle-protocol/src/service.rs index cf9d177b..3b0c4f20 100644 --- a/crates/radicle-protocol/src/service.rs +++ b/crates/radicle-protocol/src/service.rs @@ -38,7 +38,7 @@ use radicle::node::seed; use radicle::node::seed::Store as _; use radicle::node::{Penalty, Severity}; use radicle::storage::refs::{FeatureLevel, SIGREFS_BRANCH}; -use radicle::storage::RepositoryError; +use radicle::storage::{RepositoryError, RepositoryInfo, SignedRefsInfo}; use radicle_fetch::policy::SeedingPolicy; use crate::fetcher; @@ -522,33 +522,19 @@ where Ok(()) } - fn upgrade_sigrefs(&mut self, info: &radicle::storage::RepositoryInfo) -> Result<(), Error> { - let Some(ref refs) = info.refs else { - // No refs, nothing to upgrade. - return Ok(()); - }; - - if refs.feature_level() >= FeatureLevel::LATEST && refs.parent().is_some() { - // Refs are at target level or above, nothing to upgrade. + fn upgrade_sigrefs(&mut self, info: &RepositoryInfo) -> Result<(), Error> { + if !matches!(info.refs, SignedRefsInfo::NeedsMigration) { return Ok(()); } let rid = info.rid; - if refs.parent().is_none() { - log::info!( - "Migrating `rad/sigrefs` of {rid} to force feature level {}, as the history currently contains only a root commit.", - FeatureLevel::LATEST - ); - } else { - log::info!( - "Migrating `rad/sigrefs` of {rid} from level {} which is lower than target level {}.", - refs.feature_level(), - FeatureLevel::LATEST - ); - } + log::info!( + "Migrating `rad/sigrefs` of {rid} to force feature level {}.", + FeatureLevel::LATEST + ); - let repo = self.storage.repository_mut(info.rid)?; + let repo = self.storage.repository_mut(rid)?; // NOTE: We assume to reach `FeatureLevel::LATEST` by signing refs. repo.force_sign_refs(&self.signer)?; Ok(()) diff --git a/crates/radicle/src/storage.rs b/crates/radicle/src/storage.rs index bd5aa619..e8641542 100644 --- a/crates/radicle/src/storage.rs +++ b/crates/radicle/src/storage.rs @@ -26,11 +26,40 @@ use crate::identity::{Identity, RepoId}; use crate::node::device::Device; use crate::node::SyncedAt; use crate::storage::git::NAMESPACES_GLOB; -use crate::storage::refs::Refs; +use crate::storage::refs::{FeatureLevel, Refs, SignedRefsAt}; use self::refs::{RefsAt, SignedRefs}; use crate::git::UserInfo; +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SignedRefsInfo { + /// Repositories with this set to `None` are ones that are seeded but not forked. + None, + /// Local signed refs, if any. + Some(refs::SignedRefsAt), + NeedsMigration, +} + +impl SignedRefsInfo { + pub(crate) fn new( + result: Result, refs::sigrefs::read::error::Read>, + ) -> Result { + Ok(match result { + Ok(Some(refs)) + if refs.feature_level() >= FeatureLevel::LATEST && refs.parent().is_some() => + { + SignedRefsInfo::Some(refs) + } + Ok(Some(_)) => SignedRefsInfo::NeedsMigration, + Ok(None) => SignedRefsInfo::None, + Err(refs::sigrefs::read::error::Read::Downgrade { .. }) => { + SignedRefsInfo::NeedsMigration + } + Err(err) => return Err(err), + }) + } +} + /// Basic repository information. #[derive(Debug, Clone, PartialEq, Eq)] pub struct RepositoryInfo { @@ -40,9 +69,8 @@ pub struct RepositoryInfo { pub head: Oid, /// Identity document. pub doc: Doc, - /// Local signed refs, if any. - /// Repositories with this set to `None` are ones that are seeded but not forked. - pub refs: Option, + /// Information about local signed references. + pub refs: SignedRefsInfo, /// Sync time of the repository. pub synced_at: Option, } diff --git a/crates/radicle/src/storage/git.rs b/crates/radicle/src/storage/git.rs index 02e86de6..e4b00507 100644 --- a/crates/radicle/src/storage/git.rs +++ b/crates/radicle/src/storage/git.rs @@ -18,9 +18,8 @@ use crate::identity::doc::DocError; use crate::identity::{CanonicalRefs, Doc, DocAt, RepoId}; use crate::identity::{Identity, Project}; use crate::node::device::Device; -use crate::node::SyncedAt; -use crate::storage::refs; use crate::storage::refs::{FeatureLevel, Refs, SignedRefs, SignedRefsAt}; +use crate::storage::{refs, SignedRefsInfo}; use crate::storage::{ ReadRepository, ReadStorage, Remote, Remotes, RepositoryInfo, SetHead, SignRepository, WriteRepository, WriteStorage, @@ -167,12 +166,13 @@ impl ReadStorage for Storage { } }; // Nb. This will be `None` if they were not found. - let refs = refs::SignedRefsAt::load(self.info.key, &repo) + let refs = SignedRefsInfo::new(refs::SignedRefsAt::load(self.info.key, &repo)) .map_err(|err| Error::Refs(refs::Error::Read(err)))?; - let synced_at = refs - .as_ref() - .map(|r| node::SyncedAt::new(r.at, &repo)) - .transpose()?; + + let synced_at = match &refs { + SignedRefsInfo::Some(refs) => Some(node::SyncedAt::new(refs.at, &repo)?), + _ => None, + }; repos.push(RepositoryInfo { rid, @@ -258,12 +258,13 @@ impl Storage { let repo = self.repository(*rid)?; let (_, head) = repo.head()?; - let refs = refs::SignedRefsAt::load(self.info.key, &repo) - .map_err(|err| RepositoryError::from(refs::Error::Read(err)))?; - let synced_at = refs - .as_ref() - .map(|r| SyncedAt::new(r.at, &repo)) - .transpose()?; + let refs = SignedRefsInfo::new(refs::SignedRefsAt::load(self.info.key, &repo)) + .map_err(|err| Error::Refs(refs::Error::Read(err)))?; + + let synced_at = match &refs { + SignedRefsInfo::Some(refs) => Some(node::SyncedAt::new(refs.at, &repo)?), + _ => None, + }; Ok(RepositoryInfo { rid: *rid, diff --git a/crates/radicle/src/test/storage.rs b/crates/radicle/src/test/storage.rs index 1b822ada..45eb6026 100644 --- a/crates/radicle/src/test/storage.rs +++ b/crates/radicle/src/test/storage.rs @@ -102,7 +102,7 @@ impl ReadStorage for MockStorage { rid: *rid, head: r.head().unwrap().1, doc: r.doc.clone().into(), - refs: None, + refs: SignedRefsInfo::None, synced_at: None, }) .collect())