bctx_forge/substrate/
local.rs1use super::{Substrate, SubstrateCommand, SubstrateError, SubstrateResult};
2use std::process::Command;
3use std::time::Instant;
4
5pub struct LocalSubstrate;
6
7impl Substrate for LocalSubstrate {
8 fn execute(&self, cmd: SubstrateCommand) -> Result<SubstrateResult, SubstrateError> {
9 let start = Instant::now();
10
11 let mut builder = Command::new(&cmd.program);
12 builder.args(&cmd.args);
13
14 if let Some(ref cwd) = cmd.working_dir {
15 builder.current_dir(cwd);
16 }
17
18 let inherited_path = std::env::var("PATH").unwrap_or_default();
20 let augmented = if inherited_path.is_empty() {
21 "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin".to_string()
22 } else {
23 format!("/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:{inherited_path}")
24 };
25 builder.env("PATH", augmented);
26
27 for (k, v) in &cmd.env {
28 builder.env(k, v);
29 }
30
31 let output = builder.output().map_err(|e| {
32 if e.kind() == std::io::ErrorKind::NotFound {
33 SubstrateError::NotFound(cmd.program.clone())
34 } else {
35 SubstrateError::Io(e)
36 }
37 })?;
38
39 let duration_ms = start.elapsed().as_millis() as u64;
40
41 Ok(SubstrateResult {
42 stdout: output.stdout,
43 stderr: output.stderr,
44 exit_code: output.status.code().unwrap_or(-1),
45 duration_ms,
46 })
47 }
48
49 fn is_available(&self) -> bool {
50 true
51 }
52}