use std::process::{Child, Command, Stdio};
#[cfg(windows)]
use std::os::windows::process::CommandExt;
#[cfg(windows)]
const CREATE_NO_WINDOW: u32 = 0x0800_0000;
use tauri_utils::platform;
#[cfg(not(windows))]
pub fn get_output(cmd: String, args: Vec<String>, stdout: Stdio) -> crate::Result<String> {
let output = Command::new(cmd).args(args).stdout(stdout).output()?;
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
} else {
Err(crate::Error::Command(String::from_utf8_lossy(&output.stderr).to_string()).into())
}
}
#[cfg(windows)]
pub fn get_output(cmd: String, args: Vec<String>, stdout: Stdio) -> crate::Result<String> {
let output = Command::new(cmd)
.args(args)
.stdout(stdout)
.creation_flags(CREATE_NO_WINDOW)
.output()?;
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
} else {
Err(crate::Error::Command(String::from_utf8_lossy(&output.stderr).to_string()).into())
}
}
#[cfg(not(windows))]
pub fn command_path(command: String) -> crate::Result<String> {
match std::env::current_exe()?.parent() {
Some(exe_dir) => Ok(format!("{}/{}", exe_dir.display().to_string(), command)),
None => Err(crate::Error::Command("Could not evaluate executable dir".to_string()).into()),
}
}
#[cfg(windows)]
pub fn command_path(command: String) -> crate::Result<String> {
match std::env::current_exe()?.parent() {
Some(exe_dir) => Ok(format!("{}/{}.exe", exe_dir.display().to_string(), command)),
None => Err(crate::Error::Command("Could not evaluate executable dir".to_string()).into()),
}
}
#[cfg(windows)]
pub fn spawn_relative_command(
command: String,
args: Vec<String>,
stdout: Stdio,
) -> crate::Result<Child> {
let cmd = command_path(command)?;
Ok(
Command::new(cmd)
.args(args)
.creation_flags(CREATE_NO_WINDOW)
.stdout(stdout)
.spawn()?,
)
}
#[cfg(not(windows))]
pub fn spawn_relative_command(
command: String,
args: Vec<String>,
stdout: Stdio,
) -> crate::Result<Child> {
let cmd = command_path(command)?;
Ok(Command::new(cmd).args(args).stdout(stdout).spawn()?)
}
pub fn binary_command(binary_name: String) -> crate::Result<String> {
Ok(format!("{}-{}", binary_name, platform::target_triple()?))
}
#[cfg(test)]
mod test {
use super::*;
use std::io;
#[cfg(not(windows))]
#[test]
fn test_cmd_output() {
let cmd = String::from("cat");
let res = get_output(cmd, vec!["test/test.txt".to_string()], Stdio::piped());
assert!(res.is_ok());
if let Ok(s) = &res {
assert_eq!(*s, "This is a test doc!".to_string());
}
}
#[cfg(not(windows))]
#[test]
fn test_cmd_fail() {
use crate::Error;
let cmd = String::from("cat");
let res = get_output(cmd, vec!["test/".to_string()], Stdio::piped());
assert!(res.is_err());
if let Some(Error::Command(e)) = res.unwrap_err().downcast_ref::<Error>() {
assert_eq!(*e, "cat: test/: Is a directory\n".to_string());
}
}
#[test]
fn check_command_path() {
let cmd = String::from("cat");
let res = command_path(cmd);
assert!(res.is_ok());
}
#[test]
fn check_spawn_cmd() {
let cmd = String::from("cat");
let res = spawn_relative_command(cmd, vec!["test/test.txt".to_string()], Stdio::piped());
assert!(res.is_err());
if let Some(s) = res.unwrap_err().downcast_ref::<io::Error>() {
assert_eq!(s.kind(), std::io::ErrorKind::NotFound);
}
}
}