use radicle::{
Profile,
cob::{
self,
cache::{MigrateCallback, MigrateProgress},
store::access::{ReadOnly, WriteAs},
},
prelude::NodeId,
profile,
storage::ReadRepository,
};
use radicle_term as term;
use crate::terminal;
pub const MIGRATION_HINT: &str = "run `rad cob migrate` to update your database";
pub struct MigrateSpinner {
spinner: Option<term::Spinner>,
}
impl Default for MigrateSpinner {
fn default() -> Self {
Self { spinner: None }
}
}
impl MigrateCallback for MigrateSpinner {
fn progress(&mut self, progress: MigrateProgress) {
self.spinner
.get_or_insert_with(|| term::spinner("Migration in progress.."))
.message(format!(
"Migration {}/{} in progress.. ({}%)",
progress.migration.current(),
progress.migration.total(),
progress.rows.percentage()
));
if progress.is_done() {
if let Some(spinner) = self.spinner.take() {
spinner.finish()
}
}
}
}
pub mod migrate {
use super::MigrateSpinner;
#[must_use]
pub fn spinner() -> MigrateSpinner {
MigrateSpinner::default()
}
}
pub fn patches<'a, Repo>(
profile: &Profile,
repository: &'a Repo,
) -> Result<cob::patch::Cache<'a, Repo, ReadOnly, cob::cache::StoreReader>, anyhow::Error>
where
Repo: ReadRepository + cob::Store<Namespace = NodeId>,
{
profile.patches(repository).map_err(with_hint)
}
pub fn patches_mut<'a, 'b, Repo, Signer>(
profile: &Profile,
repository: &'a Repo,
signer: &'b Signer,
) -> Result<cob::patch::Cache<'a, Repo, WriteAs<'b, Signer>, cob::cache::StoreWriter>, anyhow::Error>
where
Repo: ReadRepository + cob::Store<Namespace = NodeId>,
{
profile.patches_mut(repository, signer).map_err(with_hint)
}
pub fn issues<'a, Repo>(
profile: &Profile,
repository: &'a Repo,
) -> Result<cob::issue::Cache<'a, Repo, ReadOnly, cob::cache::StoreReader>, anyhow::Error>
where
Repo: ReadRepository + cob::Store<Namespace = NodeId>,
{
profile.issues(repository).map_err(with_hint)
}
pub fn issues_mut<'a, 'b, Repo, Signer>(
profile: &Profile,
repository: &'a Repo,
signer: &'b Signer,
) -> Result<cob::issue::Cache<'a, Repo, WriteAs<'b, Signer>, cob::cache::StoreWriter>, anyhow::Error>
where
Repo: ReadRepository + cob::Store<Namespace = NodeId>,
{
profile.issues_mut(repository, signer).map_err(with_hint)
}
fn with_hint(e: profile::Error) -> anyhow::Error {
#[allow(clippy::wildcard_enum_match_arm)]
match e {
profile::Error::CobsCache(cob::cache::Error::OutOfDate) => {
terminal::args::Error::with_hint(e, MIGRATION_HINT).into()
}
e => anyhow::Error::from(e),
}
}