Skip to content

Commit 8bce446

Browse files
committed
process wrapper: move argument parsing in a separate mod.
1 parent e46a2ce commit 8bce446

File tree

3 files changed

+247
-157
lines changed

3 files changed

+247
-157
lines changed

util/process_wrapper/flags.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,12 @@ impl<'a> Flags<'a> {
119119
all.sort();
120120

121121
let mut help_text = String::new();
122-
writeln!(&mut help_text, "Help for {}", program_name).unwrap();
122+
writeln!(
123+
&mut help_text,
124+
"Help for {}: [options] -- [extra arguments]",
125+
program_name
126+
)
127+
.unwrap();
123128
for line in all {
124129
writeln!(&mut help_text, "\t{}", line).unwrap();
125130
}

util/process_wrapper/main.rs

Lines changed: 12 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -13,168 +13,24 @@
1313
// limitations under the License.
1414

1515
mod flags;
16+
mod options;
1617
mod util;
1718

18-
use std::collections::HashMap;
19-
use std::env;
2019
use std::fs::{copy, OpenOptions};
2120
use std::process::{exit, Command, Stdio};
2221

23-
use flags::{Flags, ParseOutcome};
24-
use util::*;
25-
26-
fn environment_block(
27-
environment_file_block: HashMap<String, String>,
28-
stamp_mappings: &[(String, String)],
29-
subst_mappings: &[(String, String)],
30-
) -> HashMap<String, String> {
31-
// Taking all environment variables from the current process
32-
// and sending them down to the child process
33-
let mut environment_variables: HashMap<String, String> = std::env::vars().collect();
34-
// Have the last values added take precedence over the first.
35-
// This is simpler than needing to track duplicates and explicitly override
36-
// them.
37-
environment_variables.extend(environment_file_block.into_iter());
38-
for (f, replace_with) in stamp_mappings {
39-
for value in environment_variables.values_mut() {
40-
let from = format!("{{{}}}", f);
41-
let new = value.replace(from.as_str(), replace_with);
42-
*value = new;
43-
}
44-
}
45-
for (f, replace_with) in subst_mappings {
46-
for value in environment_variables.values_mut() {
47-
let from = format!("${{{}}}", f);
48-
let new = value.replace(from.as_str(), replace_with);
49-
*value = new;
50-
}
51-
}
52-
environment_variables
53-
}
54-
55-
fn prepare_args(mut args: Vec<String>, subst_mappings: &[(String, String)]) -> Vec<String> {
56-
for (f, replace_with) in subst_mappings {
57-
for arg in args.iter_mut() {
58-
let from = format!("${{{}}}", f);
59-
let new = arg.replace(from.as_str(), replace_with);
60-
*arg = new;
61-
}
62-
}
63-
args
64-
}
22+
use crate::options::options;
6523

6624
fn main() {
67-
// Process argument list until -- is encountered.
68-
// Everything after is sent to the child process.
69-
let mut subst_mapping_raw = None;
70-
let mut volatile_status_file_raw = None;
71-
let mut env_file_raw = None;
72-
let mut arg_file_raw = None;
73-
let mut touch_file_raw = None;
74-
let mut copy_output_raw = None;
75-
let mut stdout_file_raw = None;
76-
let mut stderr_file_raw = None;
77-
let mut flags = Flags::new();
78-
flags.define_repeated_flag("--subst", "", &mut subst_mapping_raw);
79-
flags.define_flag("--volatile-status-file", "", &mut volatile_status_file_raw);
80-
flags.define_repeated_flag("--env-file", "", &mut env_file_raw);
81-
flags.define_repeated_flag("--arg-file", "", &mut arg_file_raw);
82-
flags.define_flag("--touch-file", "", &mut touch_file_raw);
83-
flags.define_repeated_flag("--copy-output", "", &mut copy_output_raw);
84-
flags.define_flag(
85-
"--stdout-file",
86-
"Redirect subprocess stdout in this file.",
87-
&mut stdout_file_raw,
88-
);
89-
flags.define_flag(
90-
"--stderr-file",
91-
"Redirect subprocess stderr in this file.",
92-
&mut stderr_file_raw,
93-
);
94-
let mut child_args = match flags
95-
.parse(env::args().collect())
96-
.expect("flag parse error")
97-
{
98-
ParseOutcome::Help(help) => {
99-
eprintln!("{}", help);
100-
return;
101-
}
102-
ParseOutcome::Parsed(p) => p,
25+
let opts = match options() {
26+
Err(err) => panic!("process wrapper error: {}", err),
27+
Ok(v) => v,
10328
};
104-
let subst_mappings: Vec<(String, String)> = subst_mapping_raw
105-
.unwrap_or_default()
106-
.into_iter()
107-
.map(|arg| {
108-
let (key, val) = arg.split_once('=').unwrap_or_else(|| {
109-
panic!(
110-
"process wrapper error: empty key for substitution '{}'",
111-
arg
112-
)
113-
});
114-
let v = if val == "${pwd}" {
115-
std::env::current_dir()
116-
.unwrap()
117-
.to_str()
118-
.unwrap()
119-
.to_string()
120-
} else {
121-
val.to_owned()
122-
};
123-
(key.to_owned(), v)
124-
})
125-
.collect();
126-
let stamp_mappings =
127-
volatile_status_file_raw.map_or_else(Vec::new, |s| read_stamp_status_to_array(s).unwrap());
128-
let environment_file_block: HashMap<String, String> = env_file_raw
129-
.unwrap_or_default()
130-
.into_iter()
131-
.flat_map(|path| -> Vec<(String, String)> {
132-
let lines = read_file_to_array(path).unwrap();
133-
lines
134-
.into_iter()
135-
.map(|l| {
136-
let splits = l
137-
.split_once('=')
138-
.expect("process wrapper error: environment file invalid");
139-
(splits.0.to_owned(), splits.1.to_owned())
140-
})
141-
.collect()
142-
})
143-
.collect();
144-
let mut file_arguments: Vec<String> = arg_file_raw
145-
.unwrap_or_default()
146-
.into_iter()
147-
.flat_map(|path| read_file_to_array(path).unwrap())
148-
.collect();
149-
// Process --copy-output
150-
let copy_output = copy_output_raw.map(|co| {
151-
if co.len() != 2 {
152-
panic!(
153-
"process wrapper error: \"--copy-output\" needs exactly 2 parameters, {} provided",
154-
co.len()
155-
)
156-
}
157-
let copy_source = &co[0];
158-
let copy_dest = &co[1];
159-
if copy_source == copy_dest {
160-
panic!(
161-
"process wrapper error: \"--copy-output\" source ({}) and dest ({}) need to be different.",
162-
copy_source, copy_dest
163-
)
164-
}
165-
(copy_source.to_owned(), copy_dest.to_owned())
166-
});
167-
child_args.append(&mut file_arguments);
168-
let child_args = prepare_args(child_args, &subst_mappings);
169-
170-
let (exec_path, args) = child_args.split_first().expect("process wrapper error: at least one argument after -- is required (the child process path) but none found.");
171-
let vars = environment_block(environment_file_block, &stamp_mappings, &subst_mappings);
172-
173-
let status = Command::new(exec_path)
174-
.args(args)
29+
let status = Command::new(opts.executable)
30+
.args(opts.child_arguments)
17531
.env_clear()
176-
.envs(vars)
177-
.stdout(if let Some(stdout_file) = stdout_file_raw {
32+
.envs(opts.child_environment)
33+
.stdout(if let Some(stdout_file) = opts.stdout_file {
17834
OpenOptions::new()
17935
.create(true)
18036
.truncate(true)
@@ -185,7 +41,7 @@ fn main() {
18541
} else {
18642
Stdio::inherit()
18743
})
188-
.stderr(if let Some(stderr_file) = stderr_file_raw {
44+
.stderr(if let Some(stderr_file) = opts.stderr_file {
18945
OpenOptions::new()
19046
.create(true)
19147
.truncate(true)
@@ -200,14 +56,14 @@ fn main() {
20056
.expect("process wrapper error: failed to spawn child process");
20157

20258
if status.success() {
203-
if let Some(tf) = touch_file_raw {
59+
if let Some(tf) = opts.touch_file {
20460
OpenOptions::new()
20561
.create(true)
20662
.write(true)
20763
.open(tf)
20864
.expect("process wrapper error: failed to create touch file");
20965
}
210-
if let Some((copy_source, copy_dest)) = copy_output {
66+
if let Some((copy_source, copy_dest)) = opts.copy_output {
21167
copy(&copy_source, &copy_dest).unwrap_or_else(|_| {
21268
panic!(
21369
"process wrapper error: failed to copy {} into {}",

0 commit comments

Comments
 (0)