Skip to main content

ruff_db/system/
command.rs

1use std::process::Output;
2
3use super::{Result, SystemPath, SystemPathBuf};
4
5/// An owned description of a command to execute with a [`CommandExecutor`].
6#[derive(Debug)]
7pub struct Command {
8    executable: String,
9    arguments: Vec<String>,
10    current_directory: Option<SystemPathBuf>,
11}
12
13impl Command {
14    /// Creates a command for the given executable.
15    pub fn new(executable: impl Into<String>) -> Self {
16        Self {
17            executable: executable.into(),
18            arguments: Vec::new(),
19            current_directory: None,
20        }
21    }
22
23    /// Adds an argument to the command.
24    pub fn arg(&mut self, argument: impl Into<String>) -> &mut Self {
25        self.arguments.push(argument.into());
26        self
27    }
28
29    /// Adds multiple arguments to the command.
30    pub fn args<I, S>(&mut self, arguments: I) -> &mut Self
31    where
32        I: IntoIterator<Item = S>,
33        S: Into<String>,
34    {
35        self.arguments.extend(arguments.into_iter().map(Into::into));
36        self
37    }
38
39    /// Sets the working directory for the command.
40    pub fn current_dir(&mut self, directory: impl AsRef<SystemPath>) -> &mut Self {
41        self.current_directory = Some(directory.as_ref().to_path_buf());
42        self
43    }
44
45    /// Returns the executable to invoke.
46    pub fn get_executable(&self) -> &str {
47        &self.executable
48    }
49
50    /// Returns the arguments passed to the executable.
51    pub fn get_args(&self) -> &[String] {
52        &self.arguments
53    }
54
55    /// Returns the command's working directory, if explicitly configured.
56    pub fn get_current_dir(&self) -> Option<&SystemPath> {
57        self.current_directory.as_deref()
58    }
59}
60
61/// Executes [`Command`]s.
62pub trait CommandExecutor: Send + Sync {
63    /// Runs a command and captures its standard output and standard error.
64    fn execute(&self, command: Command) -> Result<Output>;
65
66    /// Creates an owned executor that can be moved to another thread.
67    fn dyn_clone(&self) -> Box<dyn CommandExecutor>;
68}