Make `ReadStorage` more usable
Previously, we were not able to access a `ReadRepository` instance through `ReadStorage`. With this change, we are able to.
This commit is contained in:
parent
89fcc6de1c
commit
950fae209d
|
|
@ -83,7 +83,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
let signer = term::signer(&profile)?;
|
||||
let storage = &profile.storage;
|
||||
let (_, id) = radicle::rad::cwd()?;
|
||||
let repo = storage.repository(id)?;
|
||||
let repo = storage.repository_mut(id)?;
|
||||
let mut issues = issue::Issues::open(*signer.public_key(), &repo)?;
|
||||
|
||||
let mut issue = issues.get_mut(&options.id).map_err(|err| match err {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use anyhow::Context as _;
|
|||
use radicle::prelude::*;
|
||||
use radicle::storage::git::transport;
|
||||
use radicle::storage::RemoteId;
|
||||
use radicle::storage::WriteStorage;
|
||||
|
||||
use crate::project;
|
||||
use crate::terminal as term;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use radicle::prelude::*;
|
|||
use radicle::rad;
|
||||
use radicle::storage;
|
||||
use radicle::storage::git::{ProjectError, Storage};
|
||||
use radicle::storage::WriteStorage;
|
||||
|
||||
use crate::commands::rad_checkout as checkout;
|
||||
use crate::project;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ use radicle::cob::store;
|
|||
use radicle::cob::thread;
|
||||
use radicle::prelude::*;
|
||||
use radicle::storage;
|
||||
use radicle::storage::WriteStorage;
|
||||
|
||||
use crate::terminal as term;
|
||||
use crate::terminal::args::{Args, Error, Help};
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ where
|
|||
.get(&profile.public_key, id)?
|
||||
.context("No project with such ID exists")?;
|
||||
|
||||
let repo = storage.repository(id)?;
|
||||
let repo = storage.repository_mut(id)?;
|
||||
|
||||
if !project.is_delegate(me) {
|
||||
return Err(anyhow::anyhow!(
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ where
|
|||
.get(&profile.public_key, id)?
|
||||
.context("No project with such ID exists")?;
|
||||
|
||||
let repo = storage.repository(id)?;
|
||||
let repo = storage.repository_mut(id)?;
|
||||
|
||||
if !project.is_delegate(me) {
|
||||
return Err(anyhow::anyhow!(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::str::FromStr;
|
|||
use anyhow::{anyhow, Context as _};
|
||||
|
||||
use radicle::identity::Id;
|
||||
use radicle::storage::{ReadStorage, WriteRepository, WriteStorage};
|
||||
use radicle::storage::{ReadStorage, WriteRepository};
|
||||
|
||||
use crate::terminal as term;
|
||||
use crate::terminal::args::{Args, Error, Help};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use radicle::cob::identity::{self, Proposal, ProposalId, Proposals, Revision, Re
|
|||
use radicle::git::Oid;
|
||||
use radicle::identity::Identity;
|
||||
use radicle::prelude::Doc;
|
||||
use radicle::storage::WriteStorage as _;
|
||||
use radicle::storage::ReadStorage as _;
|
||||
use radicle_crypto::{PublicKey, Verified};
|
||||
|
||||
use crate::terminal::args::{Args, Error, Help};
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use json_color::{Color, Colorizer};
|
|||
use radicle::crypto::Unverified;
|
||||
use radicle::identity::Untrusted;
|
||||
use radicle::identity::{Doc, Id};
|
||||
use radicle::storage::{ReadRepository, ReadStorage, WriteStorage};
|
||||
use radicle::storage::{ReadRepository, ReadStorage};
|
||||
|
||||
use crate::terminal as term;
|
||||
use crate::terminal::args::{Args, Error, Help};
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
let signer = term::signer(&profile)?;
|
||||
let storage = &profile.storage;
|
||||
let (_, id) = radicle::rad::cwd()?;
|
||||
let repo = storage.repository(id)?;
|
||||
let repo = storage.repository_mut(id)?;
|
||||
let mut issues = Issues::open(*signer.public_key(), &repo)?;
|
||||
|
||||
match options.op {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::ffi::OsString;
|
|||
use crate::terminal as term;
|
||||
use crate::terminal::args::{Args, Error, Help};
|
||||
|
||||
use radicle::storage::{ReadRepository, WriteStorage};
|
||||
use radicle::storage::{ReadRepository, ReadStorage};
|
||||
|
||||
pub const HELP: Help = Help {
|
||||
name: "ls",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::str::FromStr;
|
|||
use anyhow::{anyhow, Context as _};
|
||||
|
||||
use radicle::node::{Handle, NodeId};
|
||||
use radicle::storage::WriteStorage;
|
||||
use radicle::storage::ReadStorage;
|
||||
|
||||
use crate::terminal as term;
|
||||
use crate::terminal::args::{Args, Error, Help};
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
|||
let signer = term::signer(&profile)?;
|
||||
let storage = &profile.storage;
|
||||
let (_, id) = radicle::rad::cwd()?;
|
||||
let repo = storage.repository(id)?;
|
||||
let repo = storage.repository_mut(id)?;
|
||||
let mut issues = issue::Issues::open(*signer.public_key(), &repo)?;
|
||||
|
||||
let mut issue = issues.get_mut(&options.id).map_err(|err| match err {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use anyhow::{anyhow, Context as _};
|
|||
use radicle::identity::Id;
|
||||
use radicle::node::Handle;
|
||||
use radicle::prelude::*;
|
||||
use radicle::storage::WriteStorage;
|
||||
use radicle::storage::ReadStorage;
|
||||
|
||||
use crate::terminal as term;
|
||||
use crate::terminal::args::{Args, Error, Help};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::{thread, time};
|
|||
use radicle::git;
|
||||
use radicle::prelude::Id;
|
||||
use radicle::profile::Home;
|
||||
use radicle::storage::{ReadRepository, WriteStorage};
|
||||
use radicle::storage::{ReadRepository, ReadStorage};
|
||||
use radicle::test::fixtures;
|
||||
|
||||
use radicle_cli_test::TestFormula;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use tower_http::cors::{self, CorsLayer};
|
|||
|
||||
use radicle::cob::issue::Issues;
|
||||
use radicle::identity::Id;
|
||||
use radicle::storage::{ReadRepository, WriteStorage};
|
||||
use radicle::storage::{ReadRepository, ReadStorage};
|
||||
use radicle::Profile;
|
||||
|
||||
mod auth;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use tower::ServiceExt;
|
|||
use radicle::cob::issue::Issues;
|
||||
use radicle::cob::patch::{MergeTarget, Patches};
|
||||
use radicle::git::raw as git2;
|
||||
use radicle::storage::WriteStorage;
|
||||
use radicle::storage::ReadStorage;
|
||||
use radicle_cli::commands::rad_init;
|
||||
use radicle_crypto::ssh::keystore::MemorySigner;
|
||||
use radicle_crypto::Signer;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use axum::{Json, Router};
|
|||
|
||||
use radicle::cob::issue::Issues;
|
||||
use radicle::identity::Did;
|
||||
use radicle::storage::{ReadRepository, WriteStorage};
|
||||
use radicle::storage::{ReadRepository, ReadStorage};
|
||||
|
||||
use crate::api::axum_extra::{Path, Query};
|
||||
use crate::api::error::Error;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use radicle::cob::patch::Patches;
|
|||
use radicle::cob::{thread, ActorId, Tag};
|
||||
use radicle::identity::Id;
|
||||
use radicle::node::NodeId;
|
||||
use radicle::storage::{git::paths, ReadRepository, WriteStorage};
|
||||
use radicle::storage::{git::paths, ReadRepository, ReadStorage};
|
||||
use radicle_surf::{Glob, Oid, Repository};
|
||||
|
||||
use crate::api::axum_extra::{Path, Query};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::service::filter::Filter;
|
|||
use crate::service::{NodeId, Timestamp};
|
||||
use crate::storage;
|
||||
use crate::storage::refs::SignedRefs;
|
||||
use crate::storage::{ReadRepository, WriteStorage};
|
||||
use crate::storage::{ReadRepository, ReadStorage};
|
||||
use crate::wire;
|
||||
|
||||
/// Maximum number of addresses which can be announced to other nodes.
|
||||
|
|
@ -154,8 +154,14 @@ pub struct RefsAnnouncement {
|
|||
|
||||
impl RefsAnnouncement {
|
||||
/// Check if this announcement is "fresh", meaning if it contains refs we do not have.
|
||||
pub fn is_fresh<S: WriteStorage>(&self, storage: S) -> Result<bool, storage::Error> {
|
||||
let repo = storage.repository(self.rid)?;
|
||||
pub fn is_fresh<S: ReadStorage>(&self, storage: S) -> Result<bool, storage::Error> {
|
||||
let repo = match storage.repository(self.rid) {
|
||||
// If the repo doesn't exist, we consider this announcement "fresh", since we
|
||||
// obviously don't have the refs.
|
||||
Err(e) if e.is_not_found() => return Ok(true),
|
||||
Err(e) => return Err(e),
|
||||
Ok(r) => r,
|
||||
};
|
||||
|
||||
for (remote_id, theirs) in self.refs.iter() {
|
||||
if let Ok(ours) = repo.remote(remote_id) {
|
||||
|
|
|
|||
|
|
@ -411,7 +411,11 @@ impl<S: WriteStorage + 'static, G: Signer> Simulation<S, G> {
|
|||
Input::Fetched(f, result) => {
|
||||
let result = Rc::try_unwrap(result).unwrap();
|
||||
if f.initiated {
|
||||
let mut repo = p.storage().repository(f.rid).unwrap();
|
||||
let mut repo = match p.storage().repository_mut(f.rid) {
|
||||
Ok(repo) => repo,
|
||||
Err(e) if e.is_not_found() => p.storage().create(f.rid).unwrap(),
|
||||
Err(e) => panic!("Failed to open repository: {e}"),
|
||||
};
|
||||
fetch(&mut repo, &f.remote, f.namespaces.clone()).unwrap();
|
||||
}
|
||||
p.fetched(f, result);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::{thread, time};
|
|||
|
||||
use radicle::crypto::Signer;
|
||||
use radicle::node::{FetchResult, Handle as _};
|
||||
use radicle::storage::{ReadRepository, WriteStorage};
|
||||
use radicle::storage::{ReadRepository, ReadStorage};
|
||||
use radicle::{assert_matches, rad};
|
||||
|
||||
use crate::service;
|
||||
|
|
|
|||
|
|
@ -166,7 +166,11 @@ impl<G: Signer + Ecdh + 'static> Worker<G> {
|
|||
fetch: &Fetch,
|
||||
tunnel: &mut Tunnel<WireSession<G>>,
|
||||
) -> Result<Vec<RefUpdate>, FetchError> {
|
||||
let repo = self.storage.repository(fetch.rid)?;
|
||||
let repo = match self.storage.repository_mut(fetch.rid) {
|
||||
Ok(r) => Ok(r),
|
||||
Err(e) if e.is_not_found() => self.storage.create(fetch.rid),
|
||||
Err(e) => Err(e),
|
||||
}?;
|
||||
let tunnel_addr = tunnel.local_addr()?;
|
||||
let mut cmd = process::Command::new("git");
|
||||
cmd.current_dir(repo.path())
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ pub fn run(profile: radicle::Profile) -> Result<(), Box<dyn std::error::Error +
|
|||
// Default to profile key.
|
||||
let namespace = url.namespace.unwrap_or(profile.public_key);
|
||||
|
||||
let proj = profile.storage.repository(url.repo)?;
|
||||
let proj = profile.storage.repository_mut(url.repo)?;
|
||||
if proj.is_empty()? {
|
||||
return Err(Error::RepositoryNotFound(proj.path().to_path_buf()).into());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::path::Path;
|
||||
|
||||
use radicle::{node::Handle, storage::WriteRepository, storage::WriteStorage};
|
||||
use radicle::{node::Handle, storage::ReadStorage, storage::WriteRepository};
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let cwd = Path::new(".").canonicalize()?;
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ mod test {
|
|||
use crate::crypto::PublicKey;
|
||||
use crate::rad;
|
||||
use crate::storage::git::Storage;
|
||||
use crate::storage::{ReadStorage, WriteRepository, WriteStorage};
|
||||
use crate::storage::{ReadStorage, WriteRepository};
|
||||
use crate::test::fixtures;
|
||||
|
||||
use super::did::Did;
|
||||
|
|
|
|||
|
|
@ -371,7 +371,7 @@ mod test {
|
|||
use crate::rad;
|
||||
use crate::storage::git::transport;
|
||||
use crate::storage::git::Storage;
|
||||
use crate::storage::WriteStorage;
|
||||
use crate::storage::WriteStorage as _;
|
||||
use crate::test::arbitrary;
|
||||
use crate::test::fixtures;
|
||||
|
||||
|
|
@ -414,7 +414,7 @@ mod test {
|
|||
let storage = Storage::open(tempdir.path().join("storage")).unwrap();
|
||||
let remote = arbitrary::gen::<RemoteId>(1);
|
||||
let proj = arbitrary::gen::<Id>(1);
|
||||
let repo = storage.repository(proj).unwrap();
|
||||
let repo = storage.create(proj).unwrap();
|
||||
let oid = git2::Oid::from_str("2d52a53ce5e4f141148a5f770cfd3ead2d6a45b8").unwrap();
|
||||
|
||||
let err = Doc::<Unverified>::head(&remote, &repo).unwrap_err();
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ use crate::identity::project::Project;
|
|||
use crate::storage::git::transport;
|
||||
use crate::storage::git::{ProjectError, Repository, Storage};
|
||||
use crate::storage::refs::SignedRefs;
|
||||
use crate::storage::{BranchName, ReadRepository as _, RemoteId, WriteRepository as _};
|
||||
use crate::storage::WriteRepository;
|
||||
use crate::storage::{BranchName, ReadRepository as _, RemoteId};
|
||||
use crate::{identity, storage};
|
||||
|
||||
/// Name of the radicle storage remote.
|
||||
|
|
@ -129,7 +130,7 @@ pub fn fork_remote<G: Signer, S: storage::WriteStorage>(
|
|||
.get(remote, proj)?
|
||||
.ok_or(ForkError::NotFound(proj))?;
|
||||
let project = doc.project()?;
|
||||
let repository = storage.repository(proj)?;
|
||||
let repository = storage.repository_mut(proj)?;
|
||||
|
||||
let raw = repository.raw();
|
||||
let remote_head = raw.refname_to_id(&git::refs::storage::branch(
|
||||
|
|
@ -162,7 +163,7 @@ pub fn fork<G: Signer, S: storage::WriteStorage>(
|
|||
storage: &S,
|
||||
) -> Result<(), ForkError> {
|
||||
let me = signer.public_key();
|
||||
let repository = storage.repository(proj)?;
|
||||
let repository = storage.repository_mut(proj)?;
|
||||
// TODO: We should get the id branch pointer from a stored canonical reference.
|
||||
let (canonical_id, _) = repository.identity_doc()?;
|
||||
let (canonical_branch, canonical_head) = repository.head()?;
|
||||
|
|
@ -302,7 +303,7 @@ mod tests {
|
|||
use crate::identity::Did;
|
||||
use crate::storage::git::transport;
|
||||
use crate::storage::git::Storage;
|
||||
use crate::storage::{ReadStorage, WriteStorage};
|
||||
use crate::storage::ReadStorage;
|
||||
use crate::test::fixtures;
|
||||
|
||||
use super::*;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,18 @@ pub enum Error {
|
|||
Io(#[from] io::Error),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Whether this error is caused by something not being found.
|
||||
pub fn is_not_found(&self) -> bool {
|
||||
match self {
|
||||
Self::Io(e) if e.kind() == io::ErrorKind::NotFound => true,
|
||||
Self::Git(e) if git::is_not_found_err(e) => true,
|
||||
Self::Doc(e) if e.is_not_found() => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch error.
|
||||
#[derive(Error, Debug)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
|
|
@ -246,6 +258,8 @@ impl Remote<Verified> {
|
|||
|
||||
/// Read-only operations on a storage instance.
|
||||
pub trait ReadStorage {
|
||||
type Repository: ReadRepository;
|
||||
|
||||
/// Get the storage base path.
|
||||
fn path(&self) -> &Path;
|
||||
/// Get an identity document of a repository under a given remote.
|
||||
|
|
@ -258,13 +272,18 @@ pub trait ReadStorage {
|
|||
fn contains(&self, rid: &Id) -> Result<bool, ProjectError>;
|
||||
/// Get the inventory of repositories hosted under this storage.
|
||||
fn inventory(&self) -> Result<Inventory, Error>;
|
||||
/// Open or create a read-only repository.
|
||||
fn repository(&self, rid: Id) -> Result<Self::Repository, Error>;
|
||||
}
|
||||
|
||||
/// Allows access to individual storage repositories.
|
||||
pub trait WriteStorage: ReadStorage {
|
||||
type Repository: WriteRepository;
|
||||
type RepositoryMut: WriteRepository;
|
||||
|
||||
fn repository(&self, proj: Id) -> Result<Self::Repository, Error>;
|
||||
/// Open a read-write repository.
|
||||
fn repository_mut(&self, rid: Id) -> Result<Self::RepositoryMut, Error>;
|
||||
/// Create a read-write repository.
|
||||
fn create(&self, rid: Id) -> Result<Self::RepositoryMut, Error>;
|
||||
}
|
||||
|
||||
/// Allows read-only access to a repository.
|
||||
|
|
@ -355,6 +374,8 @@ where
|
|||
T: Deref<Target = S>,
|
||||
S: ReadStorage + 'static,
|
||||
{
|
||||
type Repository = S::Repository;
|
||||
|
||||
fn path(&self) -> &Path {
|
||||
self.deref().path()
|
||||
}
|
||||
|
|
@ -374,6 +395,10 @@ where
|
|||
) -> Result<Option<identity::Doc<Verified>>, ProjectError> {
|
||||
self.deref().get(remote, proj)
|
||||
}
|
||||
|
||||
fn repository(&self, rid: Id) -> Result<Self::Repository, Error> {
|
||||
self.deref().repository(rid)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> WriteStorage for T
|
||||
|
|
@ -381,10 +406,14 @@ where
|
|||
T: Deref<Target = S>,
|
||||
S: WriteStorage + 'static,
|
||||
{
|
||||
type Repository = S::Repository;
|
||||
type RepositoryMut = S::RepositoryMut;
|
||||
|
||||
fn repository(&self, proj: Id) -> Result<Self::Repository, Error> {
|
||||
self.deref().repository(proj)
|
||||
fn repository_mut(&self, rid: Id) -> Result<Self::RepositoryMut, Error> {
|
||||
self.deref().repository_mut(rid)
|
||||
}
|
||||
|
||||
fn create(&self, rid: Id) -> Result<Self::RepositoryMut, Error> {
|
||||
self.deref().create(rid)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,8 @@ pub struct Storage {
|
|||
}
|
||||
|
||||
impl ReadStorage for Storage {
|
||||
type Repository = Repository;
|
||||
|
||||
fn path(&self) -> &Path {
|
||||
self.path.as_path()
|
||||
}
|
||||
|
|
@ -108,29 +110,39 @@ impl ReadStorage for Storage {
|
|||
}
|
||||
|
||||
fn get(&self, remote: &RemoteId, proj: Id) -> Result<Option<Doc<Verified>>, ProjectError> {
|
||||
// TODO: Don't create a repo here if it doesn't exist?
|
||||
// Perhaps for checking we could have a `contains` method?
|
||||
match self.repository(proj)?.identity_of(remote) {
|
||||
let repo = match self.repository(proj) {
|
||||
Ok(doc) => doc,
|
||||
Err(e) if e.is_not_found() => return Ok(None),
|
||||
Err(e) => return Err(e.into()),
|
||||
};
|
||||
match repo.identity_of(remote) {
|
||||
Ok(doc) => Ok(Some(doc)),
|
||||
|
||||
Err(err) if err.is_not_found() => Ok(None),
|
||||
Err(err) => Err(err),
|
||||
Err(e) if e.is_not_found() => Ok(None),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
fn inventory(&self) -> Result<Inventory, Error> {
|
||||
self.repositories()
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteStorage for Storage {
|
||||
type Repository = Repository;
|
||||
|
||||
fn repository(&self, rid: Id) -> Result<Self::Repository, Error> {
|
||||
Repository::open(paths::repository(self, &rid), rid)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteStorage for Storage {
|
||||
type RepositoryMut = Repository;
|
||||
|
||||
fn repository_mut(&self, rid: Id) -> Result<Self::RepositoryMut, Error> {
|
||||
Repository::open(paths::repository(self, &rid), rid)
|
||||
}
|
||||
|
||||
fn create(&self, rid: Id) -> Result<Self::RepositoryMut, Error> {
|
||||
Repository::create(paths::repository(self, &rid), rid)
|
||||
}
|
||||
}
|
||||
|
||||
impl Storage {
|
||||
// TODO: Return a better error when not found.
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> {
|
||||
|
|
@ -207,27 +219,27 @@ pub enum VerifyError {
|
|||
}
|
||||
|
||||
impl Repository {
|
||||
/// Open an existing repository.
|
||||
pub fn open<P: AsRef<Path>>(path: P, id: Id) -> Result<Self, Error> {
|
||||
let backend = match git2::Repository::open_bare(path.as_ref()) {
|
||||
Err(e) if ext::is_not_found_err(&e) => {
|
||||
let backend = git2::Repository::init_opts(
|
||||
&path,
|
||||
git2::RepositoryInitOptions::new()
|
||||
.bare(true)
|
||||
.no_reinit(true)
|
||||
.external_template(false),
|
||||
)?;
|
||||
let mut config = backend.config()?;
|
||||
let backend = git2::Repository::open_bare(path.as_ref())?;
|
||||
|
||||
// TODO: Get ahold of user name and/or key.
|
||||
config.set_str("user.name", "radicle")?;
|
||||
config.set_str("user.email", "radicle@localhost")?;
|
||||
Ok(Self { id, backend })
|
||||
}
|
||||
|
||||
Ok(backend)
|
||||
}
|
||||
Ok(repo) => Ok(repo),
|
||||
Err(e) => Err(e),
|
||||
}?;
|
||||
/// Create a new repository.
|
||||
pub fn create<P: AsRef<Path>>(path: P, id: Id) -> Result<Self, Error> {
|
||||
let backend = git2::Repository::init_opts(
|
||||
&path,
|
||||
git2::RepositoryInitOptions::new()
|
||||
.bare(true)
|
||||
.no_reinit(true)
|
||||
.external_template(false),
|
||||
)?;
|
||||
let mut config = backend.config()?;
|
||||
|
||||
// TODO: Get ahold of user name and/or key.
|
||||
config.set_str("user.name", "radicle")?;
|
||||
config.set_str("user.email", "radicle@localhost")?;
|
||||
|
||||
Ok(Self { id, backend })
|
||||
}
|
||||
|
|
@ -241,7 +253,7 @@ impl Repository {
|
|||
) -> Result<(Self, git::Oid), Error> {
|
||||
let (doc_oid, doc) = doc.encode()?;
|
||||
let id = Id::from(doc_oid);
|
||||
let repo = Self::open(paths::repository(storage, &id), id)?;
|
||||
let repo = Self::create(paths::repository(storage, &id), id)?;
|
||||
let oid = Doc::init(
|
||||
doc.as_slice(),
|
||||
remote,
|
||||
|
|
@ -730,7 +742,7 @@ mod tests {
|
|||
let storage = Storage::open(tmp.path()).unwrap();
|
||||
let proj_id = arbitrary::gen::<Id>(1);
|
||||
let alice = *signer.public_key();
|
||||
let project = storage.repository(proj_id).unwrap();
|
||||
let project = storage.create(proj_id).unwrap();
|
||||
let backend = &project.backend;
|
||||
let sig = git2::Signature::now(&alice.to_string(), "anonymous@radicle.xyz").unwrap();
|
||||
let head = git::initial_commit(backend, &sig).unwrap();
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ impl MockStorage {
|
|||
}
|
||||
|
||||
impl ReadStorage for MockStorage {
|
||||
type Repository = MockRepository;
|
||||
|
||||
fn path(&self) -> &Path {
|
||||
self.path.as_path()
|
||||
}
|
||||
|
|
@ -51,12 +53,20 @@ impl ReadStorage for MockStorage {
|
|||
fn inventory(&self) -> Result<Inventory, Error> {
|
||||
Ok(self.inventory.keys().cloned().collect::<Vec<_>>())
|
||||
}
|
||||
|
||||
fn repository(&self, _proj: Id) -> Result<Self::Repository, Error> {
|
||||
Ok(MockRepository {})
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteStorage for MockStorage {
|
||||
type Repository = MockRepository;
|
||||
type RepositoryMut = MockRepository;
|
||||
|
||||
fn repository(&self, _proj: Id) -> Result<Self::Repository, Error> {
|
||||
fn repository_mut(&self, _rid: Id) -> Result<Self::RepositoryMut, Error> {
|
||||
Ok(MockRepository {})
|
||||
}
|
||||
|
||||
fn create(&self, _rid: Id) -> Result<Self::RepositoryMut, Error> {
|
||||
Ok(MockRepository {})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue