use anyhow::Result;
use clap::{Args, ValueEnum};
use crate::sanity::{self, SanityOptions};
use crate::{commands::doctor, config};
#[derive(Debug, Clone, Copy, Default, ValueEnum)]
pub enum DoctorFormat {
#[default]
Text,
Json,
}
#[derive(Args)]
pub struct DoctorArgs {
#[arg(long, conflicts_with = "no_sanity_checks")]
pub auto_fix: bool,
#[arg(long, conflicts_with = "auto_fix")]
pub no_sanity_checks: bool,
#[arg(long, value_enum, default_value = "text")]
pub format: DoctorFormat,
}
pub fn handle_doctor(args: DoctorArgs) -> Result<()> {
let resolved = config::resolve_from_cwd_for_doctor()?;
if !args.no_sanity_checks {
let options = SanityOptions {
auto_fix: args.auto_fix,
skip: false,
non_interactive: false, };
let sanity_result = sanity::run_sanity_checks(&resolved, &options)?;
if !sanity_result.auto_fixes.is_empty() {
log::info!(
"Sanity checks applied {} fix(es):",
sanity_result.auto_fixes.len()
);
for fix in &sanity_result.auto_fixes {
log::info!(" - {}", fix);
}
}
if !sanity_result.needs_attention.is_empty() {
log::warn!(
"Sanity checks found {} issue(s) needing attention:",
sanity_result.needs_attention.len()
);
for issue in &sanity_result.needs_attention {
match issue.severity {
sanity::IssueSeverity::Warning => log::warn!(" - {}", issue.message),
sanity::IssueSeverity::Error => log::error!(" - {}", issue.message),
}
}
}
}
let report = doctor::run_doctor(&resolved, args.auto_fix)?;
match args.format {
DoctorFormat::Text => {
doctor::print_doctor_report_text(&report);
}
DoctorFormat::Json => {
println!("{}", serde_json::to_string_pretty(&report)?);
}
}
if report.success {
Ok(())
} else {
anyhow::bail!("Doctor check failed: one or more critical issues found")
}
}