use anyhow::{Context, Result};
use console::style;
use std::path::Path;
pub fn run(path: &Path) -> Result<()> {
let repo_path = path
.canonicalize()
.with_context(|| format!("Path does not exist: {}", path.display()))?;
println!("\nRepotoire Status\n");
let cache_dir = crate::cache::cache_dir(&repo_path);
let db_path = crate::cache::graph_db_path(&repo_path);
let findings_path = crate::cache::findings_cache_path(&repo_path);
println!(" Repository: {}", style(repo_path.display()).cyan());
println!(" Cache: {}", style(cache_dir.display()).dim());
println!();
let has_findings = findings_path.exists();
let has_db = db_path.exists();
if has_findings || has_db {
println!(" {} Analysis data found", style("[OK]").green());
let stats_path = crate::cache::graph_stats_path(&repo_path);
if let Ok(stats) = std::fs::read_to_string(&stats_path)
.ok()
.and_then(|json| serde_json::from_str::<serde_json::Value>(&json).ok())
.ok_or(())
{
let file_count = stats
.get("total_files")
.and_then(|v| v.as_i64())
.unwrap_or(0);
let func_count = stats
.get("total_functions")
.and_then(|v| v.as_i64())
.unwrap_or(0);
let class_count = stats
.get("total_classes")
.and_then(|v| v.as_i64())
.unwrap_or(0);
println!(
" {} files, {} functions, {} classes",
style(file_count).cyan(),
style(func_count).cyan(),
style(class_count).cyan()
);
}
use super::analyze::output::CacheLoadOutcome;
let outcome = super::analyze::output::load_cached_findings_outcome_from(&findings_path);
match outcome {
CacheLoadOutcome::Findings(findings) => {
use crate::models::Severity;
let total = findings.len();
let critical = findings
.iter()
.filter(|f| f.severity == Severity::Critical)
.count();
let high = findings
.iter()
.filter(|f| f.severity == Severity::High)
.count();
println!(
" {} findings ({} critical, {} high)",
style(total).cyan(),
style(critical).red(),
style(high).yellow()
);
}
outcome @ CacheLoadOutcome::Corrupt { .. } => {
if let Some(msg) = outcome.user_warning() {
println!(" {}", msg);
}
anyhow::bail!(
"findings cache is corrupt; re-run `repotoire analyze` to regenerate it"
);
}
CacheLoadOutcome::Missing | CacheLoadOutcome::VersionMismatch { .. } => {
}
}
} else {
println!(
" {} No analysis yet. Run {}",
style("[--]").dim(),
style("repotoire analyze").cyan()
);
}
println!();
println!(" API Keys:");
let has_openai = std::env::var("OPENAI_API_KEY").is_ok();
let has_anthropic = std::env::var("ANTHROPIC_API_KEY").is_ok();
if has_openai {
println!(" {} OPENAI_API_KEY", style("[OK]").green());
} else {
println!(" {} OPENAI_API_KEY", style("[--]").dim());
}
if has_anthropic {
println!(" {} ANTHROPIC_API_KEY", style("[OK]").green());
} else {
println!(" {} ANTHROPIC_API_KEY", style("[--]").dim());
}
if !has_openai && !has_anthropic {
println!("\n Set an API key to enable AI fixes (BYOK)");
}
println!();
Ok(())
}