cli: Add `rad-clone` test
This commit is contained in:
parent
a8531eff36
commit
2649e9c6fe
|
|
@ -0,0 +1,45 @@
|
|||
To create a local copy of a repository on the radicle network, we use the
|
||||
`clone` command, followed by the identifier or *RID* of the repository:
|
||||
|
||||
```
|
||||
$ rad clone rad:zVNuptPuk5XauitpCWSNVCXGGfXW
|
||||
ok Tracking relationship established for rad:zVNuptPuk5XauitpCWSNVCXGGfXW
|
||||
ok Fetching rad:zVNuptPuk5XauitpCWSNVCXGGfXW from z6MknSL…StBU8Vi..
|
||||
ok Forking under z6Mkt67…v4N1tRk..
|
||||
ok Creating checkout in ./acme..
|
||||
ok Remote z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi created
|
||||
ok Remote-tracking branch z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master created for z6MknSL…StBU8Vi
|
||||
|
||||
🌱 Project successfully cloned under [..]/acme/
|
||||
|
||||
```
|
||||
|
||||
We can now have a look at the new working copy that was created from the cloned
|
||||
repository:
|
||||
|
||||
```
|
||||
$ cd acme
|
||||
$ ls
|
||||
README
|
||||
$ cat README
|
||||
Hello World!
|
||||
```
|
||||
|
||||
Let's check that the remote tracking branch was setup correctly:
|
||||
|
||||
```
|
||||
$ git branch --remotes
|
||||
rad/master
|
||||
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master
|
||||
```
|
||||
|
||||
The first branch is ours, and the second points to the repository delegate.
|
||||
We can also take a look at the remotes:
|
||||
|
||||
```
|
||||
$ git remote -v
|
||||
rad rad://zVNuptPuk5XauitpCWSNVCXGGfXW/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (fetch)
|
||||
rad rad://zVNuptPuk5XauitpCWSNVCXGGfXW/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (push)
|
||||
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi rad://zVNuptPuk5XauitpCWSNVCXGGfXW/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (fetch)
|
||||
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi rad://zVNuptPuk5XauitpCWSNVCXGGfXW/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (push)
|
||||
```
|
||||
|
|
@ -144,7 +144,7 @@ pub fn clone<G: Signer>(
|
|||
// Track.
|
||||
if node.track_repo(id)? {
|
||||
term::success!(
|
||||
"Tracking relationship restablished for {}",
|
||||
"Tracking relationship established for {}",
|
||||
term::format::tertiary(id)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ use radicle::git;
|
|||
use radicle::profile::Home;
|
||||
use radicle::test::fixtures;
|
||||
|
||||
use radicle_node::test::environment::Environment;
|
||||
use radicle_node::test::{
|
||||
environment::{Config, Environment},
|
||||
logger,
|
||||
};
|
||||
|
||||
mod framework;
|
||||
use framework::TestFormula;
|
||||
|
|
@ -64,15 +67,15 @@ fn rad_issue() {
|
|||
let mut environment = Environment::new();
|
||||
let profile = environment.profile("alice");
|
||||
let home = &profile.home;
|
||||
let working = tempfile::tempdir().unwrap();
|
||||
let working = environment.tmp().join("working");
|
||||
|
||||
// Setup a test repository.
|
||||
fixtures::repository(working.path());
|
||||
fixtures::repository(&working);
|
||||
// Set a fixed commit time.
|
||||
env::set_var(radicle_cob::git::RAD_COMMIT_TIME, "1671125284");
|
||||
|
||||
test("examples/rad-init.md", working.path(), Some(home), []).unwrap();
|
||||
test("examples/rad-issue.md", working.path(), Some(home), []).unwrap();
|
||||
test("examples/rad-init.md", &working, Some(home), []).unwrap();
|
||||
test("examples/rad-issue.md", &working, Some(home), []).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -149,3 +152,23 @@ fn rad_patch() {
|
|||
test("examples/rad-issue.md", working.path(), Some(home), []).unwrap();
|
||||
test("examples/rad-patch.md", working.path(), Some(home), []).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rad_clone() {
|
||||
logger::init(log::Level::Debug);
|
||||
|
||||
let mut environment = Environment::new();
|
||||
let mut alice = environment.node("alice");
|
||||
let bob = environment.node("bob");
|
||||
let working = environment.tmp().join("working");
|
||||
|
||||
// Setup a test project.
|
||||
let _ = alice.project("acme", "");
|
||||
|
||||
let alice = alice.spawn(Config::default());
|
||||
let mut bob = bob.spawn(Config::default());
|
||||
|
||||
bob.connect(&alice).converge([&alice]);
|
||||
|
||||
test("examples/rad-clone.md", working, Some(&bob.home), []).unwrap();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,6 +139,8 @@ impl TestFormula {
|
|||
pub fn run(&mut self) -> Result<bool, io::Error> {
|
||||
let assert = Assert::new().substitutions(self.subs.clone());
|
||||
|
||||
fs::create_dir_all(&self.cwd)?;
|
||||
|
||||
for test in &self.tests {
|
||||
for assertion in &test.assertions {
|
||||
let program = if assertion.program == "rad" {
|
||||
|
|
@ -162,7 +164,14 @@ impl TestFormula {
|
|||
} else {
|
||||
PathBuf::from(&assertion.program)
|
||||
};
|
||||
log::debug!(target: "test", "Running `{}` in `{}`..", program.display(), self.cwd.display());
|
||||
|
||||
if !program.exists() {
|
||||
log::error!(target: "test", "Program {} does not exist..", program.display());
|
||||
}
|
||||
if !self.cwd.exists() {
|
||||
log::error!(target: "test", "Directory {} does not exist..", self.cwd.display());
|
||||
}
|
||||
let result = Command::new(program.clone())
|
||||
.env_clear()
|
||||
.envs(env::vars().filter(|(k, _)| k == "PATH"))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use std::mem::ManuallyDrop;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
iter, net, thread,
|
||||
|
|
@ -23,6 +23,8 @@ use crate::node::NodeId;
|
|||
use crate::storage::git::transport;
|
||||
use crate::{runtime, runtime::Handle, service, Runtime};
|
||||
|
||||
pub use service::Config;
|
||||
|
||||
/// Test environment.
|
||||
pub struct Environment {
|
||||
tempdir: tempfile::TempDir,
|
||||
|
|
@ -44,6 +46,11 @@ impl Environment {
|
|||
Self::default()
|
||||
}
|
||||
|
||||
/// Return the temp directory path.
|
||||
pub fn tmp(&self) -> PathBuf {
|
||||
self.tempdir.path().join("misc")
|
||||
}
|
||||
|
||||
/// Create a new node in this environment. This should be used when a running node
|
||||
/// is required. Use [`Environment::profile`] otherwise.
|
||||
pub fn node(&mut self, name: &str) -> Node<MemorySigner> {
|
||||
|
|
@ -60,7 +67,9 @@ impl Environment {
|
|||
/// Create a new profile in this environment.
|
||||
/// This should be used when a running node is not required.
|
||||
pub fn profile(&mut self, name: &str) -> Profile {
|
||||
let home = Home::new(self.tempdir.path().join(name)).init().unwrap();
|
||||
let home = Home::new(self.tmp().join("home").join(name))
|
||||
.init()
|
||||
.unwrap();
|
||||
let storage = Storage::open(home.storage()).unwrap();
|
||||
let keystore = Keystore::new(&home.keys());
|
||||
let keypair = KeyPair::from_seed(Seed::from([!(self.users as u8); 32]));
|
||||
|
|
@ -94,6 +103,7 @@ pub struct NodeHandle<G: Signer + cyphernet::EcSign + 'static> {
|
|||
pub id: NodeId,
|
||||
pub storage: Storage,
|
||||
pub signer: G,
|
||||
pub home: Home,
|
||||
pub addr: net::SocketAddr,
|
||||
pub thread: ManuallyDrop<thread::JoinHandle<Result<(), runtime::Error>>>,
|
||||
pub handle: ManuallyDrop<Handle<G>>,
|
||||
|
|
@ -115,7 +125,7 @@ impl<G: Signer + cyphernet::EcSign + 'static> Drop for NodeHandle<G> {
|
|||
|
||||
impl<G: Signer + cyphernet::EcSign> NodeHandle<G> {
|
||||
/// Connect this node to another node, and wait for the connection to be established both ways.
|
||||
pub fn connect(&mut self, remote: &NodeHandle<G>) {
|
||||
pub fn connect(&mut self, remote: &NodeHandle<G>) -> &mut Self {
|
||||
self.handle.connect(remote.id, remote.addr.into()).unwrap();
|
||||
|
||||
loop {
|
||||
|
|
@ -137,6 +147,15 @@ impl<G: Signer + cyphernet::EcSign> NodeHandle<G> {
|
|||
}
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Wait until this node's routing table matches the remotes.
|
||||
pub fn converge<'a>(
|
||||
&'a self,
|
||||
remotes: impl IntoIterator<Item = &'a NodeHandle<G>>,
|
||||
) -> BTreeSet<(Id, NodeId)> {
|
||||
converge(iter::once(self).chain(remotes.into_iter()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +186,7 @@ impl<G: cyphernet::EcSign<Pk = NodeId, Sig = Signature> + Signer + Clone> Node<G
|
|||
let proxy = net::SocketAddr::new(net::Ipv4Addr::LOCALHOST.into(), 9050);
|
||||
let daemon = ([0, 0, 0, 0], fastrand::u16(1025..)).into();
|
||||
let rt = Runtime::init(
|
||||
self.home,
|
||||
self.home.clone(),
|
||||
config,
|
||||
listen,
|
||||
proxy,
|
||||
|
|
@ -189,6 +208,7 @@ impl<G: cyphernet::EcSign<Pk = NodeId, Sig = Signature> + Signer + Clone> Node<G
|
|||
id,
|
||||
storage: self.storage,
|
||||
signer: self.signer,
|
||||
home: self.home,
|
||||
addr,
|
||||
handle,
|
||||
thread,
|
||||
|
|
@ -196,18 +216,15 @@ impl<G: cyphernet::EcSign<Pk = NodeId, Sig = Signature> + Signer + Clone> Node<G
|
|||
}
|
||||
|
||||
/// Populate a storage instance with a project.
|
||||
pub fn project(&mut self, name: &str) -> Id {
|
||||
pub fn project(&mut self, name: &str, description: &str) -> Id {
|
||||
transport::local::register(self.storage.clone());
|
||||
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let (repo, _) = fixtures::gen::repository(tmp.path());
|
||||
let description = iter::repeat_with(fastrand::alphabetic)
|
||||
.take(12)
|
||||
.collect::<String>();
|
||||
let id = rad::init(
|
||||
&repo,
|
||||
name,
|
||||
&description,
|
||||
description,
|
||||
refname!("master"),
|
||||
&self.signer,
|
||||
&self.storage,
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ fn test_inventory_sync_basic() {
|
|||
let mut alice = Node::init(tmp.path());
|
||||
let mut bob = Node::init(tmp.path());
|
||||
|
||||
alice.project("alice");
|
||||
bob.project("bob");
|
||||
alice.project("alice", "");
|
||||
bob.project("bob", "");
|
||||
|
||||
let mut alice = alice.spawn(service::Config::default());
|
||||
let bob = bob.spawn(service::Config::default());
|
||||
|
|
@ -45,9 +45,9 @@ fn test_inventory_sync_bridge() {
|
|||
let mut bob = Node::init(tmp.path());
|
||||
let mut eve = Node::init(tmp.path());
|
||||
|
||||
alice.project("alice");
|
||||
bob.project("bob");
|
||||
eve.project("eve");
|
||||
alice.project("alice", "");
|
||||
bob.project("bob", "");
|
||||
eve.project("eve", "");
|
||||
|
||||
let mut alice = alice.spawn(service::Config::default());
|
||||
let mut bob = bob.spawn(service::Config::default());
|
||||
|
|
@ -76,10 +76,10 @@ fn test_inventory_sync_ring() {
|
|||
let mut eve = Node::init(tmp.path());
|
||||
let mut carol = Node::init(tmp.path());
|
||||
|
||||
alice.project("alice");
|
||||
bob.project("bob");
|
||||
eve.project("eve");
|
||||
carol.project("carol");
|
||||
alice.project("alice", "");
|
||||
bob.project("bob", "");
|
||||
eve.project("eve", "");
|
||||
carol.project("carol", "");
|
||||
|
||||
let mut alice = alice.spawn(service::Config::default());
|
||||
let mut bob = bob.spawn(service::Config::default());
|
||||
|
|
@ -114,11 +114,11 @@ fn test_inventory_sync_star() {
|
|||
let mut carol = Node::init(tmp.path());
|
||||
let mut dave = Node::init(tmp.path());
|
||||
|
||||
alice.project("alice");
|
||||
bob.project("bob");
|
||||
eve.project("eve");
|
||||
carol.project("carol");
|
||||
dave.project("dave");
|
||||
alice.project("alice", "");
|
||||
bob.project("bob", "");
|
||||
eve.project("eve", "");
|
||||
carol.project("carol", "");
|
||||
dave.project("dave", "");
|
||||
|
||||
let alice = alice.spawn(service::Config::default());
|
||||
let mut bob = bob.spawn(service::Config::default());
|
||||
|
|
@ -142,7 +142,7 @@ fn test_replication() {
|
|||
let tmp = tempfile::tempdir().unwrap();
|
||||
let alice = Node::init(tmp.path());
|
||||
let mut bob = Node::init(tmp.path());
|
||||
let acme = bob.project("acme");
|
||||
let acme = bob.project("acme", "");
|
||||
|
||||
let mut alice = alice.spawn(service::Config::default());
|
||||
let bob = bob.spawn(service::Config::default());
|
||||
|
|
@ -199,7 +199,7 @@ fn test_clone() {
|
|||
let tmp = tempfile::tempdir().unwrap();
|
||||
let alice = Node::init(tmp.path());
|
||||
let mut bob = Node::init(tmp.path());
|
||||
let acme = bob.project("acme");
|
||||
let acme = bob.project("acme", "");
|
||||
|
||||
let mut alice = alice.spawn(service::Config::default());
|
||||
let bob = bob.spawn(service::Config::default());
|
||||
|
|
@ -249,7 +249,7 @@ fn test_fetch_up_to_date() {
|
|||
let tmp = tempfile::tempdir().unwrap();
|
||||
let alice = Node::init(tmp.path());
|
||||
let mut bob = Node::init(tmp.path());
|
||||
let acme = bob.project("acme");
|
||||
let acme = bob.project("acme", "");
|
||||
|
||||
let mut alice = alice.spawn(service::Config::default());
|
||||
let bob = bob.spawn(service::Config::default());
|
||||
|
|
|
|||
Loading…
Reference in New Issue