1use std::{
2 io::{Error, ErrorKind},
3 path::{Path, PathBuf},
4 process::{Command, Output},
5};
6
7use which::which;
8
9pub fn exec(cmd: &str, cwd: &Path) -> Result<Output, Error> {
33 match which(cmd.split(' ').next().unwrap()) {
35 Ok(_) => (),
36 Err(_) => {
37 return Err(Error::new(
38 ErrorKind::NotFound,
39 format!("Could not find specified command: {}", cmd),
40 ))
41 }
42 }
43 if !cwd.exists() {
45 return Err(Error::new(ErrorKind::Other, "Specified path is invalid!"));
46 }
47 if !cwd.is_dir() {
49 return Err(Error::new(
50 ErrorKind::Other,
51 "Specified path is not a directory",
52 ));
53 }
54 if cfg!(target_os = "windows") {
56 return Command::new("cmd")
57 .current_dir(&cwd.as_os_str())
58 .args(["/C", cmd])
59 .output();
60 } else {
61 return Command::new("sh")
62 .current_dir(&cwd.as_os_str())
63 .arg("-c")
64 .arg(cmd)
65 .output();
66 };
67}
68
69pub fn get_pwd(dir: Option<&Path>) -> PathBuf {
79 let pwd = match std::env::current_dir() {
80 Ok(v) => PathBuf::from(v),
81 Err(err) => panic!("Couldn't find current dir: {}", err),
82 };
83
84 return match dir {
85 Some(v) => v.to_path_buf(),
86 None => pwd,
87 };
88}
89
90#[cfg(test)]
91mod tests {
92 use std::path::Path;
93
94 use super::exec;
95
96 #[test]
97 fn test_exec_valid() {
98 let cmd = "echo";
99 let cwd = Path::new("/tmp");
100 let result = exec(cmd, cwd);
101 assert!(result.is_ok());
102 let output = result.unwrap();
103 assert!(output.status.success());
104 }
105
106 #[test]
107 #[should_panic]
108 fn test_exec_cmd_invalid() {
109 let cmd = "invalid_command";
110 let cwd = Path::new("/tmp");
111 exec(cmd, cwd).unwrap();
112 }
113
114 #[test]
115 #[should_panic]
116 fn test_exec_cwd_invalid() {
117 let cmd = "ls";
118 let cwd = Path::new("/dir/that/does/not/exist");
119 exec(cmd, cwd).unwrap();
120 }
121}