mangofetch_core/core/
process.rs1fn enhanced_path() -> Option<String> {
2 use std::sync::OnceLock;
3 static CACHED: OnceLock<Option<String>> = OnceLock::new();
4 CACHED
5 .get_or_init(|| {
6 let bin_dir = crate::core::paths::app_data_dir()?.join("bin");
7 let sep = if cfg!(windows) { ";" } else { ":" };
8 let current = std::env::var("PATH").unwrap_or_default();
9
10 #[allow(unused_mut)]
11 let mut extra_dirs: Vec<String> = vec![bin_dir.display().to_string()];
12
13 #[cfg(target_os = "macos")]
14 {
15 extra_dirs.push("/opt/homebrew/bin".into());
16 extra_dirs.push("/usr/local/bin".into());
17 }
18
19 #[cfg(target_os = "linux")]
20 {
21 if let Some(home) = dirs::home_dir() {
22 extra_dirs.push(home.join(".local").join("bin").display().to_string());
23 }
24 extra_dirs.push("/usr/local/bin".into());
25 }
26
27 Some(format!("{}{}{}", extra_dirs.join(sep), sep, current))
28 })
29 .clone()
30}
31
32pub fn command<S: AsRef<std::ffi::OsStr>>(program: S) -> tokio::process::Command {
33 let mut cmd = tokio::process::Command::new(program);
34 #[cfg(target_os = "windows")]
35 cmd.creation_flags(0x08000000);
36 if let Some(path) = enhanced_path() {
37 cmd.env("PATH", path);
38 }
39 cmd.env_remove("PYTHONHOME");
40 cmd.env_remove("PYTHONPATH");
41 cmd.env("PYTHONIOENCODING", "utf-8");
42 cmd.env("PYTHONUTF8", "1");
43 cmd.stdin(std::process::Stdio::null());
44 cmd
45}
46
47pub fn std_command<S: AsRef<std::ffi::OsStr>>(program: S) -> std::process::Command {
48 let mut cmd = std::process::Command::new(program);
49 #[cfg(target_os = "windows")]
50 {
51 use std::os::windows::process::CommandExt;
52 cmd.creation_flags(0x08000000);
53 }
54 if let Some(path) = enhanced_path() {
55 cmd.env("PATH", path);
56 }
57 cmd.env_remove("PYTHONHOME");
58 cmd.env_remove("PYTHONPATH");
59 cmd.env("PYTHONIOENCODING", "utf-8");
60 cmd.env("PYTHONUTF8", "1");
61 cmd.stdin(std::process::Stdio::null());
62 cmd
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use std::ffi::OsStr;
69
70 #[test]
71 fn test_tokio_command_construction() {
72 let cmd = command("test_prog");
73 let std_cmd = cmd.as_std();
74
75 assert_eq!(std_cmd.get_program(), OsStr::new("test_prog"));
76
77 let mut has_python_io = false;
78 let mut has_python_utf8 = false;
79 let mut removed_pythonhome = false;
80 let mut removed_pythonpath = false;
81
82 for (k, v) in std_cmd.get_envs() {
83 if k == OsStr::new("PYTHONIOENCODING") {
84 assert_eq!(v, Some(OsStr::new("utf-8")));
85 has_python_io = true;
86 }
87 if k == OsStr::new("PYTHONUTF8") {
88 assert_eq!(v, Some(OsStr::new("1")));
89 has_python_utf8 = true;
90 }
91 if k == OsStr::new("PYTHONHOME") {
92 assert_eq!(v, None);
93 removed_pythonhome = true;
94 }
95 if k == OsStr::new("PYTHONPATH") {
96 assert_eq!(v, None);
97 removed_pythonpath = true;
98 }
99 }
100
101 assert!(has_python_io, "PYTHONIOENCODING was not set");
102 assert!(has_python_utf8, "PYTHONUTF8 was not set");
103 assert!(removed_pythonhome, "PYTHONHOME was not removed");
104 assert!(removed_pythonpath, "PYTHONPATH was not removed");
105 }
106
107 #[test]
108 fn test_std_command_construction() {
109 let std_cmd = std_command("test_prog");
110
111 assert_eq!(std_cmd.get_program(), OsStr::new("test_prog"));
112
113 let mut has_python_io = false;
114 let mut has_python_utf8 = false;
115 let mut removed_pythonhome = false;
116 let mut removed_pythonpath = false;
117
118 for (k, v) in std_cmd.get_envs() {
119 if k == OsStr::new("PYTHONIOENCODING") {
120 assert_eq!(v, Some(OsStr::new("utf-8")));
121 has_python_io = true;
122 }
123 if k == OsStr::new("PYTHONUTF8") {
124 assert_eq!(v, Some(OsStr::new("1")));
125 has_python_utf8 = true;
126 }
127 if k == OsStr::new("PYTHONHOME") {
128 assert_eq!(v, None);
129 removed_pythonhome = true;
130 }
131 if k == OsStr::new("PYTHONPATH") {
132 assert_eq!(v, None);
133 removed_pythonpath = true;
134 }
135 }
136
137 assert!(has_python_io, "PYTHONIOENCODING was not set");
138 assert!(has_python_utf8, "PYTHONUTF8 was not set");
139 assert!(removed_pythonhome, "PYTHONHOME was not removed");
140 assert!(removed_pythonpath, "PYTHONPATH was not removed");
141 }
142}