#![forbid(unsafe_code)]
use std::fs;
use std::path::Path;
use super::paths::{
detect_stale_wrapper_scripts, discover_path_binaries, legacy_installer_conflicts,
resolve_active_binary,
};
#[derive(Debug, Clone, PartialEq, Eq)]
#[allow(clippy::struct_excessive_bools)]
pub struct InstallHealthReport {
pub active_binary: Option<String>,
pub path_binaries: Vec<String>,
pub has_path_shadowing: bool,
pub has_duplicate_installs: bool,
pub stale_wrapper_scripts: Vec<String>,
pub has_mismatched_wheel_binary_versions: bool,
pub legacy_installer_conflicts: Vec<String>,
pub active_binary_missing: bool,
pub broken_symlink_active_binary: bool,
}
#[must_use]
pub fn install_health_report(
path_value: &str,
bin_override: Option<&str>,
wheel_version: Option<&str>,
runtime_version: &str,
) -> InstallHealthReport {
let mut path_binaries = discover_path_binaries(path_value);
path_binaries.dedup();
let active_binary = resolve_active_binary(path_value, bin_override);
let has_path_shadowing = path_binaries.len() > 1;
let has_duplicate_installs = path_binaries.iter().any(|path| path.contains(".cargo"))
&& path_binaries.iter().any(|path| path.contains("site-packages"));
let stale_wrapper_scripts = detect_stale_wrapper_scripts(path_value);
let has_mismatched_wheel_binary_versions =
wheel_version.is_some_and(|version| version != runtime_version);
let legacy_installer_conflicts = legacy_installer_conflicts(path_value);
let active_binary_missing =
active_binary.as_deref().is_some_and(|path| !Path::new(path).exists());
let broken_symlink_active_binary = active_binary.as_deref().is_some_and(|path| {
let p = Path::new(path);
fs::symlink_metadata(p).map(|meta| meta.file_type().is_symlink()).unwrap_or(false)
&& fs::metadata(p).is_err()
});
InstallHealthReport {
active_binary,
path_binaries,
has_path_shadowing,
has_duplicate_installs,
stale_wrapper_scripts,
has_mismatched_wheel_binary_versions,
legacy_installer_conflicts,
active_binary_missing,
broken_symlink_active_binary,
}
}