diff --git a/radicle-cli/src/commands/issue.rs b/radicle-cli/src/commands/issue.rs index c2bc8214a..063e72bcc 100644 --- a/radicle-cli/src/commands/issue.rs +++ b/radicle-cli/src/commands/issue.rs @@ -13,7 +13,7 @@ use radicle::cob::issue::{CloseReason, State}; use radicle::cob::thread; use radicle::crypto::Signer; use radicle::issue::cache::Issues as _; -use radicle::prelude::Did; +use radicle::prelude::{Did, RepoId}; use radicle::profile; use radicle::storage; use radicle::storage::{ReadRepository, WriteRepository, WriteStorage}; @@ -69,6 +69,7 @@ Show options Options + --repo Operate on the given repository (default: cwd) --no-announce Don't announce issue to peers --header Show only the issue header, hiding the comments -q, --quiet Don't print anything @@ -167,6 +168,7 @@ pub struct LabelOptions { #[derive(Debug)] pub struct Options { pub op: Operation, + pub repo: Option, pub announce: bool, pub quiet: bool, } @@ -194,6 +196,7 @@ impl Args for Options { let mut debug = false; let mut assign_opts = AssignOptions::default(); let mut label_opts = LabelOptions::default(); + let mut repo = None; while let Some(arg) = parser.next()? { match arg { @@ -337,6 +340,12 @@ impl Args for Options { Long("quiet") | Short('q') => { quiet = true; } + Long("repo") => { + let val = parser.value()?; + let rid = term::args::rid(&val)?; + + repo = Some(rid); + } Value(val) if op.is_none() => match val.to_string_lossy().as_ref() { "c" | "comment" => op = Some(OperationName::Comment), @@ -412,6 +421,7 @@ impl Args for Options { Ok(( Options { op, + repo, announce, quiet, }, @@ -423,7 +433,11 @@ impl Args for Options { pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { let profile = ctx.profile()?; let signer = term::signer(&profile)?; - let (_, rid) = radicle::rad::cwd()?; + let rid = if let Some(rid) = options.repo { + rid + } else { + radicle::rad::cwd().map(|(_, rid)| rid)? + }; let repo = profile.storage.repository_mut(rid)?; let announce = options.announce && matches!( diff --git a/radicle-cli/src/commands/issue/cache.rs b/radicle-cli/src/commands/issue/cache.rs index 8582bf55f..65da84e6f 100644 --- a/radicle-cli/src/commands/issue/cache.rs +++ b/radicle-cli/src/commands/issue/cache.rs @@ -16,10 +16,13 @@ pub fn run(id: Option, repository: &Repository, profile: &Profile) -> a } None => issues.write_all(|result, progress| { match result { - Ok((id, _)) => term::success!("Successfully cached issue `{id}`"), + Ok((id, _)) => term::success!( + "Successfully cached issue {id} ({}/{})", + progress.seen(), + progress.total() + ), Err(e) => term::warning(format!("Failed to retrieve issue: {e}")), }; - term::info!("Cached {} of {}", progress.seen(), progress.total()); ControlFlow::Continue(()) })?, } diff --git a/radicle-cli/src/commands/patch.rs b/radicle-cli/src/commands/patch.rs index 6f4b06c48..1cc22c93a 100644 --- a/radicle-cli/src/commands/patch.rs +++ b/radicle-cli/src/commands/patch.rs @@ -145,6 +145,7 @@ Checkout options Other options + --repo Operate on the given repository (default: cwd) --[no-]announce Announce changes made to the network -q, --quiet Quiet output --help Print help @@ -278,6 +279,7 @@ impl Operation { #[derive(Debug)] pub struct Options { pub op: Operation, + pub repo: Option, pub announce: bool, pub verbose: bool, pub quiet: bool, @@ -309,6 +311,7 @@ impl Args for Options { let mut label_opts = LabelOptions::default(); let mut review_op = review::Operation::default(); let mut base_id = None; + let mut repo = None; while let Some(arg) = parser.next()? { match arg { @@ -503,6 +506,12 @@ impl Args for Options { Long("quiet") | Short('q') => { quiet = true; } + Long("repo") => { + let val = parser.value()?; + let rid = term::args::rid(&val)?; + + repo = Some(rid); + } Long("help") => { return Err(Error::HelpManual { name: "rad-patch" }.into()); } @@ -631,6 +640,7 @@ impl Args for Options { Ok(( Options { op, + repo, verbose, quiet, announce, @@ -643,11 +653,16 @@ impl Args for Options { } pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { - let (workdir, id) = radicle::rad::cwd() - .map_err(|_| anyhow!("this command must be run in the context of a repository"))?; + let (workdir, rid) = if let Some(rid) = options.repo { + (None, rid) + } else { + radicle::rad::cwd() + .map(|(workdir, rid)| (Some(workdir), rid)) + .map_err(|_| anyhow!("this command must be run in the context of a repository"))? + }; let profile = ctx.profile()?; - let repository = profile.storage.repository(id)?; + let repository = profile.storage.repository(rid)?; let announce = options.announce && options.op.is_announce(); transport::local::register(profile.storage.clone()); @@ -673,7 +688,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { options.verbose, &profile, &repository, - &workdir, + workdir.as_ref(), )?; } Operation::Diff { @@ -697,6 +712,10 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { .as_ref() .map(|base| base.resolve(&repository.backend)) .transpose()?; + let workdir = workdir.ok_or(anyhow!( + "this command must be run from a repository checkout" + ))?; + update::run( patch_id, base_id, @@ -728,6 +747,9 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { .map(|rev| rev.resolve::(&repository.backend)) .transpose()? .map(patch::RevisionId::from); + let workdir = workdir.ok_or(anyhow!( + "this command must be run from a repository checkout" + ))?; checkout::run( &patch::PatchId::from(patch_id), revision_id, @@ -798,7 +820,9 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { let patch = patches .get(&patch_id)? .ok_or_else(|| anyhow!("patch {patch_id} not found"))?; - + let workdir = workdir.ok_or(anyhow!( + "this command must be run from a repository checkout" + ))?; radicle::rad::setup_patch_upstream(&patch_id, *patch.head(), &workdir, true)?; } Operation::Cache { patch_id } => { @@ -811,7 +835,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> { if announce { let mut node = Node::new(profile.socket()); - node::announce(id, &mut node)?; + node::announce(rid, &mut node)?; } Ok(()) } diff --git a/radicle-cli/src/commands/patch/cache.rs b/radicle-cli/src/commands/patch/cache.rs index 0c80a2f84..5cbf77a55 100644 --- a/radicle-cli/src/commands/patch/cache.rs +++ b/radicle-cli/src/commands/patch/cache.rs @@ -16,10 +16,13 @@ pub fn run(id: Option, repository: &Repository, profile: &Profile) -> a } None => patches.write_all(|result, progress| { match result { - Ok((id, _)) => term::success!("Successfully cached patch `{id}`"), + Ok((id, _)) => term::success!( + "Successfully cached patch {id} ({}/{})", + progress.seen(), + progress.total() + ), Err(e) => term::warning(format!("Failed to retrieve patch: {e}")), }; - term::info!("Cached {} of {}", progress.seen(), progress.total()); ControlFlow::Continue(()) })?, } diff --git a/radicle-cli/src/commands/patch/show.rs b/radicle-cli/src/commands/patch/show.rs index c187c9e14..d4d177bf2 100644 --- a/radicle-cli/src/commands/patch/show.rs +++ b/radicle-cli/src/commands/patch/show.rs @@ -30,8 +30,7 @@ pub fn run( verbose: bool, profile: &Profile, stored: &Repository, - // TODO: Should be optional. - workdir: &git::raw::Repository, + workdir: Option<&git::raw::Repository>, ) -> anyhow::Result<()> { let patches = profile.patches(stored)?; let Some(patch) = patches.get(patch_id)? else { @@ -42,7 +41,7 @@ pub fn run( println!("{:#?}", patch); return Ok(()); } - term::patch::show(&patch, patch_id, verbose, stored, Some(workdir), profile)?; + term::patch::show(&patch, patch_id, verbose, stored, workdir, profile)?; if diff { term::blank();