use std::path::{Path, PathBuf};
pub(crate) fn make_command_exists<'a>(
path_prepend: Option<&'a Path>,
precache_fingerprint: Option<&str>,
) -> impl Fn(&str) -> bool + 'a {
use crate::app::precache;
let hint = precache_fingerprint.and_then(precache::load_cache);
let cache = std::cell::RefCell::new(std::collections::HashMap::<String, bool>::new());
#[cfg(windows)]
let effective_path = crate::win_path::effective_search_path();
move |cmd: &str| -> bool {
if cmd.contains('/') || cmd.contains('\\') || cmd.contains(':') {
return false;
}
if let Some(&cached) = cache.borrow().get(cmd) {
return cached;
}
if let Some(ref h) = hint {
if let Some(&cached) = h.commands.get(cmd) {
if cached {
cache.borrow_mut().insert(cmd.to_owned(), true);
return true;
}
}
}
let live_check = |c: &str| -> bool {
#[cfg(windows)]
{
let cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
which::which_in(c, Some(&effective_path.combined), &cwd).is_ok()
}
#[cfg(not(windows))]
{
which::which(c).is_ok()
}
};
let exists = if let Some(dir) = path_prepend {
if dir.join(cmd).is_file() {
true
} else {
#[cfg(windows)]
{
if dir.join(format!("{cmd}.exe")).is_file() {
true
} else {
live_check(cmd)
}
}
#[cfg(not(windows))]
{
live_check(cmd)
}
}
} else {
live_check(cmd)
};
cache.borrow_mut().insert(cmd.to_owned(), exists);
exists
}
}
pub(crate) fn make_command_exists_owned(
path_prepend: Option<PathBuf>,
precache_fingerprint: Option<String>,
) -> impl Fn(&str) -> bool + 'static {
use crate::app::precache;
let hint = precache_fingerprint
.as_deref()
.and_then(precache::load_cache);
let cache = std::cell::RefCell::new(std::collections::HashMap::<String, bool>::new());
#[cfg(windows)]
let effective_path = crate::win_path::effective_search_path();
move |cmd: &str| -> bool {
if cmd.contains('/') || cmd.contains('\\') || cmd.contains(':') {
return false;
}
if let Some(&cached) = cache.borrow().get(cmd) {
return cached;
}
if let Some(ref h) = hint {
if let Some(&cached) = h.commands.get(cmd) {
if cached {
cache.borrow_mut().insert(cmd.to_owned(), true);
return true;
}
}
}
let live_check = |c: &str| -> bool {
#[cfg(windows)]
{
let cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
which::which_in(c, Some(&effective_path.combined), &cwd).is_ok()
}
#[cfg(not(windows))]
{
which::which(c).is_ok()
}
};
let exists = if let Some(dir) = path_prepend.as_deref() {
#[cfg(windows)]
let direct = dir.join(cmd).is_file()
|| dir.join(format!("{cmd}.exe")).is_file();
#[cfg(not(windows))]
let direct = dir.join(cmd).is_file();
direct || live_check(cmd)
} else {
live_check(cmd)
};
cache.borrow_mut().insert(cmd.to_owned(), exists);
exists
}
}