Skip to content

Commit aea3f77

Browse files
committed
allow spawn to behave according to failure behavior
1 parent 186f588 commit aea3f77

File tree

1 file changed

+54
-39
lines changed

1 file changed

+54
-39
lines changed

src/bootstrap/src/utils/execution_context.rs

Lines changed: 54 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl ExecutionContext {
108108
cmd.stdout(stdout.stdio());
109109
cmd.stderr(stderr.stdio());
110110

111-
let child = cmd.spawn().unwrap();
111+
let child = cmd.spawn();
112112

113113
DeferredCommand { process: Some(child), stdout, stderr, command, executed_at }
114114
}
@@ -157,7 +157,7 @@ impl AsRef<ExecutionContext> for ExecutionContext {
157157
}
158158

159159
pub struct DeferredCommand<'a> {
160-
process: Option<Child>,
160+
process: Option<Result<Child, std::io::Error>>,
161161
command: &'a mut BootstrapCommand,
162162
stdout: OutputMode,
163163
stderr: OutputMode,
@@ -166,61 +166,77 @@ pub struct DeferredCommand<'a> {
166166

167167
impl<'a> DeferredCommand<'a> {
168168
pub fn wait_for_output(mut self, exec_ctx: impl AsRef<ExecutionContext>) -> CommandOutput {
169-
if self.process.is_none() {
170-
return CommandOutput::default();
171-
}
172-
173169
let exec_ctx = exec_ctx.as_ref();
174170

175-
let output = self.process.take().unwrap().wait_with_output();
171+
let process = match self.process.take() {
172+
Some(p) => p,
173+
None => return CommandOutput::default(),
174+
};
176175

177176
let created_at = self.command.get_created_location();
178177
let executed_at = self.executed_at;
179178

180-
use std::fmt::Write;
181-
182179
let mut message = String::new();
183-
let output: CommandOutput = match output {
184-
// Command has succeeded
185-
Ok(output) if output.status.success() => {
186-
CommandOutput::from_output(output, self.stdout, self.stderr)
187-
}
188-
// Command has started, but then it failed
189-
Ok(output) => {
190-
writeln!(
191-
message,
192-
r#"
180+
181+
let output = match process {
182+
Ok(child) => match child.wait_with_output() {
183+
Ok(result) if result.status.success() => {
184+
// Successful execution
185+
CommandOutput::from_output(result, self.stdout, self.stderr)
186+
}
187+
Ok(result) => {
188+
// Command ran but failed
189+
use std::fmt::Write;
190+
191+
writeln!(
192+
message,
193+
r#"
193194
Command {:?} did not execute successfully.
194195
Expected success, got {}
195196
Created at: {created_at}
196197
Executed at: {executed_at}"#,
197-
self.command, output.status,
198-
)
199-
.unwrap();
198+
self.command, result.status,
199+
)
200+
.unwrap();
201+
202+
let output = CommandOutput::from_output(result, self.stdout, self.stderr);
200203

201-
let output: CommandOutput =
202-
CommandOutput::from_output(output, self.stdout, self.stderr);
204+
if self.stdout.captures() {
205+
writeln!(message, "\nSTDOUT ----\n{}", output.stdout().trim()).unwrap();
206+
}
207+
if self.stderr.captures() {
208+
writeln!(message, "\nSTDERR ----\n{}", output.stderr().trim()).unwrap();
209+
}
203210

204-
// If the output mode is OutputMode::Capture, we can now print the output.
205-
// If it is OutputMode::Print, then the output has already been printed to
206-
// stdout/stderr, and we thus don't have anything captured to print anyway.
207-
if self.stdout.captures() {
208-
writeln!(message, "\nSTDOUT ----\n{}", output.stdout().trim()).unwrap();
211+
output
209212
}
210-
if self.stderr.captures() {
211-
writeln!(message, "\nSTDERR ----\n{}", output.stderr().trim()).unwrap();
213+
Err(e) => {
214+
// Failed to wait for output
215+
use std::fmt::Write;
216+
217+
writeln!(
218+
message,
219+
"\n\nCommand {:?} did not execute successfully.\
220+
\nIt was not possible to execute the command: {e:?}",
221+
self.command
222+
)
223+
.unwrap();
224+
225+
CommandOutput::did_not_start(self.stdout, self.stderr)
212226
}
213-
output
214-
}
215-
// The command did not even start
227+
},
216228
Err(e) => {
229+
// Failed to spawn the command
230+
use std::fmt::Write;
231+
217232
writeln!(
218233
message,
219234
"\n\nCommand {:?} did not execute successfully.\
220-
\nIt was not possible to execute the command: {e:?}",
235+
\nIt was not possible to execute the command: {e:?}",
221236
self.command
222237
)
223238
.unwrap();
239+
224240
CommandOutput::did_not_start(self.stdout, self.stderr)
225241
}
226242
};
@@ -231,19 +247,18 @@ Executed at: {executed_at}"#,
231247
if exec_ctx.fail_fast {
232248
exec_ctx.fail(&message, output);
233249
}
234-
235250
exec_ctx.add_to_delay_failure(message);
236251
}
237252
BehaviorOnFailure::Exit => {
238253
exec_ctx.fail(&message, output);
239254
}
240255
BehaviorOnFailure::Ignore => {
241-
// If failures are allowed, either the error has been printed already
242-
// (OutputMode::Print) or the user used a capture output mode and wants to
243-
// handle the error output on their own.
256+
// Failures are allowed. Output has either been printed already (OutputMode::Print)
257+
// or the user will handle captured output on their own.
244258
}
245259
}
246260
}
261+
247262
output
248263
}
249264
}

0 commit comments

Comments
 (0)