radicle_cli/terminal/
cob.rs1use radicle::{
2 Profile,
3 cob::{
4 self,
5 cache::{MigrateCallback, MigrateProgress},
6 store::access::{ReadOnly, WriteAs},
7 },
8 crypto,
9 prelude::NodeId,
10 profile,
11 storage::ReadRepository,
12};
13use radicle_term as term;
14
15use crate::terminal;
16
17pub const MIGRATION_HINT: &str = "run `rad cob migrate` to update your database";
19
20pub struct MigrateSpinner {
22 spinner: Option<term::Spinner>,
23}
24
25impl Default for MigrateSpinner {
26 fn default() -> Self {
28 Self { spinner: None }
29 }
30}
31
32impl MigrateCallback for MigrateSpinner {
33 fn progress(&mut self, progress: MigrateProgress) {
34 self.spinner
35 .get_or_insert_with(|| term::spinner("Migration in progress.."))
36 .message(format!(
37 "Migration {}/{} in progress.. ({}%)",
38 progress.migration.current(),
39 progress.migration.total(),
40 progress.rows.percentage()
41 ));
42
43 if progress.is_done()
44 && let Some(spinner) = self.spinner.take()
45 {
46 spinner.finish()
47 }
48 }
49}
50
51pub mod migrate {
53 use super::MigrateSpinner;
54
55 #[must_use]
57 pub fn spinner() -> MigrateSpinner {
58 MigrateSpinner::default()
59 }
60}
61
62pub fn patches<'a, Repo>(
64 profile: &Profile,
65 repository: &'a Repo,
66) -> Result<cob::patch::Cache<'a, Repo, ReadOnly, cob::cache::StoreReader>, anyhow::Error>
67where
68 Repo: ReadRepository + cob::Store<Namespace = NodeId>,
69{
70 profile.patches(repository).map_err(with_hint)
71}
72
73pub fn patches_mut<'a, 'b, Repo, Signer: crypto::Signer>(
77 profile: &Profile,
78 repository: &'a Repo,
79 signer: &'b Signer,
80) -> Result<cob::patch::Cache<'a, Repo, WriteAs<'b, Signer>, cob::cache::StoreWriter>, anyhow::Error>
81where
82 Repo: ReadRepository + cob::Store<Namespace = NodeId>,
83{
84 profile.patches_mut(repository, signer).map_err(with_hint)
85}
86
87pub fn issues<'a, Repo>(
89 profile: &Profile,
90 repository: &'a Repo,
91) -> Result<cob::issue::Cache<'a, Repo, ReadOnly, cob::cache::StoreReader>, anyhow::Error>
92where
93 Repo: ReadRepository + cob::Store<Namespace = NodeId>,
94{
95 profile.issues(repository).map_err(with_hint)
96}
97
98pub fn issues_mut<'a, 'b, Repo, Signer: crypto::Signer>(
102 profile: &Profile,
103 repository: &'a Repo,
104 signer: &'b Signer,
105) -> Result<cob::issue::Cache<'a, Repo, WriteAs<'b, Signer>, cob::cache::StoreWriter>, anyhow::Error>
106where
107 Repo: ReadRepository + cob::Store<Namespace = NodeId>,
108{
109 profile.issues_mut(repository, signer).map_err(with_hint)
110}
111
112fn with_hint(e: profile::Error) -> anyhow::Error {
114 #[allow(clippy::wildcard_enum_match_arm)]
117 match e {
118 profile::Error::CobsCache(cob::cache::Error::OutOfDate) => {
119 terminal::args::Error::with_hint(e, MIGRATION_HINT).into()
120 }
121 e => anyhow::Error::from(e),
122 }
123}