use std::path::PathBuf;
pub fn home_roots() -> Vec<PathBuf> {
let mut out: Vec<PathBuf> = Vec::new();
if let Some(h) = dirs::home_dir() {
out.push(h);
}
if is_wsl() {
if let Ok(rd) = std::fs::read_dir("/mnt/c/Users") {
for ent in rd.flatten() {
let p = ent.path();
if !p.is_dir() { continue; }
let name = ent.file_name();
let lname = name.to_string_lossy().to_ascii_lowercase();
if matches!(lname.as_str(),
"public" | "default" | "default user" | "all users"
| "defaultuser0" | "defaultuser100000" | "desktop.ini"
) { continue; }
out.push(p);
}
}
}
if let Ok(s) = std::env::var("AGTOP_EXTRA_HOMES") {
let sep = if cfg!(windows) { ';' } else { ':' };
for tok in s.split(sep) {
let t = tok.trim();
if t.is_empty() { continue; }
out.push(PathBuf::from(t));
}
}
let mut seen = std::collections::HashSet::new();
out.retain(|p| seen.insert(p.clone()));
out
}
#[cfg(target_os = "linux")]
fn is_wsl() -> bool {
if let Ok(s) = std::fs::read_to_string("/proc/version") {
let l = s.to_ascii_lowercase();
if l.contains("microsoft") || l.contains("wsl") { return true; }
}
if let Ok(s) = std::fs::read_to_string("/proc/sys/kernel/osrelease") {
let l = s.to_ascii_lowercase();
if l.contains("microsoft") || l.contains("wsl") { return true; }
}
false
}
#[cfg(not(target_os = "linux"))]
fn is_wsl() -> bool { false }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn own_home_always_first() {
let r = home_roots();
if let Some(h) = dirs::home_dir() {
assert_eq!(r.first(), Some(&h));
}
}
#[test]
fn extra_homes_env_appended() {
let sep = if cfg!(windows) { ";" } else { ":" };
let val = format!("/tmp/fake-home-a{sep}/tmp/fake-home-b");
let prev = std::env::var("AGTOP_EXTRA_HOMES").ok();
std::env::set_var("AGTOP_EXTRA_HOMES", &val);
let r = home_roots();
assert!(r.iter().any(|p| p == &PathBuf::from("/tmp/fake-home-a")));
assert!(r.iter().any(|p| p == &PathBuf::from("/tmp/fake-home-b")));
match prev {
Some(v) => std::env::set_var("AGTOP_EXTRA_HOMES", v),
None => std::env::remove_var("AGTOP_EXTRA_HOMES"),
}
}
}