use std::collections::HashMap; use std::io; use std::path::{Path, PathBuf}; use std::str::FromStr; use git_ext::ref_format as fmt; use crate::crypto::{Signer, Verified}; use crate::identity::doc::{Doc, DocError, Id}; use crate::identity::IdentityError; use crate::node::NodeId; pub use crate::storage::*; #[derive(Clone, Debug)] pub struct MockStorage { pub path: PathBuf, pub inventory: HashMap>, /// All refs keyed by RID. /// Each value is a map of refs keyed by node Id (public key). pub remotes: HashMap>>, } impl MockStorage { pub fn new(inventory: Vec<(Id, Doc)>) -> Self { Self { path: PathBuf::default(), inventory: inventory.into_iter().collect(), remotes: HashMap::new(), } } pub fn empty() -> Self { Self { path: PathBuf::default(), inventory: HashMap::new(), remotes: HashMap::new(), } } /// Add a remote `node` with `signed_refs` for the repo `rid`. pub fn insert_remote( &mut self, rid: Id, node: NodeId, signed_refs: refs::SignedRefs, ) { self.remotes .entry(rid) .or_insert(HashMap::new()) .insert(node, signed_refs); } } impl ReadStorage for MockStorage { type Repository = MockRepository; fn path(&self) -> &Path { self.path.as_path() } fn path_of(&self, rid: &Id) -> PathBuf { self.path().join(rid.canonical()) } fn contains(&self, rid: &Id) -> Result { Ok(self.inventory.contains_key(rid)) } fn get(&self, _remote: &RemoteId, proj: Id) -> Result>, IdentityError> { Ok(self.inventory.get(&proj).cloned()) } fn inventory(&self) -> Result { Ok(self.inventory.keys().cloned().collect::>()) } fn repository(&self, rid: Id) -> Result { let doc = self .inventory .get(&rid) .ok_or_else(|| Error::Io(io::Error::from(io::ErrorKind::NotFound)))?; Ok(MockRepository { id: rid, doc: doc.clone(), remotes: self.remotes.get(&rid).cloned().unwrap_or_default(), }) } } impl WriteStorage for MockStorage { type RepositoryMut = MockRepository; fn repository_mut(&self, rid: Id) -> Result { let doc = self.inventory.get(&rid).unwrap(); Ok(MockRepository { id: rid, doc: doc.clone(), remotes: self.remotes.get(&rid).cloned().unwrap_or_default(), }) } fn create(&self, _rid: Id) -> Result { todo!() } } #[derive(Clone, Debug)] pub struct MockRepository { id: Id, doc: Doc, remotes: HashMap>, } impl MockRepository { pub fn new(id: Id, doc: Doc) -> Self { Self { id, doc, remotes: HashMap::default(), } } } impl ReadRepository for MockRepository { fn id(&self) -> Id { self.id } fn is_empty(&self) -> Result { Ok(self.remotes.is_empty()) } fn head(&self) -> Result<(fmt::Qualified, Oid), IdentityError> { todo!() } fn canonical_head(&self) -> Result<(fmt::Qualified, Oid), IdentityError> { todo!() } fn validate_remote( &self, _remote: &Remote, ) -> Result, VerifyError> { Ok(vec![]) } fn path(&self) -> &std::path::Path { todo!() } fn remote(&self, id: &RemoteId) -> Result, refs::Error> { self.remotes .get(id) .map(|refs| Remote { refs: refs.clone() }) .ok_or(refs::Error::InvalidRef) } fn remotes(&self) -> Result, refs::Error> { Ok(self .remotes .iter() .map(|(id, refs)| (*id, Remote { refs: refs.clone() })) .collect()) } fn commit(&self, _oid: Oid) -> Result { todo!() } fn revwalk(&self, _head: Oid) -> Result { todo!() } fn is_ancestor_of(&self, _ancestor: Oid, _head: Oid) -> Result { Ok(true) } fn blob_at<'a>( &'a self, _oid: git_ext::Oid, _path: &'a std::path::Path, ) -> Result, git_ext::Error> { todo!() } fn reference( &self, _remote: &RemoteId, _reference: &git::Qualified, ) -> Result { todo!() } fn reference_oid( &self, _remote: &RemoteId, _reference: &git::Qualified, ) -> Result { Ok(Oid::from_str("ffffffffffffffffffffffffffffffffffffffff").unwrap()) } fn references_of(&self, _remote: &RemoteId) -> Result { todo!() } fn references_glob( &self, _pattern: &git::PatternStr, ) -> Result, git::ext::Error> { todo!() } fn identity_doc( &self, ) -> Result<(Oid, crate::identity::Doc), IdentityError> { Ok((git2::Oid::zero().into(), self.doc.clone().unverified())) } fn identity_doc_at( &self, _head: Oid, ) -> Result, DocError> { Ok(self.doc.clone().unverified()) } fn identity_head(&self) -> Result { self.canonical_identity_head() } fn canonical_identity_head(&self) -> Result { Ok(Oid::from_str("cccccccccccccccccccccccccccccccccccccccc").unwrap()) } fn merge_base(&self, _left: &Oid, _right: &Oid) -> Result { todo!() } } impl WriteRepository for MockRepository { fn raw(&self) -> &git2::Repository { todo!() } fn set_head(&self) -> Result { todo!() } fn sign_refs( &self, _signer: &G, ) -> Result, Error> { todo!() } fn set_identity_head(&self) -> Result { todo!() } }