echo_comment/
runner.rs

1use std::fs;
2use std::io::Write;
3use std::process::Command;
4use tempfile::NamedTempFile;
5
6use crate::error::{EchoCommentError, Result};
7
8/// Handles the execution of processed scripts
9pub struct ScriptRunner {
10    // Future: This could hold configuration like shell, flags, etc.
11}
12
13impl ScriptRunner {
14    pub fn new() -> Self {
15        Self {}
16    }
17
18    /// Execute a processed script with the given arguments
19    pub fn run_script(&self, script_content: &str, script_args: &[String]) -> Result<()> {
20        // Create a temporary file for the processed script
21        let mut temp_file =
22            NamedTempFile::new().map_err(|e| EchoCommentError::TempFileCreation { source: e })?;
23
24        // Write the processed content
25        temp_file
26            .write_all(script_content.as_bytes())
27            .map_err(|e| EchoCommentError::FileWrite { source: e })?;
28
29        // Flush to ensure content is written
30        temp_file
31            .flush()
32            .map_err(|e| EchoCommentError::FileWrite { source: e })?;
33
34        // Get the temp file path
35        let temp_path = temp_file.into_temp_path();
36
37        // Make the temp file executable (Unix only)
38        #[cfg(unix)]
39        self.make_executable(&temp_path)?;
40
41        // Execute the processed script with the provided arguments
42        let status = Command::new(&temp_path)
43            .args(script_args)
44            .status()
45            .map_err(|e| EchoCommentError::ScriptExecution {
46                message: "Failed to execute processed script".to_string(),
47                source: e,
48            })?;
49
50        // Clean up the temp file
51        temp_path.close().map_err(|e| EchoCommentError::FileWrite {
52            source: std::io::Error::other(e),
53        })?;
54
55        // Exit with the same code as the script
56        std::process::exit(status.code().unwrap_or(1));
57    }
58
59    #[cfg(unix)]
60    fn make_executable(&self, path: &std::path::Path) -> Result<()> {
61        use std::os::unix::fs::PermissionsExt;
62
63        let mut perms = fs::metadata(path)
64            .map_err(|e| EchoCommentError::PermissionSet { source: e })?
65            .permissions();
66
67        perms.set_mode(0o755);
68
69        fs::set_permissions(path, perms)
70            .map_err(|e| EchoCommentError::PermissionSet { source: e })?;
71
72        Ok(())
73    }
74}
75
76impl Default for ScriptRunner {
77    fn default() -> Self {
78        Self::new()
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn test_script_runner_creation() {
88        let _runner = ScriptRunner::new();
89    }
90}