use crate::domain::CommandError;
use async_trait::async_trait;
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct SystemCommand {
pub program: String,
pub args: Vec<String>,
pub working_dir: Option<String>,
pub env_vars: Option<Vec<(String, String)>>,
pub timeout: Option<Duration>,
pub use_sudo: bool,
}
impl SystemCommand {
pub fn new(program: &str) -> Self {
Self {
program: program.to_string(),
args: Vec::new(),
working_dir: None,
env_vars: None,
timeout: None,
use_sudo: false,
}
}
pub fn args(mut self, args: &[&str]) -> Self {
self.args = args.iter().map(|s| s.to_string()).collect();
self
}
pub fn working_dir(mut self, dir: &str) -> Self {
self.working_dir = Some(dir.to_string());
self
}
pub fn env_vars(mut self, vars: Vec<(&str, &str)>) -> Self {
self.env_vars = Some(
vars.into_iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect(),
);
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = Some(timeout);
self
}
pub fn with_sudo(mut self) -> Self {
self.use_sudo = true;
self
}
}
#[derive(Debug, Clone)]
pub struct CommandOutput {
pub stdout: String,
pub stderr: String,
pub exit_code: Option<i32>,
pub success: bool,
}
#[async_trait]
pub trait CommandExecutor: Send + Sync {
async fn execute(&self, command: &SystemCommand) -> Result<CommandOutput, CommandError>;
async fn execute_with_privileges(
&self,
command: &SystemCommand,
) -> Result<CommandOutput, CommandError>;
async fn is_command_available(&self, command_name: &str) -> Result<bool, CommandError>;
async fn get_command_path(&self, command_name: &str) -> Result<Option<String>, CommandError>;
async fn has_elevated_privileges(&self) -> Result<bool, CommandError>;
}