diff --git a/radicle-cli/examples/rad-clone-all.md b/radicle-cli/examples/rad-clone-all.md index aa99a89f..8e0fc084 100644 --- a/radicle-cli/examples/rad-clone-all.md +++ b/radicle-cli/examples/rad-clone-all.md @@ -2,7 +2,6 @@ $ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope all ✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'all' ✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MknSL…StBU8Vi.. -✓ Forking under z6Mkux1…nVhib7Z.. ✓ Creating checkout in ./heartwood.. ✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added ✓ Remote-tracking branch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master created for z6MknSL…StBU8Vi @@ -24,7 +23,7 @@ $ cat README Hello World! ``` -Let's check that we have all the namespaces in storage: +Let's check that we have Bob and Alice's namespaces in storage: ``` $ rad inspect --refs @@ -39,12 +38,6 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi       ├── id       └── sigrefs z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk -└── refs -    ├── heads -    │   └── master -    └── rad -       └── sigrefs -z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z └── refs    ├── heads    │   └── master @@ -72,3 +65,36 @@ $ git branch --remotes bob/master rad/master ``` + +We can also create our own fork just by pushing: + +``` (stderr) +$ git push -o no-sync rad master +To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z + * [new branch] master -> master +``` +``` +$ rad inspect --refs +z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi +└── refs +    ├── cobs +    │   └── xyz.radicle.id +    │      └── [...] +    ├── heads +    │   └── master +    └── rad +       ├── id +       └── sigrefs +z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk +└── refs +    ├── heads +    │   └── master +    └── rad +       └── sigrefs +z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z +└── refs +    ├── heads +    │   └── master +    └── rad +       └── sigrefs +``` diff --git a/radicle-cli/examples/rad-clone-connect.md b/radicle-cli/examples/rad-clone-connect.md index 02883783..3b716561 100644 --- a/radicle-cli/examples/rad-clone-connect.md +++ b/radicle-cli/examples/rad-clone-connect.md @@ -8,7 +8,6 @@ $ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji ✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MknSL…StBU8Vi.. ✓ Connecting to z6Mkt67…v4N1tRk@[..] ✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6Mkt67…v4N1tRk.. -✓ Forking under z6Mkux1…nVhib7Z.. ✓ Creating checkout in ./heartwood.. ✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added ✓ Remote-tracking branch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master created for z6MknSL…StBU8Vi diff --git a/radicle-cli/examples/rad-clone.md b/radicle-cli/examples/rad-clone.md index 14d3cfa2..48c547a5 100644 --- a/radicle-cli/examples/rad-clone.md +++ b/radicle-cli/examples/rad-clone.md @@ -5,7 +5,6 @@ To create a local copy of a repository on the radicle network, we use the $ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope followed ✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed' ✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MknSL…StBU8Vi.. -✓ Forking under z6Mkt67…v4N1tRk.. ✓ Creating checkout in ./heartwood.. ✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added ✓ Remote-tracking branch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master created for z6MknSL…StBU8Vi @@ -27,6 +26,11 @@ $ ls README $ cat README Hello World! +$ git status +On branch master +Your branch is up to date with 'rad/master'. + +nothing to commit, working tree clean ``` Let's check that the remote tracking branch was setup correctly: @@ -61,7 +65,7 @@ Date: Mon Jan 1 14:39:16 2018 +0000 Cloned repositories show up in `rad ls`: ``` -$ rad ls +$ rad ls --all ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ Name RID Visibility Head Description │ ├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤ diff --git a/radicle-cli/examples/rad-id-multi-delegate.md b/radicle-cli/examples/rad-id-multi-delegate.md index 6d0e5309..09f1b40f 100644 --- a/radicle-cli/examples/rad-id-multi-delegate.md +++ b/radicle-cli/examples/rad-id-multi-delegate.md @@ -4,9 +4,24 @@ $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Bob" --des ``` ``` ~bob +$ rad watch --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --node z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z -r 'refs/rad/sigrefs' -t 95cd447c57de8d232c6154f5dba0451aa593520e -i 500 --timeout 5000 $ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji ✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MknSL…StBU8Vi.. ✓ Fetched repository from 1 seed(s) +$ rad id --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji +╭────────────────────────────────────────────────────────────────────────────────╮ +│ ● ID Title Author Status Created │ +├────────────────────────────────────────────────────────────────────────────────┤ +│ ● 069e7d5 Add Bob alice z6MknSL…StBU8Vi accepted now │ +│ ● 0656c21 Initial revision alice z6MknSL…StBU8Vi accepted now │ +╰────────────────────────────────────────────────────────────────────────────────╯ +$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --sigrefs +z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi [..] +z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk [..] +z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z [..] +$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --delegates +did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice) +did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob) $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Eve" --description "" --delegate did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z --no-confirm ✓ Identity revision 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 created ╭────────────────────────────────────────────────────────────────────────╮ diff --git a/radicle-cli/examples/rad-patch-pull-update.md b/radicle-cli/examples/rad-patch-pull-update.md index 769ba261..1673f276 100644 --- a/radicle-cli/examples/rad-patch-pull-update.md +++ b/radicle-cli/examples/rad-patch-pull-update.md @@ -22,7 +22,6 @@ To push changes, run `git push`. $ rad clone rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK ✓ Seeding policy updated for rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK with scope 'all' ✓ Fetching rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK from z6MknSL…StBU8Vi.. -✓ Forking under z6Mkt67…v4N1tRk.. ✓ Creating checkout in ./heartwood.. ✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added ✓ Remote-tracking branch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master created for z6MknSL…StBU8Vi @@ -35,18 +34,20 @@ $ rad clone rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK Run `cd ./heartwood` to go to the project directory. ``` -We wait for Alice to sync our fork. +We fork the repository by pushing to `master`, and wait for Alice to sync +our fork: -``` ~bob -$ rad node events -n 2 --timeout 1 -{"type":"refsAnnounced","nid":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","rid":"rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK","refs":[{"remote":"z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk","at":"161b775a3509c8098de67f57f750972bba015b31"}],"timestamp":[..]} -{"type":"refsSynced","remote":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","rid":"rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK","at":"161b775a3509c8098de67f57f750972bba015b31"} +``` ~bob (stderr) +$ cd heartwood +$ git push rad master +✓ Synced with 1 node(s) +To rad://zhbMU4DUXrzB8xT6qAJh6yZ7bFMK/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk + * [new branch] master -> master ``` Bob then opens a patch. ``` ~bob (stderr) -$ cd heartwood $ git checkout -b bob/feature -q $ git commit --allow-empty -m "Bob's commit #1" -q $ git push rad -o sync -o patch.message="Bob's patch" HEAD:refs/patches diff --git a/radicle-cli/examples/workflow/5-patching-maintainer.md b/radicle-cli/examples/workflow/5-patching-maintainer.md index 52a90a75..ec2c332f 100644 --- a/radicle-cli/examples/workflow/5-patching-maintainer.md +++ b/radicle-cli/examples/workflow/5-patching-maintainer.md @@ -21,7 +21,6 @@ $ rad remote add z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --name bob $ git fetch bob ✓ Synced with 1 peer(s) From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk - * [new branch] master -> bob/master * [new branch] patches/3581e83ad18f5cdd806ab50fa11cfd5dd4e8ae1c -> bob/patches/3581e83ad18f5cdd806ab50fa11cfd5dd4e8ae1c ``` @@ -29,7 +28,6 @@ The contributor's changes are now visible to us. ``` $ git branch -r - bob/master bob/patches/3581e83ad18f5cdd806ab50fa11cfd5dd4e8ae1c rad/master $ rad patch show 3581e83 diff --git a/radicle-cli/src/commands/clone.rs b/radicle-cli/src/commands/clone.rs index 7b2e4d2a..35c807d6 100644 --- a/radicle-cli/src/commands/clone.rs +++ b/radicle-cli/src/commands/clone.rs @@ -18,7 +18,6 @@ use radicle::prelude::*; use radicle::rad; use radicle::storage; use radicle::storage::git::Storage; -use radicle::storage::RemoteRepository as _; use radicle::storage::RepositoryError; use crate::commands::rad_checkout as checkout; @@ -40,7 +39,6 @@ Usage Options --scope Follow scope (default: all) - --no-announce Do not announce our new refs to the network --help Print help "#, @@ -49,7 +47,6 @@ Options #[derive(Debug)] pub struct Options { id: Id, - announce: bool, scope: Scope, } @@ -59,7 +56,6 @@ impl Args for Options { let mut parser = lexopt::Parser::from_args(args); let mut id: Option = None; - let mut announce = true; let mut scope = Scope::All; while let Some(arg) = parser.next()? { @@ -73,12 +69,6 @@ impl Args for Options { // We keep this flag here for consistency though it doesn't have any effect, // since the command is fully non-interactive. } - Long("no-announce") => { - announce = false; - } - Long("announce") => { - announce = true; - } Long("help") | Short('h') => { return Err(Error::Help.into()); } @@ -95,14 +85,7 @@ impl Args for Options { let id = id.ok_or_else(|| anyhow!("to clone, an RID must be provided; see `rad clone --help`"))?; - Ok(( - Options { - id, - scope, - announce, - }, - vec![], - )) + Ok((Options { id, scope }, vec![])) } } @@ -119,7 +102,6 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { let (working, repo, doc, proj) = clone( options.id, - options.announce, options.scope, &mut node, &signer, @@ -180,8 +162,6 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { pub enum CloneError { #[error("node: {0}")] Node(#[from] node::Error), - #[error("fork: {0}")] - Fork(#[from] rad::ForkError), #[error("storage: {0}")] Storage(#[from] storage::Error), #[error("checkout: {0}")] @@ -200,7 +180,6 @@ pub enum CloneError { pub fn clone( id: Id, - announce: bool, scope: Scope, node: &mut Node, signer: &G, @@ -240,26 +219,6 @@ pub fn clone( } }; - // Create a local fork of the project, under our own id, unless we have one already. - if repository.remote(signer.public_key()).is_err() { - let mut spinner = term::spinner(format!( - "Forking under {}..", - term::format::tertiary(term::format::node(&me)) - )); - rad::fork(id, signer, &storage)?; - - if announce { - if let Err(e) = node.announce_refs(id) { - spinner.message("Announcing fork.."); - spinner.error(e); - } else { - spinner.finish(); - } - } else { - spinner.finish(); - } - } - let doc = repository.identity_doc()?; let proj = doc.project()?; let path = Path::new(proj.name()); diff --git a/radicle-cli/src/terminal.rs b/radicle-cli/src/terminal.rs index f5321d94..9dbe6246 100644 --- a/radicle-cli/src/terminal.rs +++ b/radicle-cli/src/terminal.rs @@ -14,7 +14,7 @@ use std::process; pub use radicle_term::*; -use radicle::profile::Profile; +use radicle::profile::{ConfigError, Profile}; use crate::terminal; diff --git a/radicle-cli/tests/commands.rs b/radicle-cli/tests/commands.rs index 0408ef21..b1e5df9a 100644 --- a/radicle-cli/tests/commands.rs +++ b/radicle-cli/tests/commands.rs @@ -265,13 +265,8 @@ fn rad_id() { alice.connect(&bob).converge([&bob]); let events = alice.handle.events(); - test( - "examples/rad-clone.md", - working.join("bob"), - Some(&bob.home), - [], - ) - .unwrap(); + bob.fork(acme, bob.home.path()).unwrap(); + bob.announce(acme, bob.home.path()).unwrap(); alice.has_inventory_of(&acme, &bob.id); // Alice must have Bob to try add them as a delegate @@ -321,23 +316,11 @@ fn rad_id_multi_delegate() { alice.connect(&bob).converge([&bob]); eve.connect(&alice).converge([&alice]); - test( - "examples/rad-clone.md", - working.join("bob"), - Some(&bob.home), - [], - ) - .unwrap(); + bob.fork(acme, working.join("bob")).unwrap(); bob.has_inventory_of(&acme, &alice.id); alice.has_inventory_of(&acme, &bob.id); - test( - "examples/rad-clone-all.md", - working.join("eve"), - Some(&eve.home), - [], - ) - .unwrap(); + eve.fork(acme, working.join("eve")).unwrap(); eve.has_inventory_of(&acme, &bob.id); alice.has_inventory_of(&acme, &eve.id); @@ -384,13 +367,8 @@ fn rad_id_conflict() { alice.connect(&bob).converge([&bob]); - test( - "examples/rad-clone.md", - working.join("bob"), - Some(&bob.home), - [], - ) - .unwrap(); + bob.fork(acme, working.join("bob")).unwrap(); + bob.announce(acme, bob.home.path()).unwrap(); alice.has_inventory_of(&acme, &bob.id); formula(&environment.tmp(), "examples/rad-id-conflict.md") @@ -705,16 +683,10 @@ fn rad_clean() { bob.connect(&alice).converge([&alice]); eve.connect(&alice).converge([&alice]); - test( - "examples/rad-clone.md", - working.join("bob"), - Some(&bob.home), - [], - ) - .unwrap(); - eve.handle.fetch(acme, alice.id, DEFAULT_TIMEOUT).unwrap(); + bob.fork(acme, bob.home.path()).unwrap(); + bob.announce(acme, bob.home.path()).unwrap(); bob.has_inventory_of(&acme, &alice.id); alice.has_inventory_of(&acme, &bob.id); eve.has_inventory_of(&acme, &alice.id); @@ -795,13 +767,9 @@ fn rad_clone_all() { bob.connect(&alice).converge([&alice]); eve.connect(&alice).converge([&alice]); - test( - "examples/rad-clone.md", - working.join("bob"), - Some(&bob.home), - [], - ) - .unwrap(); + // Fork and sync repo. + bob.fork(acme, bob.home.path()).unwrap(); + bob.announce(acme, bob.home.path()).unwrap(); bob.has_inventory_of(&acme, &alice.id); alice.has_inventory_of(&acme, &bob.id); @@ -1109,8 +1077,7 @@ fn test_cob_replication() { alice.connect(&bob); bob.routes_to(&[(rid, alice.id)]); - bob.rad("clone", &[rid.to_string().as_str()], working.path()) - .unwrap(); + bob.fork(rid, working.path()).unwrap(); // Wait for Alice to fetch the clone refs. events @@ -1307,8 +1274,7 @@ fn test_replication_via_seed() { let seed_events = seed.handle.events(); let alice_events = alice.handle.events(); - bob.rad("clone", &[rid.to_string().as_str()], working.join("bob")) - .unwrap(); + bob.fork(rid, working.join("bob")).unwrap(); alice.routes_to(&[(rid, alice.id), (rid, seed.id), (rid, bob.id)]); seed.routes_to(&[(rid, alice.id), (rid, seed.id), (rid, bob.id)]); @@ -1364,9 +1330,8 @@ fn rad_remote() { bob.connect(&alice); bob.routes_to(&[(rid, alice.id)]); - bob.rad("clone", &[rid.to_string().as_str()], &working) - .unwrap(); - + bob.fork(rid, bob.home.path()).unwrap(); + bob.announce(rid, bob.home.path()).unwrap(); alice.has_inventory_of(&rid, &bob.id); test( @@ -1611,14 +1576,7 @@ fn git_push_diverge() { let mut bob = bob.spawn(); bob.connect(&alice).converge([&alice]); - - test( - "examples/rad-clone.md", - working.join("bob"), - Some(&bob.home), - [], - ) - .unwrap(); + bob.fork(acme, working.join("bob")).unwrap(); alice.has_inventory_of(&acme, &bob.id); formula(&environment.tmp(), "examples/git/git-push-diverge.md") @@ -1659,16 +1617,7 @@ fn rad_push_and_pull_patches() { let mut bob = bob.spawn(); bob.connect(&alice).converge([&alice]); - - logger::init(log::Level::Debug); - - test( - "examples/rad-clone.md", - working.join("bob"), - Some(&bob.home), - [], - ) - .unwrap(); + bob.fork(acme, working.join("bob")).unwrap(); alice.has_inventory_of(&acme, &bob.id); formula(&environment.tmp(), "examples/rad-push-and-pull-patches.md") diff --git a/radicle-node/src/test/environment.rs b/radicle-node/src/test/environment.rs index c8e2f40f..c80c90e9 100644 --- a/radicle-node/src/test/environment.rs +++ b/radicle-node/src/test/environment.rs @@ -275,6 +275,20 @@ impl NodeHandle { self.rad("clone", &[rid.to_string().as_str()], cwd) } + /// Fork a repo. + pub fn fork>(&self, rid: Id, cwd: P) -> io::Result<()> { + self.clone(rid, &cwd)?; + self.rad("fork", &[rid.to_string().as_str()], &cwd)?; + self.announce(rid, &cwd)?; + + Ok(()) + } + + /// Announce a repo. + pub fn announce>(&self, rid: Id, cwd: P) -> io::Result<()> { + self.rad("sync", &[rid.to_string().as_str(), "--announce"], cwd) + } + /// Run a `rad` CLI command. pub fn rad>(&self, cmd: &str, args: &[&str], cwd: P) -> io::Result<()> { let cwd = cwd.as_ref(); @@ -295,6 +309,7 @@ impl NodeHandle { .env("RAD_PASSPHRASE", "radicle") .env("TZ", "UTC") .env("LANG", "C") + .env(radicle::cob::git::RAD_COMMIT_TIME, "1671125284") .envs(git::env::GIT_DEFAULT_CONFIG) .current_dir(cwd) .arg(cmd)