turtle_build/infrastructure/command_runner/
os.rs1use crate::infrastructure::CommandRunner;
2use async_trait::async_trait;
3use core::error::Error;
4use std::process::{ExitStatus, Output, Stdio};
5use tokio::{process::Command, sync::Semaphore};
6
7#[derive(Debug)]
9pub struct OsCommandRunner {
10 semaphore: Semaphore,
11}
12
13impl OsCommandRunner {
14 pub fn new(job_limit: usize) -> Self {
16 Self {
17 semaphore: Semaphore::new(job_limit),
18 }
19 }
20
21 fn create_command(command: &str) -> Command {
22 if cfg!(target_os = "windows") {
23 let components = command.split_whitespace().collect::<Vec<_>>();
24 let mut process = Command::new(components[0]);
25
26 process.args(&components[1..]);
27 process
28 } else {
29 let mut process = Command::new("sh");
30
31 process.arg("-ec").arg(command);
32 process
33 }
34 }
35}
36
37#[async_trait]
38impl CommandRunner for OsCommandRunner {
39 async fn run(&self, command: &str) -> Result<Output, Box<dyn Error>> {
40 let _permit = self.semaphore.acquire().await?;
41
42 Ok(Self::create_command(command)
43 .stdin(Stdio::null())
44 .output()
45 .await?)
46 }
47
48 async fn run_with_console(&self, command: &str) -> Result<ExitStatus, Box<dyn Error>> {
49 let _permit = self.semaphore.acquire().await?;
50
51 Ok(Self::create_command(command).status().await?)
53 }
54}