use crate::platform::PerlInterpreterResult;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::{LazyLock, Mutex};
use std::time::SystemTime;
#[derive(Debug, Clone, PartialEq, Eq)]
struct PerlBinaryFingerprint {
len: u64,
modified: Option<SystemTime>,
}
static PERL_VERSION_CACHE: LazyLock<
Mutex<HashMap<PathBuf, (PerlBinaryFingerprint, Option<String>)>>,
> = LazyLock::new(|| Mutex::new(HashMap::new()));
fn perl_binary_fingerprint(perl_path: &Path) -> Option<PerlBinaryFingerprint> {
let metadata = std::fs::metadata(perl_path).ok()?;
let modified = metadata.modified().ok();
Some(PerlBinaryFingerprint { len: metadata.len(), modified })
}
fn detect_perl_version_cached(perl_path: &Path) -> Option<String> {
let fingerprint = perl_binary_fingerprint(perl_path)?;
if let Ok(cache) = PERL_VERSION_CACHE.lock()
&& let Some((cached_fingerprint, cached_version)) = cache.get(perl_path)
&& *cached_fingerprint == fingerprint
{
return cached_version.clone();
}
let cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
let oracle =
perl_lsp_rs_core::config::PerlOracleEnv::for_version_probe(perl_path.to_path_buf(), cwd);
let detected_version =
oracle.into_command().arg("-e").arg("print $]").output().ok().and_then(|out| {
if out.status.success() { String::from_utf8(out.stdout).ok() } else { None }
});
if let Ok(mut cache) = PERL_VERSION_CACHE.lock() {
cache.insert(perl_path.to_path_buf(), (fingerprint, detected_version.clone()));
}
detected_version
}
pub(super) fn detect_perl_info() -> String {
match crate::platform::find_perl_interpreter_cached(None) {
PerlInterpreterResult::ConfiguredPath(path)
| PerlInterpreterResult::FoundOnPath(path)
| PerlInterpreterResult::FoundViaFallback { path, .. } => {
match detect_perl_version_cached(&path) {
Some(v) if !v.trim().is_empty() => {
format!("Found Perl at {} (version {})", path.display(), v.trim())
}
_ => format!("Found Perl at {}", path.display()),
}
}
PerlInterpreterResult::NotFound { .. } => {
#[cfg(windows)]
{
"Perl was not found on PATH. Install Perl from https://strawberryperl.com \
or set a custom path."
.to_string()
}
#[cfg(not(windows))]
{
"Perl was not found on PATH. Install Perl via your package manager \
(e.g. `apt install perl` or `brew install perl`) or set a custom path."
.to_string()
}
}
}
}