use std::collections::BTreeMap;
use aristo_core::canon::{CanonCatalogue, CanonError};
use crate::commands::index::workspace_or_error;
use crate::{CliError, CliResult};
const CATALOGUE_REL: &str = ".aristo/catalogue.json";
pub(crate) fn run() -> CliResult<()> {
let ws = workspace_or_error()?;
let client = super::required_client("canon catalogue", &ws.root)?;
let catalogue = client.catalogue().map_err(canon_error_to_cli)?;
let aristo_dir = ws.aristo_dir();
std::fs::create_dir_all(&aristo_dir).map_err(CliError::Io)?;
let out_path = aristo_dir.join("catalogue.json");
let json = serde_json::to_string_pretty(&catalogue).map_err(|e| CliError::Other {
message: format!("serializing catalogue: {e}"),
exit_code: 1,
})?;
std::fs::write(&out_path, json).map_err(CliError::Io)?;
print_summary(&catalogue);
Ok(())
}
fn print_summary(catalogue: &CanonCatalogue) {
let total = catalogue.entries.len();
println!(
"ok: downloaded {total} canon entr{} to {CATALOGUE_REL} (gitignored local snapshot)",
if total == 1 { "y" } else { "ies" }
);
if total == 0 {
println!(
" note: the catalogue is empty — this server has no canon corpus configured \
(check `aristo auth status` for which server this checkout resolves to)."
);
return;
}
let backed = catalogue
.entries
.iter()
.filter(|e| e.tier_label() == "aristos")
.count();
println!(
" backed (aristos): {backed} · unbacked (kanon): {}",
total - backed
);
let mut by_category: BTreeMap<&str, usize> = BTreeMap::new();
for e in &catalogue.entries {
*by_category.entry(e.category.as_str()).or_default() += 1;
}
println!(" by category:");
for (cat, n) in &by_category {
println!(" {cat}: {n}");
}
println!(" read/search the full snapshot at {CATALOGUE_REL}");
}
fn canon_error_to_cli(e: CanonError) -> CliError {
CliError::Other {
message: format!("canon catalogue error: {e}"),
exit_code: 1,
}
}