makepad_shell/
shell.rs

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}