Skip to content

Commit 1984a46

Browse files
committed
Make it easier to detect when bootstrap tries to read uncaptured stdout/stderr
If e.g. only stdout is captured, but the caller tries to read stderr, previously they would get back an empty string. Now the code will explicitly panic when accessing an uncaptured output stream.
1 parent ead6aad commit 1984a46

File tree

2 files changed

+32
-20
lines changed

2 files changed

+32
-20
lines changed

src/bootstrap/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,9 @@ impl Build {
968968
let mut message = String::new();
969969
let output: CommandOutput = match output {
970970
// Command has succeeded
971-
Ok(output) if output.status.success() => output.into(),
971+
Ok(output) if output.status.success() => {
972+
CommandOutput::from_output(output, stdout, stderr)
973+
}
972974
// Command has started, but then it failed
973975
Ok(output) => {
974976
writeln!(
@@ -982,7 +984,7 @@ Executed at: {executed_at}"#,
982984
)
983985
.unwrap();
984986

985-
let output: CommandOutput = output.into();
987+
let output: CommandOutput = CommandOutput::from_output(output, stdout, stderr);
986988

987989
// If the output mode is OutputMode::Capture, we can now print the output.
988990
// If it is OutputMode::Print, then the output has already been printed to

src/bootstrap/src/utils/exec.rs

+28-18
Original file line numberDiff line numberDiff line change
@@ -223,17 +223,31 @@ pub fn command<S: AsRef<OsStr>>(program: S) -> BootstrapCommand {
223223
}
224224

225225
/// Represents the output of an executed process.
226-
#[allow(unused)]
227226
pub struct CommandOutput {
228227
status: CommandStatus,
229-
stdout: Vec<u8>,
230-
stderr: Vec<u8>,
228+
stdout: Option<Vec<u8>>,
229+
stderr: Option<Vec<u8>>,
231230
}
232231

233232
impl CommandOutput {
234233
#[must_use]
235234
pub fn did_not_start() -> Self {
236-
Self { status: CommandStatus::DidNotStart, stdout: vec![], stderr: vec![] }
235+
Self { status: CommandStatus::DidNotStart, stdout: None, stderr: None }
236+
}
237+
238+
#[must_use]
239+
pub fn from_output(output: Output, stdout: OutputMode, stderr: OutputMode) -> Self {
240+
Self {
241+
status: CommandStatus::Finished(output.status),
242+
stdout: match stdout {
243+
OutputMode::Print => None,
244+
OutputMode::Capture => Some(output.stdout),
245+
},
246+
stderr: match stderr {
247+
OutputMode::Print => None,
248+
OutputMode::Capture => Some(output.stderr),
249+
},
250+
}
237251
}
238252

239253
#[must_use]
@@ -259,7 +273,10 @@ impl CommandOutput {
259273

260274
#[must_use]
261275
pub fn stdout(&self) -> String {
262-
String::from_utf8(self.stdout.clone()).expect("Cannot parse process stdout as UTF-8")
276+
String::from_utf8(
277+
self.stdout.clone().expect("Accessing stdout of a command that did not capture stdout"),
278+
)
279+
.expect("Cannot parse process stdout as UTF-8")
263280
}
264281

265282
#[must_use]
@@ -269,26 +286,19 @@ impl CommandOutput {
269286

270287
#[must_use]
271288
pub fn stderr(&self) -> String {
272-
String::from_utf8(self.stderr.clone()).expect("Cannot parse process stderr as UTF-8")
289+
String::from_utf8(
290+
self.stderr.clone().expect("Accessing stderr of a command that did not capture stderr"),
291+
)
292+
.expect("Cannot parse process stderr as UTF-8")
273293
}
274294
}
275295

276296
impl Default for CommandOutput {
277297
fn default() -> Self {
278298
Self {
279299
status: CommandStatus::Finished(ExitStatus::default()),
280-
stdout: vec![],
281-
stderr: vec![],
282-
}
283-
}
284-
}
285-
286-
impl From<Output> for CommandOutput {
287-
fn from(output: Output) -> Self {
288-
Self {
289-
status: CommandStatus::Finished(output.status),
290-
stdout: output.stdout,
291-
stderr: output.stderr,
300+
stdout: Some(vec![]),
301+
stderr: Some(vec![]),
292302
}
293303
}
294304
}

0 commit comments

Comments
 (0)