1use std::process::{Child, Command, Stdio};
2
3#[cfg(windows)]
4use std::os::windows::process::CommandExt;
5
6#[cfg(windows)]
7const CREATE_NO_WINDOW: u32 = 0x0800_0000;
8
9use tauri_utils::platform;
10
11#[cfg(not(windows))]
13pub fn get_output(cmd: String, args: Vec<String>, stdout: Stdio) -> crate::Result<String> {
14 let output = Command::new(cmd).args(args).stdout(stdout).output()?;
15
16 if output.status.success() {
17 Ok(String::from_utf8_lossy(&output.stdout).to_string())
18 } else {
19 Err(crate::Error::Command(String::from_utf8_lossy(&output.stderr).to_string()).into())
20 }
21}
22
23#[cfg(windows)]
25pub fn get_output(cmd: String, args: Vec<String>, stdout: Stdio) -> crate::Result<String> {
26 let output = Command::new(cmd)
27 .args(args)
28 .stdout(stdout)
29 .creation_flags(CREATE_NO_WINDOW)
30 .output()?;
31
32 if output.status.success() {
33 Ok(String::from_utf8_lossy(&output.stdout).to_string())
34 } else {
35 Err(crate::Error::Command(String::from_utf8_lossy(&output.stderr).to_string()).into())
36 }
37}
38
39#[cfg(not(windows))]
41pub fn command_path(command: String) -> crate::Result<String> {
42 match std::env::current_exe()?.parent() {
43 Some(exe_dir) => Ok(format!("{}/{}", exe_dir.display().to_string(), command)),
44 None => Err(crate::Error::Command("Could not evaluate executable dir".to_string()).into()),
45 }
46}
47
48#[cfg(windows)]
50pub fn command_path(command: String) -> crate::Result<String> {
51 match std::env::current_exe()?.parent() {
52 Some(exe_dir) => Ok(format!("{}/{}.exe", exe_dir.display().to_string(), command)),
53 None => Err(crate::Error::Command("Could not evaluate executable dir".to_string()).into()),
54 }
55}
56
57#[cfg(windows)]
60pub fn spawn_relative_command(
61 command: String,
62 args: Vec<String>,
63 stdout: Stdio,
64) -> crate::Result<Child> {
65 let cmd = command_path(command)?;
66 Ok(
67 Command::new(cmd)
68 .args(args)
69 .creation_flags(CREATE_NO_WINDOW)
70 .stdout(stdout)
71 .spawn()?,
72 )
73}
74
75#[cfg(not(windows))]
78pub fn spawn_relative_command(
79 command: String,
80 args: Vec<String>,
81 stdout: Stdio,
82) -> crate::Result<Child> {
83 let cmd = command_path(command)?;
84 Ok(Command::new(cmd).args(args).stdout(stdout).spawn()?)
85}
86
87pub fn binary_command(binary_name: String) -> crate::Result<String> {
89 Ok(format!("{}-{}", binary_name, platform::target_triple()?))
90}
91
92#[cfg(test)]
94mod test {
95 use super::*;
96 use std::io;
97
98 #[cfg(not(windows))]
99 #[test]
100 fn test_cmd_output() {
102 let cmd = String::from("cat");
104
105 let res = get_output(cmd, vec!["test/test.txt".to_string()], Stdio::piped());
107
108 assert!(res.is_ok());
110
111 if let Ok(s) = &res {
113 assert_eq!(*s, "This is a test doc!".to_string());
115 }
116 }
117
118 #[cfg(not(windows))]
119 #[test]
120 fn test_cmd_fail() {
122 use crate::Error;
123
124 let cmd = String::from("cat");
126
127 let res = get_output(cmd, vec!["test/".to_string()], Stdio::piped());
129
130 assert!(res.is_err());
132
133 if let Some(Error::Command(e)) = res.unwrap_err().downcast_ref::<Error>() {
135 assert_eq!(*e, "cat: test/: Is a directory\n".to_string());
137 }
138 }
139
140 #[test]
141 fn check_command_path() {
143 let cmd = String::from("cat");
145
146 let res = command_path(cmd);
148
149 assert!(res.is_ok());
151 }
152
153 #[test]
154 fn check_spawn_cmd() {
156 let cmd = String::from("cat");
158
159 let res = spawn_relative_command(cmd, vec!["test/test.txt".to_string()], Stdio::piped());
161
162 assert!(res.is_err());
164
165 if let Some(s) = res.unwrap_err().downcast_ref::<io::Error>() {
167 assert_eq!(s.kind(), std::io::ErrorKind::NotFound);
169 }
170 }
171}