1use std::{
2 path::{Path, PathBuf},
3 fs::File,
4 io::{Write,Read},
5 fs,
6 io::prelude::*,
7 io::BufReader,
8 process::{Command, Stdio}
9};
10
11pub fn shell(cwd: &Path, cmd: &str, args: &[&str]) -> Result<(), String> {
12 let mut cmd_build = Command::new(cmd);
13
14 cmd_build.args(args)
15 .current_dir(cwd);
16
17 let mut child = cmd_build.spawn().map_err( | e | format!("Error starting {} in dir {:?} - {:?}", cmd, cwd, e)) ?;
18
19 let r = child.wait().map_err( | e | format!("Process {} in dir {:?} returned error {:?} ", cmd, cwd, e)) ?;
20 if !r.success() {
21 return Err(format!("Process {} in dir {:?} returned error exit code ", cmd, cwd));
22 }
23 Ok(())
24}
25
26pub fn shell_env(env: &[(&str, &str)], cwd: &Path, cmd: &str, args: &[&str]) -> Result<(), String> {
27 let mut cmd_build = Command::new(cmd);
28
29 cmd_build.args(args)
30 .current_dir(cwd);
31
32 for (key, value) in env {
33 cmd_build.env(key, value);
34 }
35 let mut child = cmd_build.spawn().map_err( | e | format!("Error starting {} in dir {:?} - {:?}", cmd, cwd, e)) ?;
36
37 let r = child.wait().map_err( | e | format!("Process {} in dir {:?} returned error {:?} ", cmd, cwd, e)) ?;
38 if !r.success() {
39 return Err(format!("Process {} in dir {:?} returned error exit code ", cmd, cwd));
40 }
41 Ok(())
42}
43
44
45pub fn shell_env_cap(env: &[(&str, &str)], cwd: &Path, cmd: &str, args: &[&str]) -> Result<String, String> {
46 let mut cmd_build = Command::new(cmd);
47
48 cmd_build.args(args)
49 .stdout(Stdio::piped())
50 .stderr(Stdio::piped())
51 .current_dir(cwd);
52
53 for (key, value) in env {
54 cmd_build.env(key, value);
55 }
56 let mut child = cmd_build.spawn().map_err( | e | format!("Error starting {} in dir {:?} - {:?}", cmd, cwd, e)) ?;
57
58 let r = child.wait().map_err( | e | format!("Process {} in dir {:?} returned error {:?} ", cmd, cwd, e)) ?;
59 if !r.success() {
60 let mut out = String::new();
61 let _ = child.stderr.unwrap().read_to_string(&mut out);
62 return Err(format!("Process {} in dir {:?} returned error exit code {} ", cmd, cwd, out));
63 }
64 let mut out = String::new();
65 let _ = child.stdout.unwrap().read_to_string(&mut out);
66 Ok(out)
67}
68
69pub fn shell_env_filter(start:&str, minus:Vec<String>, env: &[(&str, &str)], cwd: &Path, cmd: &str, args: &[&str]) -> Result<(), String> {
70
71 let mut cmd_build = Command::new(cmd);
72
73 cmd_build.args(args)
74 .stdin(Stdio::piped())
75 .stdout(Stdio::piped())
76 .current_dir(cwd);
77
78 for (key, value) in env {
79 cmd_build.env(key, value);
80 }
81
82 let mut child = cmd_build.spawn().map_err( | e | format!("Error starting {} in dir {:?} - {:?}", cmd, cwd, e)) ?;
83
84 let stdout = child.stdout.take().expect("stdout cannot be taken!");
85 let start = start.to_string();
86 let _stdout_thread = {
87 std::thread::spawn(move || {
88 let mut reader = BufReader::new(stdout);
89 let mut output = false;
90 'a: loop{
91 let mut line = String::new();
92 if let Ok(_) = reader.read_line(&mut line){
93 if line.contains(&start){
94 output = true;
95 }
96 if output{
97 for min in &minus{
98 if line.contains(min){
99 continue 'a;
100 }
101 }
102 println!("{}",line);
103 }
104 }
105 }
106 })
107 };
108
109 let r = child.wait().map_err( | e | format!("Process {} in dir {:?} returned error {:?} ", cmd, cwd, e)) ?;
110 if !r.success() {
111 return Err(format!("Process {} in dir {:?} returned error exit code {} ", cmd, cwd, r));
112 }
113 Ok(())
114}
115
116pub fn write_text(path: &Path, data:&str) -> Result<(), String> {
117 mkdir(path.parent().unwrap()) ?;
118 match fs::File::create(path) {
119 Err(e) => {
120 Err(format!("file create {:?} failed {:?}", path, e))
121 },
122 Ok(mut f) =>{
123 f.write_all(data.as_bytes())
124 .map_err( | _e | format!("Cant write file {:?}", path))
125 }
126 }
127}
128
129pub fn rmdir(path: &Path) -> Result<(), String> {
130 match fs::remove_dir_all(path) {
131 Err(e) => {
132 Err(format!("rmdir {:?} failed {:?}", path, e))
133 },
134 Ok(()) => Ok(())
135 }
136}
137
138
139pub fn mkdir(path: &Path) -> Result<(), String> {
140 match fs::create_dir_all(path) {
141 Err(e) => {
142 Err(format!("mkdir {:?} failed {:?}", path, e))
143 },
144 Ok(()) => Ok(())
145 }
146}
147
148pub fn rm(path: &Path) -> Result<(), String> {
149 match fs::remove_file(path) {
150 Err(e) => {
151 Err(format!("remove_file {:?} failed {:?}", path, e))
152 },
153 Ok(()) => Ok(())
154 }
155}
156
157
158#[allow(unused)]
159pub fn cp(source_path: &Path, dest_path: &Path, exec: bool) -> Result<(), String> {
160 let data = fs::read(source_path)
161 .map_err( | _e | format!("Cant open input file {:?}", source_path)) ?;
162 mkdir(dest_path.parent().unwrap()) ?;
163 let mut output = File::create(dest_path)
164 .map_err( | _e | format!("Cant open output file {:?}", dest_path)) ?;
165 output.write(&data)
166 .map_err( | _e | format!("Cant write output file {:?}", dest_path)) ?;
167 #[cfg(any(target_os = "macos", target_os = "linux"))]
168 if exec {
169 use std::os::unix::fs::PermissionsExt;
170 std::fs::set_permissions(dest_path, PermissionsExt::from_mode(0o744))
171 .map_err( | _e | format!("Cant set exec permissions on output file {:?}", dest_path)) ?;
172 }
173 Ok(())
174}
175
176pub fn cp_all(source_dir: &Path, dest_dir: &Path, exec: bool) -> Result<(), String> {
177 cp_all_recursive(source_dir, dest_dir, exec)?;
178 Ok(())
179}
180
181fn cp_all_recursive(source_dir: &Path, dest_dir: &Path, exec: bool) -> Result<(), String> {
182 if !source_dir.is_dir() {
183 return Err(format!("{:?} is not a directory", source_dir));
184 }
185
186 mkdir(dest_dir) ?;
187
188 for entry in fs::read_dir(source_dir).map_err(|_e| format!("Unable to read source directory {:?}", source_dir))? {
189 let entry = entry.map_err(|_e| format!("Unable to process directory entry"))?;
190 let source_path = entry.path();
191 if source_path.is_file() {
192 let dest_path = dest_dir.join(source_path.file_name()
193 .ok_or_else(|| format!("Unable to get filename for {:?}", source_path))?);
194
195 cp(&source_path, &dest_path, exec)?;
196 } else if source_path.is_dir() {
197 let dest_path = dest_dir.join(source_path.file_name()
198 .ok_or_else(|| format!("Unable to get folder name for {:?}", source_path))?);
199
200 cp_all_recursive(&source_path, &dest_path, exec)?;
201 }
202 }
203
204 Ok(())
205}
206
207pub fn ls(dir: &Path) -> Result<Vec<PathBuf>, String> {
208 let mut result = Vec::new();
209 ls_recursive(dir, dir, &mut result)?;
210 Ok(result)
211}
212
213fn ls_recursive(dir: &Path, prefix: &Path, result: &mut Vec<PathBuf>) -> Result<(), String> {
214 for entry in fs::read_dir(dir).map_err(|_e| format!("Unable to read source directory {:?}", dir))? {
215 let entry = entry.map_err(|_e| format!("Unable to process directory entry"))?;
216 let source_path = entry.path();
217 if source_path.is_file() {
218 let file_name = source_path
219 .file_name()
220 .ok_or_else(|| format!("Unable to get filename"))?
221 .to_str()
222 .ok_or_else(|| format!( "Unable to convert filename to str"))?;
223
224 if !file_name.starts_with('.') {
225 let result_path = source_path.strip_prefix(prefix)
226 .map_err(|_e| format!("Unable to strip prefix"))?;
227 result.push(result_path.to_path_buf());
228 }
229 } else if source_path.is_dir() {
230 ls_recursive(&source_path, prefix, result)?;
231 }
232 }
233
234 Ok(())
235}