use std::path::PathBuf;
use std::process::Command;
pub const ENV_SKIP_PERL_INC: &str = "STRYKE_NO_PERL_INC";
fn cache_path() -> Option<PathBuf> {
dirs_next().map(|d| d.join("perl_inc.txt"))
}
fn dirs_next() -> Option<PathBuf> {
std::env::var_os("HOME").map(|h| PathBuf::from(h).join(".cache").join("stryke"))
}
pub fn paths_from_system_perl() -> Vec<String> {
if std::env::var_os(ENV_SKIP_PERL_INC).is_some() {
return Vec::new();
}
if let Some(ref path) = cache_path() {
if let Ok(contents) = crate::perl_fs::read_file_text_perl_compat(path) {
let paths = parse_perl_inc_output(&contents);
if !paths.is_empty() {
return paths;
}
}
}
let output = match Command::new("perl")
.args(["-e", r#"print join "\n", @INC"#])
.output()
{
Ok(o) => o,
Err(_) => return Vec::new(),
};
if !output.status.success() {
return Vec::new();
}
let raw = crate::perl_decode::decode_utf8_or_latin1(&output.stdout);
if let Some(ref path) = cache_path() {
let _ = std::fs::create_dir_all(path.parent().unwrap());
let _ = std::fs::write(path, raw.as_bytes());
}
parse_perl_inc_output(&raw)
}
pub fn parse_perl_inc_output(s: &str) -> Vec<String> {
s.lines()
.map(str::trim)
.filter(|line| !line.is_empty())
.map(String::from)
.collect()
}
pub fn push_unique_string_paths(target: &mut Vec<String>, extra: Vec<String>) {
for p in extra {
if !target.iter().any(|e| e == &p) {
target.push(p);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_perl_inc_output_trims_and_skips_blank_lines() {
assert_eq!(
parse_perl_inc_output(" /a/lib \n\n/b\n"),
vec!["/a/lib".to_string(), "/b".to_string()]
);
}
#[test]
fn push_unique_string_paths_dedupes() {
let mut v = vec!["a".to_string()];
push_unique_string_paths(&mut v, vec!["a".to_string(), "b".to_string()]);
assert_eq!(v, vec!["a", "b"]);
}
#[test]
fn parse_perl_inc_output_empty_and_whitespace_only() {
assert!(parse_perl_inc_output("").is_empty());
assert!(parse_perl_inc_output(" \n\t\n").is_empty());
}
#[test]
fn push_unique_string_paths_empty_extra_is_noop() {
let mut v = vec!["a".to_string()];
push_unique_string_paths(&mut v, vec![]);
assert_eq!(v, vec!["a"]);
}
#[test]
fn push_unique_string_paths_appends_in_order() {
let mut v = vec!["first".to_string()];
push_unique_string_paths(&mut v, vec!["second".to_string(), "third".to_string()]);
assert_eq!(v, vec!["first", "second", "third"]);
}
}