cob: abstract namespace identifier

This change is to help separate the fact the namespacing by a `NodeId` is a
Radicle specific concern. The identifier can, in theory, be any kind of path
component, as long it is valid in Git.

The motivation for the change is to help separate the idea of a device's
`NodeId` vs an agent being an author – for future agent repository work.
This commit is contained in:
Fintan Halpenny 2024-12-03 13:23:01 +00:00
parent 1f4fcc5e6a
commit 9988b63bb2
24 changed files with 105 additions and 81 deletions

View File

@ -7,6 +7,7 @@ use anyhow::{anyhow, Context};
use radicle::cob::identity::{self, IdentityMut, Revision, RevisionId}; use radicle::cob::identity::{self, IdentityMut, Revision, RevisionId};
use radicle::identity::{doc, Doc, Identity, PayloadError, RawDoc, Visibility}; use radicle::identity::{doc, Doc, Identity, PayloadError, RawDoc, Visibility};
use radicle::node::device::Device; use radicle::node::device::Device;
use radicle::node::NodeId;
use radicle::prelude::{Did, RepoId}; use radicle::prelude::{Did, RepoId};
use radicle::storage::refs; use radicle::storage::refs;
use radicle::storage::{ReadRepository, ReadStorage as _, WriteRepository}; use radicle::storage::{ReadRepository, ReadStorage as _, WriteRepository};
@ -731,7 +732,7 @@ fn update<R, G>(
signer: &Device<G>, signer: &Device<G>,
) -> anyhow::Result<Revision> ) -> anyhow::Result<Revision>
where where
R: WriteRepository + cob::Store, R: WriteRepository + cob::Store<Namespace = NodeId>,
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
{ {
if let Some((title, description)) = edit_title_description(title, description)? { if let Some((title, description)) = edit_title_description(title, description)? {

View File

@ -12,7 +12,7 @@ use radicle::issue::cache::Issues as _;
use radicle::node::notifications; use radicle::node::notifications;
use radicle::node::notifications::*; use radicle::node::notifications::*;
use radicle::patch::cache::Patches as _; use radicle::patch::cache::Patches as _;
use radicle::prelude::{Profile, RepoId}; use radicle::prelude::{NodeId, Profile, RepoId};
use radicle::storage::{BranchName, ReadRepository, ReadStorage}; use radicle::storage::{BranchName, ReadRepository, ReadStorage};
use radicle::{cob, git, Storage}; use radicle::{cob, git, Storage};
@ -261,7 +261,7 @@ fn list_repo<'a, R: ReadStorage>(
profile: &Profile, profile: &Profile,
) -> anyhow::Result<Option<term::VStack<'a>>> ) -> anyhow::Result<Option<term::VStack<'a>>>
where where
<R as ReadStorage>::Repository: cob::Store, <R as ReadStorage>::Repository: cob::Store<Namespace = NodeId>,
{ {
let mut table = term::Table::new(term::TableOptions { let mut table = term::Table::new(term::TableOptions {
spacing: 3, spacing: 3,

View File

@ -13,6 +13,7 @@ use radicle::cob::{issue, thread};
use radicle::crypto; use radicle::crypto;
use radicle::issue::cache::Issues as _; use radicle::issue::cache::Issues as _;
use radicle::node::device::Device; use radicle::node::device::Device;
use radicle::node::NodeId;
use radicle::prelude::{Did, RepoId}; use radicle::prelude::{Did, RepoId};
use radicle::profile; use radicle::profile;
use radicle::storage; use radicle::storage;
@ -815,7 +816,7 @@ fn open<R, G>(
profile: &Profile, profile: &Profile,
) -> anyhow::Result<()> ) -> anyhow::Result<()>
where where
R: ReadRepository + WriteRepository + cob::Store, R: ReadRepository + WriteRepository + cob::Store<Namespace = NodeId>,
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
{ {
let (title, description) = if let (Some(t), Some(d)) = (title.as_ref(), description.as_ref()) { let (title, description) = if let (Some(t), Some(d)) = (title.as_ref(), description.as_ref()) {
@ -849,7 +850,7 @@ fn edit<'a, 'g, R, G>(
signer: &Device<G>, signer: &Device<G>,
) -> anyhow::Result<issue::IssueMut<'a, 'g, R, cob::cache::StoreWriter>> ) -> anyhow::Result<issue::IssueMut<'a, 'g, R, cob::cache::StoreWriter>>
where where
R: WriteRepository + ReadRepository + cob::Store, R: WriteRepository + ReadRepository + cob::Store<Namespace = NodeId>,
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
{ {
let id = id.resolve(&repo.backend)?; let id = id.resolve(&repo.backend)?;
@ -891,7 +892,7 @@ where
} }
/// Get a comment from the user, by prompting. /// Get a comment from the user, by prompting.
pub fn prompt_comment<R: WriteRepository + radicle::cob::Store>( pub fn prompt_comment<R: WriteRepository + radicle::cob::Store<Namespace = NodeId>>(
message: Message, message: Message,
reply_to: Option<Rev>, reply_to: Option<Rev>,
issue: &issue::Issue, issue: &issue::Issue,

View File

@ -6,7 +6,7 @@ use anyhow::{anyhow, Context as _};
use radicle::cob::job::{JobStore, Reason, State}; use radicle::cob::job::{JobStore, Reason, State};
use radicle::crypto; use radicle::crypto;
use radicle::node::device::Device; use radicle::node::device::Device;
use radicle::node::Handle; use radicle::node::{Handle, NodeId};
use radicle::storage::{WriteRepository, WriteStorage}; use radicle::storage::{WriteRepository, WriteStorage};
use radicle::{cob, Node}; use radicle::{cob, Node};
@ -269,7 +269,7 @@ fn trigger<R, G>(
quiet: bool, quiet: bool,
) -> anyhow::Result<()> ) -> anyhow::Result<()>
where where
R: WriteRepository + cob::Store, R: WriteRepository + cob::Store<Namespace = NodeId>,
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
{ {
let commit = commit.resolve(&repo.backend)?; let commit = commit.resolve(&repo.backend)?;
@ -289,7 +289,7 @@ fn start<R, G>(
signer: &Device<G>, signer: &Device<G>,
) -> anyhow::Result<()> ) -> anyhow::Result<()>
where where
R: WriteRepository + cob::Store, R: WriteRepository + cob::Store<Namespace = NodeId>,
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
{ {
let job_id = job_id.resolve(&repo.backend)?; let job_id = job_id.resolve(&repo.backend)?;
@ -301,7 +301,9 @@ where
} }
// TODO: This should use the COB cache for performance. // TODO: This should use the COB cache for performance.
fn list<R: WriteRepository + cob::Store>(store: &JobStore<R>) -> anyhow::Result<()> { fn list<R: WriteRepository + cob::Store<Namespace = NodeId>>(
store: &JobStore<R>,
) -> anyhow::Result<()> {
if store.is_empty()? { if store.is_empty()? {
term::print(term::format::italic("Nothing to show.")); term::print(term::format::italic("Nothing to show."));
return Ok(()); return Ok(());
@ -343,7 +345,7 @@ fn list<R: WriteRepository + cob::Store>(store: &JobStore<R>) -> anyhow::Result<
Ok(()) Ok(())
} }
fn show<R: WriteRepository + cob::Store>( fn show<R: WriteRepository + cob::Store<Namespace = NodeId>>(
job_id: &Rev, job_id: &Rev,
store: &JobStore<R>, store: &JobStore<R>,
repo: &radicle::storage::git::Repository, repo: &radicle::storage::git::Repository,
@ -366,7 +368,7 @@ fn finish<R, G>(
signer: &Device<G>, signer: &Device<G>,
) -> anyhow::Result<()> ) -> anyhow::Result<()>
where where
R: WriteRepository + cob::Store, R: WriteRepository + cob::Store<Namespace = NodeId>,
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
{ {
let job_id = job_id.resolve(&repo.backend)?; let job_id = job_id.resolve(&repo.backend)?;

View File

@ -3,6 +3,7 @@ use radicle::{
self, self,
cache::{MigrateCallback, MigrateProgress}, cache::{MigrateCallback, MigrateProgress},
}, },
prelude::NodeId,
profile, profile,
storage::ReadRepository, storage::ReadRepository,
Profile, Profile,
@ -61,7 +62,7 @@ pub fn patches<'a, R>(
repository: &'a R, repository: &'a R,
) -> Result<cob::patch::Cache<cob::patch::Patches<'a, R>, cob::cache::StoreReader>, anyhow::Error> ) -> Result<cob::patch::Cache<cob::patch::Patches<'a, R>, cob::cache::StoreReader>, anyhow::Error>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
profile.patches(repository).map_err(with_hint) profile.patches(repository).map_err(with_hint)
} }
@ -72,7 +73,7 @@ pub fn patches_mut<'a, R>(
repository: &'a R, repository: &'a R,
) -> Result<cob::patch::Cache<cob::patch::Patches<'a, R>, cob::cache::StoreWriter>, anyhow::Error> ) -> Result<cob::patch::Cache<cob::patch::Patches<'a, R>, cob::cache::StoreWriter>, anyhow::Error>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
profile.patches_mut(repository).map_err(with_hint) profile.patches_mut(repository).map_err(with_hint)
} }
@ -83,7 +84,7 @@ pub fn issues<'a, R>(
repository: &'a R, repository: &'a R,
) -> Result<cob::issue::Cache<cob::issue::Issues<'a, R>, cob::cache::StoreReader>, anyhow::Error> ) -> Result<cob::issue::Cache<cob::issue::Issues<'a, R>, cob::cache::StoreReader>, anyhow::Error>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
profile.issues(repository).map_err(with_hint) profile.issues(repository).map_err(with_hint)
} }
@ -94,7 +95,7 @@ pub fn issues_mut<'a, R>(
repository: &'a R, repository: &'a R,
) -> Result<cob::issue::Cache<cob::issue::Issues<'a, R>, cob::cache::StoreWriter>, anyhow::Error> ) -> Result<cob::issue::Cache<cob::issue::Issues<'a, R>, cob::cache::StoreWriter>, anyhow::Error>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
profile.issues_mut(repository).map_err(with_hint) profile.issues_mut(repository).map_err(with_hint)
} }

View File

@ -55,4 +55,4 @@ qcheck-macros = { version = "1", default-features = false }
[dev-dependencies.radicle-crypto] [dev-dependencies.radicle-crypto]
path = "../radicle-crypto" path = "../radicle-crypto"
version = "0" version = "0"
features = ["test"] features = ["test", "radicle-git-ext"]

View File

@ -1,7 +1,6 @@
// Copyright © 2022 The Radicle Link Contributors // Copyright © 2022 The Radicle Link Contributors
use nonempty::NonEmpty; use nonempty::NonEmpty;
use radicle_crypto::PublicKey;
use crate::Embed; use crate::Embed;
use crate::Evaluate; use crate::Evaluate;
@ -58,7 +57,7 @@ pub fn create<T, S, G>(
signer: &G, signer: &G,
resource: Option<Oid>, resource: Option<Oid>,
related: Vec<Oid>, related: Vec<Oid>,
identifier: &PublicKey, identifier: &S::Namespace,
args: Create, args: Create,
) -> Result<CollaborativeObject<T>, error::Create> ) -> Result<CollaborativeObject<T>, error::Create>
where where

View File

@ -1,7 +1,5 @@
// Copyright © 2022 The Radicle Link Contributors // Copyright © 2022 The Radicle Link Contributors
use radicle_crypto::PublicKey;
use crate::{ObjectId, Store, TypeName}; use crate::{ObjectId, Store, TypeName};
use super::error; use super::error;
@ -17,7 +15,7 @@ use super::error;
/// type. /// type.
pub fn remove<S>( pub fn remove<S>(
storage: &S, storage: &S,
identifier: &PublicKey, identifier: &S::Namespace,
typename: &TypeName, typename: &TypeName,
oid: &ObjectId, oid: &ObjectId,
) -> Result<(), error::Remove> ) -> Result<(), error::Remove>

View File

@ -3,7 +3,6 @@ use std::iter;
use git_ext::Oid; use git_ext::Oid;
use nonempty::NonEmpty; use nonempty::NonEmpty;
use radicle_crypto::PublicKey;
use crate::{ use crate::{
change, change_graph::ChangeGraph, history::EntryId, CollaborativeObject, Embed, Evaluate, change, change_graph::ChangeGraph, history::EntryId, CollaborativeObject, Embed, Evaluate,
@ -61,7 +60,7 @@ pub fn update<T, S, G>(
signer: &G, signer: &G,
resource: Option<Oid>, resource: Option<Oid>,
related: Vec<Oid>, related: Vec<Oid>,
identifier: &PublicKey, identifier: &S::Namespace,
args: Update, args: Update,
) -> Result<Updated<T>, error::Update> ) -> Result<Updated<T>, error::Update>
where where

View File

@ -4,7 +4,6 @@ use std::{collections::BTreeMap, error::Error};
use git_ext::ref_format::RefString; use git_ext::ref_format::RefString;
use git_ext::Oid; use git_ext::Oid;
use radicle_crypto::PublicKey;
use crate::change::EntryId; use crate::change::EntryId;
use crate::{ObjectId, TypeName}; use crate::{ObjectId, TypeName};
@ -59,6 +58,8 @@ pub trait Storage {
type UpdateError: Error + Send + Sync + 'static; type UpdateError: Error + Send + Sync + 'static;
type RemoveError: Error + Send + Sync + 'static; type RemoveError: Error + Send + Sync + 'static;
type Namespace;
/// Get all references which point to a head of the change graph for a /// Get all references which point to a head of the change graph for a
/// particular object /// particular object
fn objects( fn objects(
@ -74,7 +75,7 @@ pub trait Storage {
/// Update a ref to a particular collaborative object /// Update a ref to a particular collaborative object
fn update( fn update(
&self, &self,
identifier: &PublicKey, namespace: &Self::Namespace,
typename: &TypeName, typename: &TypeName,
object_id: &ObjectId, object_id: &ObjectId,
entry: &EntryId, entry: &EntryId,
@ -83,7 +84,7 @@ pub trait Storage {
/// Remove a ref to a particular collaborative object /// Remove a ref to a particular collaborative object
fn remove( fn remove(
&self, &self,
identifier: &PublicKey, namespace: &Self::Namespace,
typename: &TypeName, typename: &TypeName,
object_id: &ObjectId, object_id: &ObjectId,
) -> Result<(), Self::RemoveError>; ) -> Result<(), Self::RemoveError>;

View File

@ -1,6 +1,6 @@
use std::{collections::BTreeMap, convert::TryFrom as _}; use std::{collections::BTreeMap, convert::TryFrom as _};
use radicle_crypto::PublicKey; use radicle_git_ext::ref_format::{refname, Component};
use tempfile::TempDir; use tempfile::TempDir;
use crate::{ use crate::{
@ -105,6 +105,8 @@ impl object::Storage for Storage {
type UpdateError = git2::Error; type UpdateError = git2::Error;
type RemoveError = git2::Error; type RemoveError = git2::Error;
type Namespace = crypto::PublicKey;
fn objects( fn objects(
&self, &self,
typename: &crate::TypeName, typename: &crate::TypeName,
@ -148,12 +150,16 @@ impl object::Storage for Storage {
fn update( fn update(
&self, &self,
identifier: &PublicKey, namespace: &Self::Namespace,
typename: &crate::TypeName, typename: &crate::TypeName,
object_id: &ObjectId, object_id: &ObjectId,
entry: &change::EntryId, entry: &change::EntryId,
) -> Result<(), Self::UpdateError> { ) -> Result<(), Self::UpdateError> {
let name = format!("refs/rad/{}/cobs/{}/{}", identifier, typename, object_id); let name = refname!("refs/rad")
.join(Component::from(namespace))
.join(refname!("cobs"))
.join::<Component>(typename.into())
.join::<Component>(object_id.into());
self.raw self.raw
.reference(&name, (*entry).into(), true, "new change")?; .reference(&name, (*entry).into(), true, "new change")?;
Ok(()) Ok(())
@ -161,11 +167,15 @@ impl object::Storage for Storage {
fn remove( fn remove(
&self, &self,
identifier: &PublicKey, namespace: &Self::Namespace,
typename: &crate::TypeName, typename: &crate::TypeName,
object_id: &ObjectId, object_id: &ObjectId,
) -> Result<(), Self::RemoveError> { ) -> Result<(), Self::RemoveError> {
let name = format!("refs/rad/{}/cobs/{}/{}", identifier, typename, object_id); let name = refname!("refs/rad")
.join(Component::from(namespace))
.join(refname!("cobs"))
.join::<Component>(typename.into())
.join::<Component>(object_id.into());
self.raw.find_reference(&name)?.delete()?; self.raw.find_reference(&name)?.delete()?;
Ok(()) Ok(())

View File

@ -8,6 +8,7 @@ use localtime::LocalTime;
use radicle::cob::TypedId; use radicle::cob::TypedId;
use radicle::crypto::PublicKey; use radicle::crypto::PublicKey;
use radicle::identity::DocAt; use radicle::identity::DocAt;
use radicle::prelude::NodeId;
use radicle::prelude::RepoId; use radicle::prelude::RepoId;
use radicle::storage::refs::RefsAt; use radicle::storage::refs::RefsAt;
use radicle::storage::{ use radicle::storage::{
@ -299,7 +300,7 @@ fn cache_cobs<S, C>(
cache: &mut C, cache: &mut C,
) -> Result<(), error::Cache> ) -> Result<(), error::Cache>
where where
S: ReadRepository + cob::Store, S: ReadRepository + cob::Store<Namespace = NodeId>,
C: cob::cache::Update<cob::issue::Issue> + cob::cache::Update<cob::patch::Patch>, C: cob::cache::Update<cob::issue::Issue> + cob::cache::Update<cob::patch::Patch>,
C: cob::cache::Remove<cob::issue::Issue> + cob::cache::Remove<cob::patch::Patch>, C: cob::cache::Remove<cob::issue::Issue> + cob::cache::Remove<cob::patch::Patch>,
{ {

View File

@ -13,6 +13,7 @@ use std::{env, fmt, io};
use thiserror::Error; use thiserror::Error;
use radicle::prelude::NodeId;
use radicle::storage::git::transport::local::{Url, UrlError}; use radicle::storage::git::transport::local::{Url, UrlError};
use radicle::storage::{ReadRepository, WriteStorage}; use radicle::storage::{ReadRepository, WriteStorage};
use radicle::{cob, profile}; use radicle::{cob, profile};
@ -262,7 +263,7 @@ pub(crate) fn warn(s: impl fmt::Display) {
} }
/// Get the patch store. /// Get the patch store.
pub(crate) fn patches<'a, R: ReadRepository + cob::Store>( pub(crate) fn patches<'a, R: ReadRepository + cob::Store<Namespace = NodeId>>(
profile: &Profile, profile: &Profile,
repo: &'a R, repo: &'a R,
) -> Result<cob::patch::Cache<cob::patch::Patches<'a, R>, cob::cache::StoreReader>, list::Error> { ) -> Result<cob::patch::Cache<cob::patch::Patches<'a, R>, cob::cache::StoreReader>, list::Error> {

View File

@ -4,6 +4,7 @@ use thiserror::Error;
use radicle::cob; use radicle::cob;
use radicle::git; use radicle::git;
use radicle::prelude::NodeId;
use radicle::storage::git::transport::local::Url; use radicle::storage::git::transport::local::Url;
use radicle::storage::ReadRepository; use radicle::storage::ReadRepository;
use radicle::Profile; use radicle::Profile;
@ -34,7 +35,7 @@ pub enum Error {
} }
/// List refs for fetching (`git fetch` and `git ls-remote`). /// List refs for fetching (`git fetch` and `git ls-remote`).
pub fn for_fetch<R: ReadRepository + cob::Store + 'static>( pub fn for_fetch<R: ReadRepository + cob::Store<Namespace = NodeId> + 'static>(
url: &Url, url: &Url,
profile: &Profile, profile: &Profile,
stored: &R, stored: &R,
@ -83,7 +84,7 @@ pub fn for_push<R: ReadRepository>(profile: &Profile, stored: &R) -> Result<(),
} }
/// List canonical patch references. These are magic refs that can be used to pull patch updates. /// List canonical patch references. These are magic refs that can be used to pull patch updates.
fn patch_refs<R: ReadRepository + cob::Store + 'static>( fn patch_refs<R: ReadRepository + cob::Store<Namespace = NodeId> + 'static>(
profile: &Profile, profile: &Profile,
stored: &R, stored: &R,
) -> Result<(), Error> { ) -> Result<(), Error> {

View File

@ -11,6 +11,7 @@ use thiserror::Error;
use crate::identity::doc::Doc; use crate::identity::doc::Doc;
use crate::node::device::Device; use crate::node::device::Device;
use crate::node::NodeId;
use crate::{ use crate::{
cob, cob,
cob::{ cob::{
@ -192,13 +193,14 @@ impl Identity {
} }
} }
pub fn initialize<'a, R: WriteRepository + cob::Store, G>( pub fn initialize<'a, R, G>(
doc: &Doc, doc: &Doc,
store: &'a R, store: &'a R,
signer: &Device<G>, signer: &Device<G>,
) -> Result<IdentityMut<'a, R>, cob::store::Error> ) -> Result<IdentityMut<'a, R>, cob::store::Error>
where where
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
R: WriteRepository + cob::Store<Namespace = NodeId>,
{ {
let mut store = cob::store::Store::open(store)?; let mut store = cob::store::Store::open(store)?;
let (id, identity) = Transaction::<Identity, _>::initial( let (id, identity) = Transaction::<Identity, _>::initial(
@ -227,7 +229,7 @@ impl Identity {
} }
/// Get a proposal mutably. /// Get a proposal mutably.
pub fn get_mut<'a, R: WriteRepository + cob::Store>( pub fn get_mut<'a, R: WriteRepository + cob::Store<Namespace = NodeId>>(
id: &ObjectId, id: &ObjectId,
repo: &'a R, repo: &'a R,
) -> Result<IdentityMut<'a, R>, store::Error> { ) -> Result<IdentityMut<'a, R>, store::Error> {
@ -248,7 +250,7 @@ impl Identity {
Self::get(&oid, repo).map_err(RepositoryError::from) Self::get(&oid, repo).map_err(RepositoryError::from)
} }
pub fn load_mut<R: WriteRepository + cob::Store>( pub fn load_mut<R: WriteRepository + cob::Store<Namespace = NodeId>>(
repo: &R, repo: &R,
) -> Result<IdentityMut<R>, RepositoryError> { ) -> Result<IdentityMut<R>, RepositoryError> {
let oid = repo.identity_root()?; let oid = repo.identity_root()?;
@ -892,7 +894,7 @@ impl<R> fmt::Debug for IdentityMut<'_, R> {
impl<R> IdentityMut<'_, R> impl<R> IdentityMut<'_, R>
where where
R: WriteRepository + cob::Store, R: WriteRepository + cob::Store<Namespace = NodeId>,
{ {
/// Reload the identity data from storage. /// Reload the identity data from storage.
pub fn reload(&mut self) -> Result<(), store::Error> { pub fn reload(&mut self) -> Result<(), store::Error> {

View File

@ -17,6 +17,7 @@ use crate::cob::thread::{Comment, CommentId, Thread};
use crate::cob::{op, store, ActorId, Embed, EntryId, ObjectId, TypeName}; use crate::cob::{op, store, ActorId, Embed, EntryId, ObjectId, TypeName};
use crate::identity::doc::DocError; use crate::identity::doc::DocError;
use crate::node::device::Device; use crate::node::device::Device;
use crate::node::NodeId;
use crate::prelude::{Did, Doc, ReadRepository, RepoId}; use crate::prelude::{Did, Doc, ReadRepository, RepoId};
use crate::storage::{HasRepoId, RepositoryError, WriteRepository}; use crate::storage::{HasRepoId, RepositoryError, WriteRepository};
@ -589,7 +590,7 @@ impl<R, C> std::fmt::Debug for IssueMut<'_, '_, R, C> {
impl<R, C> IssueMut<'_, '_, R, C> impl<R, C> IssueMut<'_, '_, R, C>
where where
R: WriteRepository + cob::Store, R: WriteRepository + cob::Store<Namespace = NodeId>,
C: cob::cache::Update<Issue>, C: cob::cache::Update<Issue>,
{ {
/// Reload the issue data from storage. /// Reload the issue data from storage.
@ -792,7 +793,7 @@ impl IssueCounts {
impl<'a, R> Issues<'a, R> impl<'a, R> Issues<'a, R>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
/// Open an issues store. /// Open an issues store.
pub fn open(repository: &'a R) -> Result<Self, RepositoryError> { pub fn open(repository: &'a R) -> Result<Self, RepositoryError> {
@ -805,7 +806,7 @@ where
impl<'a, R> Issues<'a, R> impl<'a, R> Issues<'a, R>
where where
R: WriteRepository + cob::Store, R: WriteRepository + cob::Store<Namespace = NodeId>,
{ {
/// Create a new issue. /// Create a new issue.
pub fn create<'g, G, C>( pub fn create<'g, G, C>(

View File

@ -10,6 +10,7 @@ use crate::cob::cache::{Remove, StoreReader, StoreWriter, Update};
use crate::cob::store; use crate::cob::store;
use crate::cob::{Embed, Label, ObjectId, TypeName, Uri}; use crate::cob::{Embed, Label, ObjectId, TypeName, Uri};
use crate::node::device::Device; use crate::node::device::Device;
use crate::node::NodeId;
use crate::prelude::{Did, RepoId}; use crate::prelude::{Did, RepoId};
use crate::storage::{HasRepoId, ReadRepository, RepositoryError, SignRepository, WriteRepository}; use crate::storage::{HasRepoId, ReadRepository, RepositoryError, SignRepository, WriteRepository};
@ -107,7 +108,7 @@ impl<'a, R, C> Cache<super::Issues<'a, R>, C> {
signer: &Device<G>, signer: &Device<G>,
) -> Result<IssueMut<'a, 'g, R, C>, super::Error> ) -> Result<IssueMut<'a, 'g, R, C>, super::Error>
where where
R: ReadRepository + WriteRepository + cob::Store, R: ReadRepository + WriteRepository + cob::Store<Namespace = NodeId>,
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
C: Update<Issue>, C: Update<Issue>,
{ {
@ -127,7 +128,7 @@ impl<'a, R, C> Cache<super::Issues<'a, R>, C> {
pub fn remove<G>(&mut self, id: &IssueId, signer: &Device<G>) -> Result<(), super::Error> pub fn remove<G>(&mut self, id: &IssueId, signer: &Device<G>) -> Result<(), super::Error>
where where
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
R: ReadRepository + SignRepository + cob::Store, R: ReadRepository + SignRepository + cob::Store<Namespace = NodeId>,
C: Remove<Issue>, C: Remove<Issue>,
{ {
self.store.remove(id, signer)?; self.store.remove(id, signer)?;
@ -199,7 +200,7 @@ impl<'a, R, C> Cache<super::Issues<'a, R>, C> {
impl<'a, R> Cache<super::Issues<'a, R>, cache::NoCache> impl<'a, R> Cache<super::Issues<'a, R>, cache::NoCache>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
/// Get a `Cache` that does no write-through modifications and /// Get a `Cache` that does no write-through modifications and
/// uses the [`super::Issues`] store for all reads and writes. /// uses the [`super::Issues`] store for all reads and writes.

View File

@ -21,6 +21,7 @@ use crate::cob::{EntryId, ObjectId, TypeName};
use crate::crypto::ssh::ExtendedSignature; use crate::crypto::ssh::ExtendedSignature;
use crate::git; use crate::git;
use crate::node::device::Device; use crate::node::device::Device;
use crate::node::NodeId;
use crate::prelude::ReadRepository; use crate::prelude::ReadRepository;
use crate::storage::{Oid, WriteRepository}; use crate::storage::{Oid, WriteRepository};
@ -315,7 +316,7 @@ impl<R> std::fmt::Debug for JobMut<'_, '_, R> {
impl<R> JobMut<'_, '_, R> impl<R> JobMut<'_, '_, R>
where where
R: WriteRepository + cob::Store, R: WriteRepository + cob::Store<Namespace = NodeId>,
{ {
/// Reload the COB from storage. /// Reload the COB from storage.
pub fn reload(&mut self) -> Result<(), store::Error> { pub fn reload(&mut self) -> Result<(), store::Error> {
@ -397,7 +398,7 @@ impl<'a, R> Deref for JobStore<'a, R> {
impl<'a, R> JobStore<'a, R> impl<'a, R> JobStore<'a, R>
where where
R: WriteRepository + ReadRepository + cob::Store, R: WriteRepository + ReadRepository + cob::Store<Namespace = NodeId>,
{ {
pub fn open(repository: &'a R) -> Result<Self, store::Error> { pub fn open(repository: &'a R) -> Result<Self, store::Error> {
let raw = store::Store::open(repository)?; let raw = store::Store::open(repository)?;

View File

@ -1976,7 +1976,7 @@ pub struct PatchMut<'a, 'g, R, C> {
impl<'a, 'g, R, C> PatchMut<'a, 'g, R, C> impl<'a, 'g, R, C> PatchMut<'a, 'g, R, C>
where where
C: cob::cache::Update<Patch>, C: cob::cache::Update<Patch>,
R: ReadRepository + SignRepository + cob::Store, R: ReadRepository + SignRepository + cob::Store<Namespace = NodeId>,
{ {
pub fn new(id: ObjectId, patch: Patch, cache: &'g mut Cache<Patches<'a, R>, C>) -> Self { pub fn new(id: ObjectId, patch: Patch, cache: &'g mut Cache<Patches<'a, R>, C>) -> Self {
Self { Self {
@ -2507,7 +2507,7 @@ where
impl<'a, R> Patches<'a, R> impl<'a, R> Patches<'a, R>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
/// Open a patches store. /// Open a patches store.
pub fn open(repository: &'a R) -> Result<Self, RepositoryError> { pub fn open(repository: &'a R) -> Result<Self, RepositoryError> {
@ -2590,7 +2590,7 @@ where
impl<'a, R> Patches<'a, R> impl<'a, R> Patches<'a, R>
where where
R: ReadRepository + SignRepository + cob::Store, R: ReadRepository + SignRepository + cob::Store<Namespace = NodeId>,
{ {
/// Open a new patch. /// Open a new patch.
pub fn create<'g, C, G>( pub fn create<'g, C, G>(

View File

@ -15,8 +15,8 @@ use crate::prelude::RepoId;
use crate::storage::{HasRepoId, ReadRepository, RepositoryError, SignRepository, WriteRepository}; use crate::storage::{HasRepoId, ReadRepository, RepositoryError, SignRepository, WriteRepository};
use super::{ use super::{
ByRevision, MergeTarget, Patch, PatchCounts, PatchId, PatchMut, Revision, RevisionId, State, ByRevision, MergeTarget, NodeId, Patch, PatchCounts, PatchId, PatchMut, Revision, RevisionId,
Status, State, Status,
}; };
/// A set of read-only methods for a [`Patch`] store. /// A set of read-only methods for a [`Patch`] store.
@ -119,7 +119,7 @@ impl<'a, R, C> Cache<super::Patches<'a, R>, C> {
signer: &Device<G>, signer: &Device<G>,
) -> Result<PatchMut<'a, 'g, R, C>, super::Error> ) -> Result<PatchMut<'a, 'g, R, C>, super::Error>
where where
R: WriteRepository + cob::Store, R: WriteRepository + cob::Store<Namespace = NodeId>,
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
C: Update<Patch>, C: Update<Patch>,
{ {
@ -149,7 +149,7 @@ impl<'a, R, C> Cache<super::Patches<'a, R>, C> {
signer: &Device<G>, signer: &Device<G>,
) -> Result<PatchMut<'a, 'g, R, C>, super::Error> ) -> Result<PatchMut<'a, 'g, R, C>, super::Error>
where where
R: WriteRepository + cob::Store, R: WriteRepository + cob::Store<Namespace = NodeId>,
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
C: Update<Patch>, C: Update<Patch>,
{ {
@ -170,7 +170,7 @@ impl<'a, R, C> Cache<super::Patches<'a, R>, C> {
pub fn remove<G>(&mut self, id: &PatchId, signer: &Device<G>) -> Result<(), super::Error> pub fn remove<G>(&mut self, id: &PatchId, signer: &Device<G>) -> Result<(), super::Error>
where where
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
R: ReadRepository + SignRepository + cob::Store, R: ReadRepository + SignRepository + cob::Store<Namespace = NodeId>,
C: Remove<Patch>, C: Remove<Patch>,
{ {
self.store.remove(id, signer)?; self.store.remove(id, signer)?;
@ -276,7 +276,7 @@ where
impl<'a, R> Cache<super::Patches<'a, R>, cache::NoCache> impl<'a, R> Cache<super::Patches<'a, R>, cache::NoCache>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
/// Get a `Cache` that does no write-through modifications and /// Get a `Cache` that does no write-through modifications and
/// uses the [`super::Patches`] store for all reads and writes. /// uses the [`super::Patches`] store for all reads and writes.
@ -488,7 +488,7 @@ impl Iterator for NoCacheIter<'_> {
impl<R> Patches for Cache<super::Patches<'_, R>, cache::NoCache> impl<R> Patches for Cache<super::Patches<'_, R>, cache::NoCache>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
type Error = super::Error; type Error = super::Error;
type Iter<'b> type Iter<'b>

View File

@ -174,7 +174,7 @@ where
impl<'a, T, R> Store<'a, T, R> impl<'a, T, R> Store<'a, T, R>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
T: CobWithType, T: CobWithType,
{ {
/// Open a new generic store. /// Open a new generic store.
@ -190,7 +190,7 @@ where
impl<T, R> Store<'_, T, R> impl<T, R> Store<'_, T, R>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
T: Cob + cob::Evaluate<R>, T: Cob + cob::Evaluate<R>,
{ {
pub fn transaction( pub fn transaction(
@ -204,7 +204,7 @@ where
impl<T, R> Store<'_, T, R> impl<T, R> Store<'_, T, R>
where where
R: ReadRepository + SignRepository + cob::Store, R: ReadRepository + SignRepository + cob::Store<Namespace = NodeId>,
T: Cob + cob::Evaluate<R>, T: Cob + cob::Evaluate<R>,
T::Action: Serialize, T::Action: Serialize,
{ {
@ -423,7 +423,7 @@ where
Self: From<Tx>, Self: From<Tx>,
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
F: FnOnce(&mut Tx, &R) -> Result<(), Error>, F: FnOnce(&mut Tx, &R) -> Result<(), Error>,
R: ReadRepository + SignRepository + cob::Store, R: ReadRepository + SignRepository + cob::Store<Namespace = NodeId>,
T::Action: Serialize + Clone, T::Action: Serialize + Clone,
{ {
let mut tx = Tx::from(Transaction::default()); let mut tx = Tx::from(Transaction::default());
@ -487,7 +487,7 @@ where
signer: &Device<G>, signer: &Device<G>,
) -> Result<(T, EntryId), Error> ) -> Result<(T, EntryId), Error>
where where
R: ReadRepository + SignRepository + cob::Store, R: ReadRepository + SignRepository + cob::Store<Namespace = NodeId>,
T::Action: Serialize + Clone, T::Action: Serialize + Clone,
G: crypto::signature::Signer<crypto::Signature>, G: crypto::signature::Signer<crypto::Signature>,
{ {

View File

@ -605,7 +605,7 @@ impl Home {
repository: &'a R, repository: &'a R,
) -> Result<cob::issue::Cache<cob::issue::Issues<'a, R>, cob::cache::StoreReader>, Error> ) -> Result<cob::issue::Cache<cob::issue::Issues<'a, R>, cob::cache::StoreReader>, Error>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
let db = self.cobs_db()?; let db = self.cobs_db()?;
let store = cob::issue::Issues::open(repository)?; let store = cob::issue::Issues::open(repository)?;
@ -621,7 +621,7 @@ impl Home {
repository: &'a R, repository: &'a R,
) -> Result<cob::issue::Cache<cob::issue::Issues<'a, R>, cob::cache::StoreWriter>, Error> ) -> Result<cob::issue::Cache<cob::issue::Issues<'a, R>, cob::cache::StoreWriter>, Error>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
let db = self.cobs_db_mut()?; let db = self.cobs_db_mut()?;
let store = cob::issue::Issues::open(repository)?; let store = cob::issue::Issues::open(repository)?;
@ -637,7 +637,7 @@ impl Home {
repository: &'a R, repository: &'a R,
) -> Result<cob::patch::Cache<cob::patch::Patches<'a, R>, cob::cache::StoreReader>, Error> ) -> Result<cob::patch::Cache<cob::patch::Patches<'a, R>, cob::cache::StoreReader>, Error>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
let db = self.cobs_db()?; let db = self.cobs_db()?;
let store = cob::patch::Patches::open(repository)?; let store = cob::patch::Patches::open(repository)?;
@ -653,7 +653,7 @@ impl Home {
repository: &'a R, repository: &'a R,
) -> Result<cob::patch::Cache<cob::patch::Patches<'a, R>, cob::cache::StoreWriter>, Error> ) -> Result<cob::patch::Cache<cob::patch::Patches<'a, R>, cob::cache::StoreWriter>, Error>
where where
R: ReadRepository + cob::Store, R: ReadRepository + cob::Store<Namespace = NodeId>,
{ {
let db = self.cobs_db_mut()?; let db = self.cobs_db_mut()?;
let store = cob::patch::Patches::open(repository)?; let store = cob::patch::Patches::open(repository)?;

View File

@ -11,20 +11,18 @@ use storage::RepositoryError;
use storage::SignRepository; use storage::SignRepository;
use storage::ValidateRepository; use storage::ValidateRepository;
use crate::git;
use crate::git::*; use crate::git::*;
use crate::identity; use crate::identity;
use crate::identity::doc::DocError; use crate::identity::doc::DocError;
use crate::node::device::Device; use crate::node::device::Device;
use crate::node::NodeId;
use crate::storage; use crate::storage;
use crate::storage::Error; use crate::storage::Error;
use crate::storage::{ use crate::storage::{
git::{Remote, Remotes, Validations}, git::{Remote, Remotes, Validations},
ReadRepository, Verified, ReadRepository, Verified,
}; };
use crate::{
git, identity,
identity::{doc::DocError, PublicKey},
};
use super::{RemoteId, Repository}; use super::{RemoteId, Repository};
@ -92,6 +90,8 @@ impl cob::object::Storage for Repository {
type UpdateError = git2::Error; type UpdateError = git2::Error;
type RemoveError = git2::Error; type RemoveError = git2::Error;
type Namespace = NodeId;
fn objects( fn objects(
&self, &self,
typename: &cob::TypeName, typename: &cob::TypeName,
@ -146,13 +146,13 @@ impl cob::object::Storage for Repository {
fn update( fn update(
&self, &self,
identifier: &PublicKey, namespace: &Self::Namespace,
typename: &cob::TypeName, typename: &cob::TypeName,
object_id: &cob::ObjectId, object_id: &cob::ObjectId,
entry: &cob::EntryId, entry: &cob::EntryId,
) -> Result<(), Self::UpdateError> { ) -> Result<(), Self::UpdateError> {
self.backend.reference( self.backend.reference(
git::refs::storage::cob(identifier, typename, object_id).as_str(), git::refs::storage::cob(namespace, typename, object_id).as_str(),
(*entry).into(), (*entry).into(),
true, true,
&format!( &format!(
@ -166,13 +166,13 @@ impl cob::object::Storage for Repository {
fn remove( fn remove(
&self, &self,
identifier: &PublicKey, namespace: &Self::Namespace,
typename: &cob::TypeName, typename: &cob::TypeName,
object_id: &cob::ObjectId, object_id: &cob::ObjectId,
) -> Result<(), Self::RemoveError> { ) -> Result<(), Self::RemoveError> {
let mut reference = self let mut reference = self
.backend .backend
.find_reference(git::refs::storage::cob(identifier, typename, object_id).as_str())?; .find_reference(git::refs::storage::cob(namespace, typename, object_id).as_str())?;
reference.delete() reference.delete()
} }
@ -377,6 +377,8 @@ impl<R: storage::WriteRepository> cob::object::Storage for DraftStore<'_, R> {
type UpdateError = git2::Error; type UpdateError = git2::Error;
type RemoveError = git2::Error; type RemoveError = git2::Error;
type Namespace = NodeId;
fn objects( fn objects(
&self, &self,
typename: &cob::TypeName, typename: &cob::TypeName,
@ -421,13 +423,13 @@ impl<R: storage::WriteRepository> cob::object::Storage for DraftStore<'_, R> {
fn update( fn update(
&self, &self,
identifier: &PublicKey, namespace: &Self::Namespace,
typename: &cob::TypeName, typename: &cob::TypeName,
object_id: &cob::ObjectId, object_id: &cob::ObjectId,
entry: &cob::history::EntryId, entry: &cob::history::EntryId,
) -> Result<(), Self::UpdateError> { ) -> Result<(), Self::UpdateError> {
self.repo.raw().reference( self.repo.raw().reference(
git::refs::storage::draft::cob(identifier, typename, object_id).as_str(), git::refs::storage::draft::cob(namespace, typename, object_id).as_str(),
(*entry).into(), (*entry).into(),
true, true,
&format!( &format!(
@ -441,12 +443,12 @@ impl<R: storage::WriteRepository> cob::object::Storage for DraftStore<'_, R> {
fn remove( fn remove(
&self, &self,
identifier: &PublicKey, namespace: &Self::Namespace,
typename: &cob::TypeName, typename: &cob::TypeName,
object_id: &cob::ObjectId, object_id: &cob::ObjectId,
) -> Result<(), Self::RemoveError> { ) -> Result<(), Self::RemoveError> {
let mut reference = self.repo.raw().find_reference( let mut reference = self.repo.raw().find_reference(
git::refs::storage::draft::cob(identifier, typename, object_id).as_str(), git::refs::storage::draft::cob(namespace, typename, object_id).as_str(),
)?; )?;
reference.delete() reference.delete()

View File

@ -364,6 +364,8 @@ impl radicle_cob::object::Storage for MockRepository {
type UpdateError = Infallible; type UpdateError = Infallible;
type RemoveError = Infallible; type RemoveError = Infallible;
type Namespace = crypto::PublicKey;
fn objects( fn objects(
&self, &self,
_typename: &radicle_cob::TypeName, _typename: &radicle_cob::TypeName,
@ -384,7 +386,7 @@ impl radicle_cob::object::Storage for MockRepository {
fn update( fn update(
&self, &self,
_identifier: &radicle_crypto::PublicKey, _namespace: &Self::Namespace,
_typename: &radicle_cob::TypeName, _typename: &radicle_cob::TypeName,
_object_id: &radicle_cob::ObjectId, _object_id: &radicle_cob::ObjectId,
_entry: &radicle_cob::EntryId, _entry: &radicle_cob::EntryId,
@ -394,7 +396,7 @@ impl radicle_cob::object::Storage for MockRepository {
fn remove( fn remove(
&self, &self,
_identifier: &radicle_crypto::PublicKey, _namespace: &Self::Namespace,
_typename: &radicle_cob::TypeName, _typename: &radicle_cob::TypeName,
_object_id: &radicle_cob::ObjectId, _object_id: &radicle_cob::ObjectId,
) -> Result<(), Self::RemoveError> { ) -> Result<(), Self::RemoveError> {