Remove `Project` type
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
parent
c2b599f068
commit
e382bc4eb9
|
|
@ -21,9 +21,10 @@ use crate::address_manager::AddressManager;
|
||||||
use crate::clock::RefClock;
|
use crate::clock::RefClock;
|
||||||
use crate::collections::{HashMap, HashSet};
|
use crate::collections::{HashMap, HashSet};
|
||||||
use crate::crypto;
|
use crate::crypto;
|
||||||
|
use crate::crypto::Verified;
|
||||||
use crate::git;
|
use crate::git;
|
||||||
use crate::git::Url;
|
use crate::git::Url;
|
||||||
use crate::identity::{Id, Project};
|
use crate::identity::{Doc, Id};
|
||||||
use crate::service::config::ProjectTracking;
|
use crate::service::config::ProjectTracking;
|
||||||
use crate::service::message::{NodeAnnouncement, RefsAnnouncement};
|
use crate::service::message::{NodeAnnouncement, RefsAnnouncement};
|
||||||
use crate::service::peer::{Peer, PeerError, PeerState};
|
use crate::service::peer::{Peer, PeerError, PeerState};
|
||||||
|
|
@ -255,7 +256,7 @@ impl<'r, T: WriteStorage<'r>, S: address_book::Store, G: crypto::Signer> Service
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a project from storage, using the local node's key.
|
/// Get a project from storage, using the local node's key.
|
||||||
pub fn get(&self, proj: &Id) -> Result<Option<Project>, storage::Error> {
|
pub fn get(&self, proj: &Id) -> Result<Option<Doc<Verified>>, storage::Error> {
|
||||||
self.storage.get(&self.node_id(), proj)
|
self.storage.get(&self.node_id(), proj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -645,7 +646,7 @@ impl<S, T, G> Iterator for Service<S, T, G> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Lookup {
|
pub struct Lookup {
|
||||||
/// Whether the project was found locally or not.
|
/// Whether the project was found locally or not.
|
||||||
pub local: Option<Project>,
|
pub local: Option<Doc<Verified>>,
|
||||||
/// A list of remote peers on which the project is known to exist.
|
/// A list of remote peers on which the project is known to exist.
|
||||||
pub remote: Vec<NodeId>,
|
pub remote: Vec<NodeId>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use log::*;
|
||||||
use crate::address_book::{KnownAddress, Source};
|
use crate::address_book::{KnownAddress, Source};
|
||||||
use crate::clock::RefClock;
|
use crate::clock::RefClock;
|
||||||
use crate::collections::HashMap;
|
use crate::collections::HashMap;
|
||||||
|
use crate::git;
|
||||||
use crate::git::Url;
|
use crate::git::Url;
|
||||||
use crate::service;
|
use crate::service;
|
||||||
use crate::service::config::*;
|
use crate::service::config::*;
|
||||||
|
|
@ -63,10 +64,17 @@ where
|
||||||
S: WriteStorage<'r> + 'static,
|
S: WriteStorage<'r> + 'static,
|
||||||
{
|
{
|
||||||
pub fn new(name: &'static str, ip: impl Into<net::IpAddr>, storage: S) -> Self {
|
pub fn new(name: &'static str, ip: impl Into<net::IpAddr>, storage: S) -> Self {
|
||||||
|
let git_url = Url {
|
||||||
|
scheme: git::url::Scheme::File,
|
||||||
|
path: storage.path().to_string_lossy().to_string().into(),
|
||||||
|
|
||||||
|
..git::Url::default()
|
||||||
|
};
|
||||||
|
|
||||||
Self::config(
|
Self::config(
|
||||||
name,
|
name,
|
||||||
Config {
|
Config {
|
||||||
git_url: storage.url(),
|
git_url,
|
||||||
..Config::default()
|
..Config::default()
|
||||||
},
|
},
|
||||||
ip,
|
ip,
|
||||||
|
|
|
||||||
|
|
@ -473,9 +473,9 @@ fn prop_inventory_exchange_dense() {
|
||||||
(bob_inv.inventory, bob.node_id()),
|
(bob_inv.inventory, bob.node_id()),
|
||||||
(eve_inv.inventory, eve.node_id()),
|
(eve_inv.inventory, eve.node_id()),
|
||||||
] {
|
] {
|
||||||
for proj in inv {
|
for id in inv.keys() {
|
||||||
routing
|
routing
|
||||||
.entry(proj.id.clone())
|
.entry(id.clone())
|
||||||
.or_insert_with(|| HashSet::with_hasher(rng.clone().into()))
|
.or_insert_with(|| HashSet::with_hasher(rng.clone().into()))
|
||||||
.insert(*peer);
|
.insert(*peer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,17 +187,11 @@ pub fn configure_remote<'r>(
|
||||||
repo: &'r git2::Repository,
|
repo: &'r git2::Repository,
|
||||||
remote_name: &str,
|
remote_name: &str,
|
||||||
remote_id: &RemoteId,
|
remote_id: &RemoteId,
|
||||||
remote_path: &Path,
|
remote_url: &Url,
|
||||||
) -> Result<git2::Remote<'r>, git2::Error> {
|
) -> Result<git2::Remote<'r>, git2::Error> {
|
||||||
let url = Url {
|
|
||||||
scheme: git_url::Scheme::File,
|
|
||||||
path: remote_path.to_string_lossy().to_string().into(),
|
|
||||||
|
|
||||||
..Url::default()
|
|
||||||
};
|
|
||||||
let fetch = format!("+refs/remotes/{remote_id}/heads/*:refs/remotes/rad/*");
|
let fetch = format!("+refs/remotes/{remote_id}/heads/*:refs/remotes/rad/*");
|
||||||
let push = format!("refs/heads/*:refs/remotes/{remote_id}/heads/*");
|
let push = format!("refs/heads/*:refs/remotes/{remote_id}/heads/*");
|
||||||
let remote = repo.remote_with_fetch(remote_name, url.to_string().as_str(), &fetch)?;
|
let remote = repo.remote_with_fetch(remote_name, remote_url.to_string().as_str(), &fetch)?;
|
||||||
repo.remote_add_push(remote_name, &push)?;
|
repo.remote_add_push(remote_name, &push)?;
|
||||||
|
|
||||||
Ok(remote)
|
Ok(remote)
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
pub mod doc;
|
pub mod doc;
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::{ffi::OsString, fmt, str::FromStr};
|
use std::{ffi::OsString, fmt, str::FromStr};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::crypto;
|
use crate::crypto;
|
||||||
use crate::crypto::Verified;
|
|
||||||
use crate::git;
|
use crate::git;
|
||||||
use crate::serde_ext;
|
use crate::serde_ext;
|
||||||
use crate::storage::Remotes;
|
|
||||||
|
|
||||||
pub use crypto::PublicKey;
|
pub use crypto::PublicKey;
|
||||||
pub use doc::{Delegate, Doc};
|
pub use doc::{Delegate, Doc};
|
||||||
|
|
@ -175,36 +172,6 @@ impl Deref for Did {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A stored and verified project.
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Project {
|
|
||||||
/// The project identifier.
|
|
||||||
pub id: Id,
|
|
||||||
/// The latest project identity document.
|
|
||||||
pub doc: Doc<Verified>,
|
|
||||||
/// The project remotes.
|
|
||||||
pub remotes: Remotes<Verified>,
|
|
||||||
/// On-disk file path for this project's repository.
|
|
||||||
pub path: PathBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Project {
|
|
||||||
pub fn delegate(&mut self, name: String, key: crypto::PublicKey) -> bool {
|
|
||||||
self.doc.delegate(Delegate {
|
|
||||||
name,
|
|
||||||
id: Did::from(key),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for Project {
|
|
||||||
type Target = Doc<Verified>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.doc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,12 @@ impl Doc<Verified> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt to add a new delegate to the document. Returns `true` if it wasn't there before.
|
/// Attempt to add a new delegate to the document. Returns `true` if it wasn't there before.
|
||||||
pub fn delegate(&mut self, delegate: Delegate) -> bool {
|
pub fn delegate(&mut self, name: String, key: crypto::PublicKey) -> bool {
|
||||||
|
let delegate = Delegate {
|
||||||
|
name,
|
||||||
|
id: Did::from(key),
|
||||||
|
};
|
||||||
|
|
||||||
if self.delegates.iter().all(|d| d.id != delegate.id) {
|
if self.delegates.iter().all(|d| d.id != delegate.id) {
|
||||||
self.delegates.push(delegate);
|
self.delegates.push(delegate);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -510,7 +515,7 @@ mod test {
|
||||||
let repo = storage.repository(&id).unwrap();
|
let repo = storage.repository(&id).unwrap();
|
||||||
|
|
||||||
// Make a change to the description and sign it.
|
// Make a change to the description and sign it.
|
||||||
proj.doc.payload.description += "!";
|
proj.payload.description += "!";
|
||||||
proj.sign(&alice)
|
proj.sign(&alice)
|
||||||
.and_then(|(_, sig)| {
|
.and_then(|(_, sig)| {
|
||||||
proj.update(
|
proj.update(
|
||||||
|
|
@ -524,7 +529,7 @@ mod test {
|
||||||
|
|
||||||
// Add Bob as a delegate, and sign it.
|
// Add Bob as a delegate, and sign it.
|
||||||
proj.delegate("bob".to_owned(), *bob.public_key());
|
proj.delegate("bob".to_owned(), *bob.public_key());
|
||||||
proj.doc.threshold = 2;
|
proj.threshold = 2;
|
||||||
proj.sign(&alice)
|
proj.sign(&alice)
|
||||||
.and_then(|(_, sig)| {
|
.and_then(|(_, sig)| {
|
||||||
proj.update(
|
proj.update(
|
||||||
|
|
@ -552,7 +557,7 @@ mod test {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Update description again with signatures by Eve and Bob.
|
// Update description again with signatures by Eve and Bob.
|
||||||
proj.doc.payload.description += "?";
|
proj.payload.description += "?";
|
||||||
let (current, head) = proj
|
let (current, head) = proj
|
||||||
.sign(&bob)
|
.sign(&bob)
|
||||||
.and_then(|(_, bob_sig)| {
|
.and_then(|(_, bob_sig)| {
|
||||||
|
|
@ -579,7 +584,7 @@ mod test {
|
||||||
assert_eq!(identity.root, id);
|
assert_eq!(identity.root, id);
|
||||||
assert_eq!(identity.current, current);
|
assert_eq!(identity.current, current);
|
||||||
assert_eq!(identity.head, head);
|
assert_eq!(identity.head, head);
|
||||||
assert_eq!(identity.doc, proj.doc);
|
assert_eq!(identity.doc, proj);
|
||||||
|
|
||||||
let proj = storage.get(alice.public_key(), &id).unwrap().unwrap();
|
let proj = storage.get(alice.public_key(), &id).unwrap().unwrap();
|
||||||
assert_eq!(proj.description, "Acme's repository!?");
|
assert_eq!(proj.description, "Acme's repository!?");
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ pub fn init<'r, G: Signer, S: storage::WriteStorage<'r>>(
|
||||||
.verified()?;
|
.verified()?;
|
||||||
|
|
||||||
let (id, _, project) = doc.create(pk, "Initialize Radicle", storage)?;
|
let (id, _, project) = doc.create(pk, "Initialize Radicle", storage)?;
|
||||||
|
let url = storage.url(&id);
|
||||||
|
|
||||||
git::set_upstream(
|
git::set_upstream(
|
||||||
repo,
|
repo,
|
||||||
|
|
@ -69,7 +70,7 @@ pub fn init<'r, G: Signer, S: storage::WriteStorage<'r>>(
|
||||||
// TODO: Note that you'll likely want to use `RemoteCallbacks` and set
|
// TODO: Note that you'll likely want to use `RemoteCallbacks` and set
|
||||||
// `push_update_reference` to test whether all the references were pushed
|
// `push_update_reference` to test whether all the references were pushed
|
||||||
// successfully.
|
// successfully.
|
||||||
git::configure_remote(repo, REMOTE_NAME, pk, project.path())?.push::<&str>(
|
git::configure_remote(repo, REMOTE_NAME, pk, &url)?.push::<&str>(
|
||||||
&[&format!(
|
&[&format!(
|
||||||
"{}:{}",
|
"{}:{}",
|
||||||
&git::refs::workdir::branch(&default_branch),
|
&git::refs::workdir::branch(&default_branch),
|
||||||
|
|
@ -120,14 +121,11 @@ pub fn fork_remote<'r, G: Signer, S: storage::WriteStorage<'r>>(
|
||||||
|
|
||||||
let raw = repository.raw();
|
let raw = repository.raw();
|
||||||
let remote_head = raw
|
let remote_head = raw
|
||||||
.find_reference(&git::refs::storage::branch(
|
.find_reference(&git::refs::storage::branch(remote, &project.default_branch))?
|
||||||
remote,
|
|
||||||
&project.doc.default_branch,
|
|
||||||
))?
|
|
||||||
.target()
|
.target()
|
||||||
.ok_or(ForkError::InvalidReference)?;
|
.ok_or(ForkError::InvalidReference)?;
|
||||||
raw.reference(
|
raw.reference(
|
||||||
&git::refs::storage::branch(me, &project.doc.default_branch),
|
&git::refs::storage::branch(me, &project.default_branch),
|
||||||
remote_head,
|
remote_head,
|
||||||
false,
|
false,
|
||||||
&format!("creating default branch for {me}"),
|
&format!("creating default branch for {me}"),
|
||||||
|
|
@ -274,17 +272,14 @@ pub fn checkout<P: AsRef<Path>, S: storage::ReadStorage>(
|
||||||
.ok_or_else(|| CheckoutError::NotFound(proj.clone()))?;
|
.ok_or_else(|| CheckoutError::NotFound(proj.clone()))?;
|
||||||
|
|
||||||
let mut opts = git2::RepositoryInitOptions::new();
|
let mut opts = git2::RepositoryInitOptions::new();
|
||||||
opts.no_reinit(true).description(&project.doc.description);
|
opts.no_reinit(true).description(&project.description);
|
||||||
|
|
||||||
let repo = git2::Repository::init_opts(path, &opts)?;
|
let repo = git2::Repository::init_opts(path, &opts)?;
|
||||||
let default_branch = project.doc.default_branch.as_str();
|
let default_branch = project.default_branch.as_str();
|
||||||
|
let url = storage.url(proj);
|
||||||
|
|
||||||
// Configure and fetch all refs from remote.
|
// Configure and fetch all refs from remote.
|
||||||
git::configure_remote(&repo, REMOTE_NAME, remote, &project.path)?.fetch::<&str>(
|
git::configure_remote(&repo, REMOTE_NAME, remote, &url)?.fetch::<&str>(&[], None, None)?;
|
||||||
&[],
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// Setup default branch.
|
// Setup default branch.
|
||||||
|
|
@ -306,6 +301,8 @@ pub fn checkout<P: AsRef<Path>, S: storage::ReadStorage>(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::git::fmt::refname;
|
use crate::git::fmt::refname;
|
||||||
use crate::identity::{Delegate, Did};
|
use crate::identity::{Delegate, Did};
|
||||||
|
|
@ -332,14 +329,20 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let project = storage.get(&public_key, &proj).unwrap().unwrap();
|
let project = storage.get(&public_key, &proj).unwrap().unwrap();
|
||||||
|
let remotes: HashMap<_, _> = storage
|
||||||
|
.repository(&proj)
|
||||||
|
.unwrap()
|
||||||
|
.remotes()
|
||||||
|
.unwrap()
|
||||||
|
.collect::<Result<_, _>>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(project.remotes[&public_key].refs, refs);
|
assert_eq!(remotes[&public_key].refs, refs);
|
||||||
assert_eq!(project.id, proj);
|
assert_eq!(project.name, "acme");
|
||||||
assert_eq!(project.doc.name, "acme");
|
assert_eq!(project.description, "Acme's repo");
|
||||||
assert_eq!(project.doc.description, "Acme's repo");
|
assert_eq!(project.default_branch, BranchName::from("master"));
|
||||||
assert_eq!(project.doc.default_branch, BranchName::from("master"));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
project.doc.delegates.first(),
|
project.delegates.first(),
|
||||||
&Delegate {
|
&Delegate {
|
||||||
name: String::from("anonymous"),
|
name: String::from("anonymous"),
|
||||||
id: Did::from(public_key),
|
id: Did::from(public_key),
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ use crate::git::ext as git_ext;
|
||||||
use crate::git::Url;
|
use crate::git::Url;
|
||||||
use crate::git::{RefError, RefStr, RefString};
|
use crate::git::{RefError, RefStr, RefString};
|
||||||
use crate::identity;
|
use crate::identity;
|
||||||
use crate::identity::{Id, IdError, Project};
|
use crate::identity::{Id, IdError};
|
||||||
use crate::storage::git::IdentityError;
|
use crate::storage::git::IdentityError;
|
||||||
use crate::storage::refs::Refs;
|
use crate::storage::refs::Refs;
|
||||||
|
|
||||||
|
|
@ -216,8 +216,9 @@ impl Remote<Verified> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ReadStorage {
|
pub trait ReadStorage {
|
||||||
fn url(&self) -> Url;
|
fn path(&self) -> &Path;
|
||||||
fn get(&self, remote: &RemoteId, proj: &Id) -> Result<Option<Project>, Error>;
|
fn url(&self, proj: &Id) -> Url;
|
||||||
|
fn get(&self, remote: &RemoteId, proj: &Id) -> Result<Option<identity::Doc<Verified>>, Error>;
|
||||||
fn inventory(&self) -> Result<Inventory, Error>;
|
fn inventory(&self) -> Result<Inventory, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,7 +255,7 @@ pub trait ReadRepository<'r> {
|
||||||
fn remote(&self, remote: &RemoteId) -> Result<Remote<Verified>, refs::Error>;
|
fn remote(&self, remote: &RemoteId) -> Result<Remote<Verified>, refs::Error>;
|
||||||
fn remotes(&'r self) -> Result<Self::Remotes, git2::Error>;
|
fn remotes(&'r self) -> Result<Self::Remotes, git2::Error>;
|
||||||
/// Return the project associated with this repository.
|
/// Return the project associated with this repository.
|
||||||
fn project(&self) -> Result<Project, Error>;
|
fn project(&self) -> Result<identity::Doc<Verified>, Error>;
|
||||||
fn project_identity(&self) -> Result<(Oid, identity::Doc<Unverified>), IdentityError>;
|
fn project_identity(&self) -> Result<(Oid, identity::Doc<Unverified>), IdentityError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,15 +269,19 @@ where
|
||||||
T: Deref<Target = S>,
|
T: Deref<Target = S>,
|
||||||
S: ReadStorage + 'static,
|
S: ReadStorage + 'static,
|
||||||
{
|
{
|
||||||
fn url(&self) -> Url {
|
fn path(&self) -> &Path {
|
||||||
self.deref().url()
|
self.deref().path()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn url(&self, proj: &Id) -> Url {
|
||||||
|
self.deref().url(proj)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inventory(&self) -> Result<Inventory, Error> {
|
fn inventory(&self) -> Result<Inventory, Error> {
|
||||||
self.deref().inventory()
|
self.deref().inventory()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self, remote: &RemoteId, proj: &Id) -> Result<Option<Project>, Error> {
|
fn get(&self, remote: &RemoteId, proj: &Id) -> Result<Option<identity::Doc<Verified>>, Error> {
|
||||||
self.deref().get(remote, proj)
|
self.deref().get(remote, proj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use once_cell::sync::Lazy;
|
||||||
use crate::crypto::{Signer, Unverified, Verified};
|
use crate::crypto::{Signer, Unverified, Verified};
|
||||||
use crate::git;
|
use crate::git;
|
||||||
use crate::identity;
|
use crate::identity;
|
||||||
use crate::identity::{Doc, Id, Project};
|
use crate::identity::{Doc, Id};
|
||||||
use crate::storage::refs;
|
use crate::storage::refs;
|
||||||
use crate::storage::refs::{Refs, SignedRefs};
|
use crate::storage::refs::{Refs, SignedRefs};
|
||||||
use crate::storage::{
|
use crate::storage::{
|
||||||
|
|
@ -50,37 +50,27 @@ impl fmt::Debug for Storage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadStorage for Storage {
|
impl ReadStorage for Storage {
|
||||||
fn url(&self) -> Url {
|
fn path(&self) -> &Path {
|
||||||
|
self.path.as_path()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn url(&self, proj: &Id) -> Url {
|
||||||
|
let path = self.path().join(proj.to_string());
|
||||||
|
|
||||||
Url {
|
Url {
|
||||||
scheme: git_url::Scheme::File,
|
scheme: git_url::Scheme::File,
|
||||||
host: None,
|
path: path.to_string_lossy().to_string().into(),
|
||||||
path: self.path.to_string_lossy().to_string().into(),
|
|
||||||
..Url::default()
|
..git::Url::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self, remote: &RemoteId, proj: &Id) -> Result<Option<Project>, Error> {
|
fn get(&self, remote: &RemoteId, proj: &Id) -> Result<Option<Doc<Verified>>, Error> {
|
||||||
// TODO: Don't create a repo here if it doesn't exist?
|
// TODO: Don't create a repo here if it doesn't exist?
|
||||||
// Perhaps for checking we could have a `contains` method?
|
// Perhaps for checking we could have a `contains` method?
|
||||||
let repo = self.repository(proj)?;
|
self.repository(proj)?
|
||||||
|
.identity_of(remote)
|
||||||
if let Some(doc) = repo.identity_of(remote)? {
|
.map_err(Error::from)
|
||||||
let remotes = repo.remotes()?.collect::<Result<_, _>>()?;
|
|
||||||
let path = repo.path().to_path_buf();
|
|
||||||
|
|
||||||
// TODO: We should check that there is at least one remote, which is
|
|
||||||
// the one of the local user, otherwise it means the project is in
|
|
||||||
// an corrupted state.
|
|
||||||
|
|
||||||
Ok(Some(Project {
|
|
||||||
id: proj.clone(),
|
|
||||||
doc,
|
|
||||||
remotes,
|
|
||||||
path,
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inventory(&self) -> Result<Inventory, Error> {
|
fn inventory(&self) -> Result<Inventory, Error> {
|
||||||
|
|
@ -445,7 +435,7 @@ impl<'r> ReadRepository<'r> for Repository {
|
||||||
Ok(Box::new(iter))
|
Ok(Box::new(iter))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn project(&self) -> Result<Project, Error> {
|
fn project(&self) -> Result<Doc<Verified>, Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ use std::collections::{BTreeMap, HashSet};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ops::RangeBounds;
|
use std::ops::RangeBounds;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use nonempty::NonEmpty;
|
use nonempty::NonEmpty;
|
||||||
use quickcheck::Arbitrary;
|
use quickcheck::Arbitrary;
|
||||||
|
|
@ -12,7 +11,7 @@ use crate::crypto;
|
||||||
use crate::crypto::{KeyPair, PublicKey, Seed, Signer, Unverified, Verified};
|
use crate::crypto::{KeyPair, PublicKey, Seed, Signer, Unverified, Verified};
|
||||||
use crate::git;
|
use crate::git;
|
||||||
use crate::hash;
|
use crate::hash;
|
||||||
use crate::identity::{doc::Delegate, doc::Doc, Did, Id, Project};
|
use crate::identity::{doc::Delegate, doc::Doc, Did, Id};
|
||||||
use crate::storage;
|
use crate::storage;
|
||||||
use crate::storage::refs::{Refs, SignedRefs};
|
use crate::storage::refs::{Refs, SignedRefs};
|
||||||
use crate::test::signer::MockSigner;
|
use crate::test::signer::MockSigner;
|
||||||
|
|
@ -67,23 +66,6 @@ impl Arbitrary for storage::Remotes<crypto::Verified> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arbitrary for Project {
|
|
||||||
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
|
|
||||||
let doc = Doc::<Verified>::arbitrary(g);
|
|
||||||
let (oid, _) = doc.encode().unwrap();
|
|
||||||
let id = Id::from(oid);
|
|
||||||
let remotes = storage::Remotes::arbitrary(g);
|
|
||||||
let path = PathBuf::arbitrary(g);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
id,
|
|
||||||
doc,
|
|
||||||
remotes,
|
|
||||||
path,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Arbitrary for Did {
|
impl Arbitrary for Did {
|
||||||
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
|
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
|
||||||
Self::from(PublicKey::arbitrary(g))
|
Self::from(PublicKey::arbitrary(g))
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,42 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use git_url::Url;
|
use git_url::Url;
|
||||||
|
|
||||||
use crate::crypto::{Signer, Verified};
|
use crate::crypto::{Signer, Verified};
|
||||||
use crate::identity::{Id, Project};
|
use crate::identity::doc::Doc;
|
||||||
|
use crate::identity::Id;
|
||||||
|
|
||||||
pub use crate::storage::*;
|
pub use crate::storage::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MockStorage {
|
pub struct MockStorage {
|
||||||
pub inventory: Vec<Project>,
|
pub path: PathBuf,
|
||||||
|
pub inventory: HashMap<Id, Doc<Verified>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MockStorage {
|
impl MockStorage {
|
||||||
pub fn new(inventory: Vec<Project>) -> Self {
|
pub fn new(inventory: Vec<(Id, Doc<Verified>)>) -> Self {
|
||||||
Self { inventory }
|
Self {
|
||||||
|
path: PathBuf::default(),
|
||||||
|
inventory: inventory.into_iter().collect(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Self {
|
Self {
|
||||||
inventory: Vec::new(),
|
path: PathBuf::default(),
|
||||||
|
inventory: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadStorage for MockStorage {
|
impl ReadStorage for MockStorage {
|
||||||
fn url(&self) -> Url {
|
fn path(&self) -> &Path {
|
||||||
|
self.path.as_path()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn url(&self, _proj: &Id) -> Url {
|
||||||
Url {
|
Url {
|
||||||
scheme: git_url::Scheme::Radicle,
|
scheme: git_url::Scheme::Radicle,
|
||||||
host: Some("mock".to_string()),
|
host: Some("mock".to_string()),
|
||||||
|
|
@ -31,21 +44,12 @@ impl ReadStorage for MockStorage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self, _remote: &RemoteId, proj: &Id) -> Result<Option<Project>, Error> {
|
fn get(&self, _remote: &RemoteId, proj: &Id) -> Result<Option<Doc<Verified>>, Error> {
|
||||||
if let Some(proj) = self.inventory.iter().find(|p| p.id == *proj) {
|
Ok(self.inventory.get(proj).cloned())
|
||||||
return Ok(Some(proj.clone()));
|
|
||||||
}
|
|
||||||
Ok(None)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inventory(&self) -> Result<Inventory, Error> {
|
fn inventory(&self) -> Result<Inventory, Error> {
|
||||||
let inventory = self
|
Ok(self.inventory.keys().cloned().collect::<Vec<_>>())
|
||||||
.inventory
|
|
||||||
.iter()
|
|
||||||
.map(|proj| proj.id.clone())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
Ok(inventory)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,7 +126,7 @@ impl ReadRepository<'_> for MockRepository {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn project(&self) -> Result<Project, Error> {
|
fn project(&self) -> Result<Doc<Verified>, Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue