1use std::ffi::{OsStr, OsString};
4use std::path::{Path, PathBuf};
5
6pub fn split_path(path: &OsStr) -> Vec<PathBuf> {
8 std::env::split_paths(path)
9 .filter(|p| !p.as_os_str().is_empty())
10 .collect()
11}
12
13pub fn prepend_dedup(dir: &Path, current: &OsStr) -> OsString {
16 let mut entries: Vec<PathBuf> = vec![dir.to_path_buf()];
17 for entry in split_path(current) {
18 if entry != dir {
19 entries.push(entry);
20 }
21 }
22 std::env::join_paths(entries).unwrap_or_else(|_| current.to_os_string())
23}
24
25pub fn without_dir(dir: &Path, current: &OsStr) -> OsString {
28 let entries: Vec<PathBuf> = split_path(current)
29 .into_iter()
30 .filter(|entry| entry != dir)
31 .collect();
32 std::env::join_paths(entries).unwrap_or_else(|_| current.to_os_string())
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38
39 #[test]
40 fn prepend_puts_dir_first_and_dedups() {
41 let current = OsString::from("/usr/bin:/shim:/bin");
42 let out = prepend_dedup(Path::new("/shim"), ¤t);
43 let entries = split_path(&out);
44 assert_eq!(entries[0], PathBuf::from("/shim"));
45 assert_eq!(
46 entries.iter().filter(|p| *p == Path::new("/shim")).count(),
47 1
48 );
49 }
50
51 #[test]
52 fn without_dir_removes_all_occurrences() {
53 let current = OsString::from("/shim:/usr/bin:/shim:/bin");
54 let out = without_dir(Path::new("/shim"), ¤t);
55 let entries = split_path(&out);
56 assert!(!entries.iter().any(|p| p == Path::new("/shim")));
57 assert_eq!(
58 entries,
59 vec![PathBuf::from("/usr/bin"), PathBuf::from("/bin")]
60 );
61 }
62}