cli: Don't fail clone if we have repo locally

This commit is contained in:
Alexis Sellier 2023-02-27 18:19:02 +01:00
parent c70dc71b18
commit 207030d2e1
No known key found for this signature in database
4 changed files with 58 additions and 22 deletions

View File

@ -175,28 +175,33 @@ pub fn clone<G: Signer>(
// Get seeds. This consults the local routing table only.
let mut seeds = node.seeds(id)?;
if !seeds.has_connections() {
return Err(CloneError::NotFound(id));
}
// Fetch from all seeds.
for seed in seeds.connected() {
let spinner = term::spinner(format!(
"Fetching {} from {}..",
term::format::tertiary(id),
term::format::tertiary(term::format::node(seed))
));
if seeds.has_connections() {
// Fetch from all seeds.
for seed in seeds.connected() {
let spinner = term::spinner(format!(
"Fetching {} from {}..",
term::format::tertiary(id),
term::format::tertiary(term::format::node(seed))
));
// TODO: If none of them succeeds, output an error. Otherwise tell the caller
// how many succeeded.
match node.fetch(id, *seed)? {
FetchResult::Success { .. } => {
spinner.finish();
}
FetchResult::Failed { reason } => {
spinner.error(reason);
// TODO: If none of them succeeds, output an error. Otherwise tell the caller
// how many succeeded.
match node.fetch(id, *seed)? {
FetchResult::Success { .. } => {
spinner.finish();
}
FetchResult::Failed { reason } => {
spinner.error(reason);
}
}
}
}
// TODO: Warn if no seeds were found, and we might be checking out stale data.
// If we don't have the project locally, even after attempting to fetch,
// there's nothing we can do.
if !storage.contains(&id)? {
return Err(CloneError::NotFound(id));
}
// Create a local fork of the project, under our own id.
{

View File

@ -4,6 +4,7 @@ use std::str::FromStr;
use std::{thread, time};
use radicle::git;
use radicle::node::Handle as _;
use radicle::prelude::Id;
use radicle::profile::Home;
use radicle::storage::{ReadRepository, ReadStorage};
@ -293,6 +294,29 @@ fn rad_init_sync_and_clone() {
.unwrap();
}
#[test]
// User tries to clone; no seeds are available, but user has the repo locally.
fn test_clone_without_seeds() {
logger::init(log::Level::Debug);
let mut environment = Environment::new();
let mut alice = environment.node("alice");
let working = environment.tmp().join("working");
let rid = alice.project("heartwood", "Radicle Heartwood Protocol & Stack");
let mut alice = alice.spawn(Config::default());
let seeds = alice.handle.seeds(rid).unwrap();
assert!(!seeds.has_connections());
alice
.rad("clone", &[rid.to_string().as_str()], working.as_path())
.unwrap();
alice
.rad("inspect", &[], working.join("heartwood").as_path())
.unwrap();
}
#[test]
//
// alice -- seed -- bob

View File

@ -1,3 +1,4 @@
use std::io::BufRead as _;
use std::mem::ManuallyDrop;
use std::path::{Path, PathBuf};
use std::{
@ -209,15 +210,21 @@ impl<G: Signer + cyphernet::Ecdh> NodeHandle<G> {
.args(args)
.output()?;
for line in io::BufReader::new(io::Cursor::new(&result.stdout))
.lines()
.flatten()
{
log::debug!(target: "test", "rad {cmd}: {line}");
}
log::debug!(
target: "test",
"Ran command `rad {cmd}` (status={})", result.status.code().unwrap()
);
if !result.status.success() {
log::debug!(target: "test", "Command: {result:#?}");
return Err(io::ErrorKind::Other.into());
}
Ok(())
}
}

View File

@ -158,12 +158,12 @@ pub fn fork_remote<G: Signer, S: storage::WriteStorage>(
}
pub fn fork<G: Signer, S: storage::WriteStorage>(
proj: Id,
rid: Id,
signer: &G,
storage: &S,
) -> Result<(), ForkError> {
let me = signer.public_key();
let repository = storage.repository_mut(proj)?;
let repository = storage.repository_mut(rid)?;
// 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()?;