Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
heartwood crates radicle-cli src commands issue cache.rs
use std::ops::ControlFlow;

use radicle::Profile;
use radicle::cob::store::access::ReadOnly;
use radicle::issue::IssueId;
use radicle::storage::ReadStorage as _;
use radicle::storage::git::Repository;

use crate::terminal as term;

pub enum CacheMode<'a> {
    Storage,
    Repository {
        repository: &'a Repository,
    },
    Issue {
        id: IssueId,
        repository: &'a Repository,
    },
}

pub fn run(mode: CacheMode, profile: &Profile) -> anyhow::Result<()> {
    match mode {
        CacheMode::Storage => {
            let repos = profile.storage.repositories()?;
            for info in repos {
                term::info!("Caching all issues for {}", info.rid);
                cache(None, &profile.storage.repository(info.rid)?, profile)?
            }
        }
        CacheMode::Repository { repository: repo } => cache(None, repo, profile)?,
        CacheMode::Issue {
            id,
            repository: repo,
        } => cache(Some(id), repo, profile)?,
    }
    Ok(())
}

fn cache(id: Option<IssueId>, repository: &Repository, profile: &Profile) -> anyhow::Result<()> {
    let mut issues = {
        // NOTE: Since we require a cache that is writable, on top of a store that
        // is read-only, we can neither use [`term::cob::issues_mut`] nor [`term::cob::issues`]
        // since these convenience functions pair a writable cache with a writable
        // store, and respectively a read-only cache with a read-only store.

        let db = profile.cobs_db_mut()?;
        db.check_version()?;
        let store = radicle::cob::issue::Issues::open(repository, ReadOnly)?;

        radicle::cob::issue::Cache::open(store, db)
    };

    match id {
        Some(id) => {
            issues.write(&id)?;
            term::success!("Successfully cached issue `{id}`");
        }
        None => issues.write_all(|result, progress| {
            match result {
                Ok((id, _)) => term::success!(
                    "Successfully cached issue {id} ({}/{})",
                    progress.current(),
                    progress.total()
                ),
                Err(e) => term::warning(format!("Failed to retrieve issue: {e}")),
            };
            ControlFlow::Continue(())
        })?,
    }

    Ok(())
}