cli: allow multiple RIDs for `rad seed`
Closes rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/issue/f9ec8a2
This commit is contained in:
parent
a90aabb1fe
commit
6bbe919c4b
|
|
@ -0,0 +1,11 @@
|
||||||
|
It is possible to use the `rad seed` command to specify multiple RIDs at the
|
||||||
|
same time, where each repository specified will be fetched (unless `--no-fetch`
|
||||||
|
is used):
|
||||||
|
|
||||||
|
```
|
||||||
|
$ rad seed rad:z3Rry7rpdWuGpfjPYGzdJKQADsoNW rad:z3zTnCfi6cVSZG8eCGn6AMDypgAPm
|
||||||
|
✓ Seeding policy updated for rad:z3Rry7rpdWuGpfjPYGzdJKQADsoNW with scope 'all'
|
||||||
|
✓ Fetching rad:z3Rry7rpdWuGpfjPYGzdJKQADsoNW from z6Mkt67…v4N1tRk@[..]
|
||||||
|
✓ Seeding policy updated for rad:z3zTnCfi6cVSZG8eCGn6AMDypgAPm with scope 'all'
|
||||||
|
✓ Fetching rad:z3zTnCfi6cVSZG8eCGn6AMDypgAPm from z6Mkt67…v4N1tRk@[..]
|
||||||
|
```
|
||||||
|
|
@ -4,6 +4,7 @@ use std::time;
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
|
||||||
|
use nonempty::NonEmpty;
|
||||||
use radicle::node::policy;
|
use radicle::node::policy;
|
||||||
use radicle::node::policy::{Policy, Scope};
|
use radicle::node::policy::{Policy, Scope};
|
||||||
use radicle::node::Handle;
|
use radicle::node::Handle;
|
||||||
|
|
@ -22,7 +23,7 @@ pub const HELP: Help = Help {
|
||||||
usage: r#"
|
usage: r#"
|
||||||
Usage
|
Usage
|
||||||
|
|
||||||
rad seed [<rid>] [--[no-]fetch] [--from <nid>] [--scope <scope>] [<option>...]
|
rad seed [<rid>...] [--[no-]fetch] [--from <nid>] [--scope <scope>] [<option>...]
|
||||||
|
|
||||||
The `seed` command, when no Repository ID (<rid>) is provided, will list the
|
The `seed` command, when no Repository ID (<rid>) is provided, will list the
|
||||||
repositories being seeded.
|
repositories being seeded.
|
||||||
|
|
@ -49,7 +50,7 @@ Options
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Operation {
|
pub enum Operation {
|
||||||
Seed {
|
Seed {
|
||||||
rid: RepoId,
|
rids: NonEmpty<RepoId>,
|
||||||
fetch: bool,
|
fetch: bool,
|
||||||
seeds: BTreeSet<NodeId>,
|
seeds: BTreeSet<NodeId>,
|
||||||
timeout: time::Duration,
|
timeout: time::Duration,
|
||||||
|
|
@ -69,7 +70,7 @@ impl Args for Options {
|
||||||
use lexopt::prelude::*;
|
use lexopt::prelude::*;
|
||||||
|
|
||||||
let mut parser = lexopt::Parser::from_args(args);
|
let mut parser = lexopt::Parser::from_args(args);
|
||||||
let mut rid: Option<RepoId> = None;
|
let mut rids: Vec<RepoId> = Vec::new();
|
||||||
let mut scope: Option<Scope> = None;
|
let mut scope: Option<Scope> = None;
|
||||||
let mut fetch: Option<bool> = None;
|
let mut fetch: Option<bool> = None;
|
||||||
let mut timeout = time::Duration::from_secs(9);
|
let mut timeout = time::Duration::from_secs(9);
|
||||||
|
|
@ -79,7 +80,8 @@ impl Args for Options {
|
||||||
while let Some(arg) = parser.next()? {
|
while let Some(arg) = parser.next()? {
|
||||||
match &arg {
|
match &arg {
|
||||||
Value(val) => {
|
Value(val) => {
|
||||||
rid = Some(term::args::rid(val)?);
|
let rid = term::args::rid(val)?;
|
||||||
|
rids.push(rid);
|
||||||
}
|
}
|
||||||
Long("scope") => {
|
Long("scope") => {
|
||||||
let val = parser.value()?;
|
let val = parser.value()?;
|
||||||
|
|
@ -113,9 +115,9 @@ impl Args for Options {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let op = match rid {
|
let op = match NonEmpty::from_vec(rids) {
|
||||||
Some(rid) => Operation::Seed {
|
Some(rids) => Operation::Seed {
|
||||||
rid,
|
rids,
|
||||||
fetch: fetch.unwrap_or(true),
|
fetch: fetch.unwrap_or(true),
|
||||||
scope: scope.unwrap_or(Scope::All),
|
scope: scope.unwrap_or(Scope::All),
|
||||||
timeout,
|
timeout,
|
||||||
|
|
@ -134,24 +136,28 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
|
|
||||||
match options.op {
|
match options.op {
|
||||||
Operation::Seed {
|
Operation::Seed {
|
||||||
rid,
|
rids,
|
||||||
fetch,
|
fetch,
|
||||||
scope,
|
scope,
|
||||||
timeout,
|
timeout,
|
||||||
seeds,
|
seeds,
|
||||||
} => {
|
} => {
|
||||||
|
for rid in rids {
|
||||||
update(rid, scope, &mut node, &profile)?;
|
update(rid, scope, &mut node, &profile)?;
|
||||||
|
|
||||||
if fetch && node.is_running() {
|
if fetch && node.is_running() {
|
||||||
sync::fetch(
|
if let Err(e) = sync::fetch(
|
||||||
rid,
|
rid,
|
||||||
SyncSettings::default()
|
SyncSettings::default()
|
||||||
.seeds(seeds)
|
.seeds(seeds.clone())
|
||||||
.timeout(timeout)
|
.timeout(timeout)
|
||||||
.with_profile(&profile),
|
.with_profile(&profile),
|
||||||
&mut node,
|
&mut node,
|
||||||
&profile,
|
&profile,
|
||||||
)?;
|
) {
|
||||||
|
term::error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Operation::List => seeding(&profile)?,
|
Operation::List => seeding(&profile)?,
|
||||||
|
|
|
||||||
|
|
@ -1347,6 +1347,29 @@ fn rad_seed_and_follow() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rad_seed_many() {
|
||||||
|
let mut environment = Environment::new();
|
||||||
|
let alice = environment.node(Config::test(Alias::new("alice")));
|
||||||
|
let mut bob = environment.node(Config::test(Alias::new("bob")));
|
||||||
|
// Bob creates two projects that Alice seeds in the test
|
||||||
|
let _ = bob.project("heartwood", "Radicle Heartwood Protocol & Stack");
|
||||||
|
let _ = bob.project("nixpkgs", "Home for Nix Packages");
|
||||||
|
let working = tempfile::tempdir().unwrap();
|
||||||
|
let alice = alice.spawn();
|
||||||
|
let mut bob = bob.spawn();
|
||||||
|
|
||||||
|
bob.connect(&alice).converge([&alice]);
|
||||||
|
|
||||||
|
test(
|
||||||
|
"examples/rad-seed-many.md",
|
||||||
|
working.path(),
|
||||||
|
Some(&alice.home),
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rad_unseed() {
|
fn rad_unseed() {
|
||||||
let mut environment = Environment::new();
|
let mut environment = Environment::new();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue