lazy_badger/
run.rs

1use std::{
2    path::{Path, PathBuf},
3    process::{Command, ExitStatus, Stdio},
4};
5
6/// The executor of commands
7pub const EXECUTOR: &str = "bash";
8
9/// All errors triggered by the script management module
10#[derive(Debug, thiserror::Error)]
11pub enum RunScriptError {
12    /// Script is not executable
13    #[error("Given script '{0:?}' is not executable")]
14    NotExecutable(PathBuf),
15    /// Script is not a file
16    #[error("Given path '{0:?}' is not a file")]
17    NotAFile(PathBuf),
18    /// File was not found
19    #[error("Given path '{0:?}' was not found")]
20    NotFound(PathBuf),
21    /// Error reading the file
22    #[error("Error reading file '{0:?}': {1}")]
23    ReadFailure(PathBuf, std::io::Error),
24    /// Error running the script
25    #[error("Error running the script '{0:?}': {1}")]
26    RunFailure(PathBuf, std::io::Error),
27    /// Error parsing script output
28    #[error("Error parsing script '{0:?}' output")]
29    OutputParse(PathBuf),
30}
31
32/// Runs a script from its path
33///
34/// Forwards the given arguments to the scripts
35///
36/// The script will take control over stdin, stdout and stderr during execution
37///
38/// # Errors
39///
40/// - Path is not a file;
41/// - Path is not found;
42/// - Script is not executable;
43/// - Error running the script;
44/// - Error parsing script output;
45pub fn run_script(path: &Path, arguments: &[String]) -> Result<ExitStatus, RunScriptError> {
46    if !path.exists() {
47        return Err(RunScriptError::NotFound(path.to_path_buf()));
48    }
49    if !path.is_file() {
50        return Err(RunScriptError::NotAFile(path.to_path_buf()));
51    }
52    let md = path
53        .metadata()
54        .map_err(|err| RunScriptError::ReadFailure(path.to_path_buf(), err))?;
55    if !super::read::is_path_executable(md.permissions()) {
56        return Err(RunScriptError::NotExecutable(path.to_path_buf()));
57    }
58
59    let status = Command::new(EXECUTOR)
60        .arg(path)
61        .args(arguments)
62        .stdin(Stdio::inherit())
63        .stdout(Stdio::inherit())
64        .stderr(Stdio::inherit())
65        .spawn()
66        .map_err(|err| RunScriptError::RunFailure(path.to_path_buf(), err))?
67        .wait()
68        .map_err(|err| RunScriptError::RunFailure(path.to_path_buf(), err))?;
69
70    Ok(status)
71}