use std::path::Path;
use crate::app::doctor;
use crate::domain::model::Config;
use crate::domain::shell::Shell;
use crate::format::format_check_line;
use crate::shell_alias::add_shell_alias_conflicts;
use crate::{AppContext, CmdOutcome, CmdResult, OptionalContext, Spinner};
pub(crate) fn build_doctor_env_info(config: Option<&Config>) -> doctor::DoctorEnvInfo {
let mut info = doctor::DoctorEnvInfo::default();
#[cfg(windows)]
{
let p = crate::win_path::effective_search_path();
info.effective_search_path = Some(doctor::EffectiveSearchPathSummary {
from_process: p.from_process,
from_user_registry: p.from_user_registry,
from_system_registry: p.from_system_registry,
});
}
let clink_bin = std::env::current_exe()
.ok()
.and_then(|p| p.to_str().map(|s| s.to_string()))
.unwrap_or_else(|| "runex".to_string());
info.clink_export_for_drift_check = Some(crate::app::shell_export::export_script(
Shell::Clink,
&clink_bin,
config,
));
info.check_rcfile_markers = doctor::RcfileMarkerSelection::all();
info
}
pub(crate) fn handle(
config_flag: Option<&Path>,
path_prepend: Option<&Path>,
no_shell_aliases: bool,
verbose: bool,
strict: bool,
json: bool,
) -> CmdResult {
let ctx = AppContext::build_optional(config_flag, None, path_prepend, false);
let OptionalContext {
config_path,
config,
parse_error,
command_exists,
..
} = ctx;
let spinner = Spinner::start("Checking environment...");
let env_info = build_doctor_env_info(config.as_ref());
let mut result = doctor::diagnose(
&config_path,
config.as_ref(),
parse_error.as_deref(),
&env_info,
&command_exists,
);
if !no_shell_aliases {
add_shell_alias_conflicts(&mut result, config.as_ref());
}
let source = crate::infra::config_store::read_config_source(&config_path).ok();
if let Some(src) = source.as_deref() {
result.checks.extend(doctor::check_rejected_rules(src));
}
if strict {
if let Some(src) = source.as_deref() {
result.checks.extend(doctor::check_unknown_fields(src));
result.checks.extend(doctor::check_precache_deprecation(src));
}
if let Some(cfg) = config.as_ref() {
result.checks.extend(doctor::check_unreachable_duplicates(cfg));
}
}
spinner.stop();
if json {
println!("{}", serde_json::to_string_pretty(&result.checks)?);
} else {
for check in &result.checks {
println!("{}", format_check_line(check, verbose));
}
}
if !result.is_healthy() {
return Ok(CmdOutcome::ExitCode(1));
}
Ok(CmdOutcome::Ok)
}