use std::ffi::OsStr;
use std::path::PathBuf;
use crate::{constant::TOOLCHAIN_FILE, utils::trimmed_or_none};
pub fn resolve_toolchain_file() -> Option<PathBuf> {
let current_dir = std::env::current_dir().ok();
std::iter::successors(current_dir.as_deref(), |prev| prev.parent())
.find_map(|dir| Some(dir.join(TOOLCHAIN_FILE)).filter(|p| p.is_file()))
}
pub fn detect_pinned_toolchain() -> Option<String> {
resolve_toolchain_file()
.and_then(|path| {
std::fs::read_to_string(path)
.map(|s| trimmed_or_none(&s).map(str::to_owned))
.ok()
})
.flatten()
}
pub fn detect_default_toolchain() -> Option<String> {
let default_file = crate::moonup_home().join("default");
std::fs::read_to_string(default_file)
.map(|s| trimmed_or_none(&s).map(str::to_owned))
.ok()
.flatten()
}
pub fn detect_active_toolchain() -> PathBuf {
let active = detect_active_toolchainspec();
crate::moonup_home().join("toolchains").join(active)
}
pub fn detect_active_toolchainspec() -> String {
detect_pinned_toolchain()
.or(detect_default_toolchain())
.unwrap_or("latest".to_string())
}
pub fn resolve_exe<T, U>(binary_name: T, paths: U) -> Option<PathBuf>
where
T: AsRef<OsStr>,
U: AsRef<OsStr>,
{
#[cfg(target_os = "windows")]
if std::env::var("PATHEXT").is_err() {
unsafe {
std::env::set_var("PATHEXT", crate::constant::DEFAULT_PATHEXT);
};
}
which::which_in_global(binary_name, Some(paths))
.and_then(|mut i| i.next().ok_or(which::Error::CannotFindBinaryPath))
.ok()
}
pub fn resolve_file<T, U>(file_name: T, paths: U) -> Option<PathBuf>
where
T: AsRef<OsStr>,
U: AsRef<OsStr>,
{
let file_name = file_name.as_ref();
std::env::split_paths(paths.as_ref())
.map(|path| path.join(file_name))
.find(|path| path.is_file())
}