1pub(crate) mod args;
2pub(crate) use args::Error;
3
4pub mod format;
5pub mod io;
6pub use io::signer;
7pub mod cob;
8pub mod comment;
9pub mod highlight;
10pub mod issue;
11pub mod json;
12pub mod patch;
13pub mod upload_pack;
14
15pub use radicle_term::*;
16
17use radicle::profile::{Home, Profile};
18
19pub trait Context {
21 fn profile(&self) -> Result<Profile, anyhow::Error>;
23 fn home(&self) -> Result<Home, std::io::Error>;
25}
26
27impl Context for Profile {
28 fn profile(&self) -> Result<Profile, anyhow::Error> {
29 Ok(self.clone())
30 }
31
32 fn home(&self) -> Result<Home, std::io::Error> {
33 Ok(self.home.clone())
34 }
35}
36
37pub struct DefaultContext;
39
40impl Context for DefaultContext {
41 fn home(&self) -> Result<Home, std::io::Error> {
42 radicle::profile::home()
43 }
44
45 fn profile(&self) -> Result<Profile, anyhow::Error> {
46 match Profile::load() {
47 Ok(profile) => Ok(profile),
48 Err(radicle::profile::Error::NotFound(path)) => Err(args::Error::with_hint(
49 anyhow::anyhow!("Radicle profile not found in '{}'.", path.display()),
50 "To setup your radicle profile, run `rad auth`.",
51 )
52 .into()),
53 Err(radicle::profile::Error::LoadConfig(e)) => Err(e.into()),
54 Err(e) => Err(anyhow::anyhow!("Could not load radicle profile: {e}")),
55 }
56 }
57}
58
59pub fn fail(error: &anyhow::Error) {
60 let err = error.to_string();
61 let err = err.trim_end();
62
63 for line in err.lines() {
64 io::error(line);
65 }
66
67 if let Some(e) = error.downcast_ref::<radicle::node::Error>() {
69 if e.is_connection_err() {
70 io::hint("to start your node, run `rad node start`.");
71 }
72 }
73 if let Some(Error::WithHint { hint, .. }) = error.downcast_ref::<Error>() {
74 io::hint(hint);
75 }
76}