evobench_tools/
run_with_pre_exec.rs1use std::{borrow::Cow, ffi::OsStr, fmt::Display, path::Path, process::Command};
4
5use crate::io_utils::bash::bash_string_from_program_path_and_args;
6
7#[derive(Debug, Clone, Copy)]
8pub enum BashSettingsLevel {
9 None,
10 SetMEU,
11 SetMEUPipefail,
12}
13
14impl BashSettingsLevel {
15 pub fn str(self) -> &'static str {
16 match self {
17 BashSettingsLevel::None => "",
18 BashSettingsLevel::SetMEU => "set -meu",
19 BashSettingsLevel::SetMEUPipefail => "set -meuo pipefail",
20 }
21 }
22}
23
24pub struct BashSettings {
25 pub level: BashSettingsLevel,
26 pub set_ifs: bool,
27}
28
29impl Display for BashSettings {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 write!(
32 f,
33 "{}\n{}",
34 self.level.str(),
35 if self.set_ifs { "IFS=\n" } else { "" }
36 )
37 }
38}
39
40pub struct RunWithPreExec<'t> {
41 pub pre_exec_bash_code: Cow<'t, str>,
42 pub bash_settings: BashSettings,
43 pub bash_path: Option<Cow<'t, Path>>,
44}
45
46impl<'t> RunWithPreExec<'t> {
47 pub fn command<S: AsRef<OsStr> + AsRef<str>>(
54 &self,
55 command_path: &str,
56 args: impl AsRef<[S]>,
57 ) -> Command {
58 let Self {
59 pre_exec_bash_code,
60 bash_settings,
61 bash_path,
62 } = self;
63
64 if pre_exec_bash_code.trim().is_empty() {
65 let mut command = Command::new(command_path);
66 command.args(args.as_ref());
67 command
68 } else {
69 let mut command = {
70 let bash: &Path = "bash".as_ref();
71 let bash = bash_path.as_ref().map(AsRef::as_ref).unwrap_or(bash);
72 Command::new(bash)
73 };
74 command.arg("-c");
75 {
76 let mut code = bash_settings.to_string();
77 code.push_str(&pre_exec_bash_code);
78 code.push_str("\n\nexec ");
79 code.push_str(&bash_string_from_program_path_and_args(
80 command_path,
81 args.as_ref(),
82 ));
83 command.arg(code);
84 }
85 command
86 }
87 }
88}
89
90pub fn join_pre_exec_bash_code(a: &str, b: &str) -> String {
91 let mut s = String::new();
92 if !a.trim().is_empty() {
93 s.push_str(a);
94 s.push_str("\n\n");
95 }
96 if !b.trim().is_empty() {
97 s.push_str(b);
98 s.push_str("\n\n");
99 }
100 s
101}