Skip to content

Commit a12f541

Browse files
committed
Implement new command execution logic
This function both handles error printing and early/late failures, but it also always returns the actual output of the command
1 parent 894f7a4 commit a12f541

File tree

2 files changed

+104
-2
lines changed

2 files changed

+104
-2
lines changed

src/bootstrap/src/lib.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use crate::core::builder::Kind;
4141
use crate::core::config::{flags, LldMode};
4242
use crate::core::config::{DryRun, Target};
4343
use crate::core::config::{LlvmLibunwind, TargetSelection};
44-
use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, OutputMode};
44+
use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, CommandOutput, OutputMode};
4545
use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir};
4646

4747
mod core;
@@ -958,6 +958,65 @@ impl Build {
958958
})
959959
}
960960

961+
fn run_tracked(&self, command: BootstrapCommand) -> CommandOutput {
962+
if self.config.dry_run() {
963+
return CommandOutput::default();
964+
}
965+
966+
self.verbose(|| println!("running: {command:?}"));
967+
968+
let (output, print_error): (io::Result<CommandOutput>, bool) = match command.output_mode {
969+
mode @ (OutputMode::PrintAll | OutputMode::PrintOutput) => (
970+
command.command.status().map(|status| status.into()),
971+
matches!(mode, OutputMode::PrintAll),
972+
),
973+
OutputMode::SuppressOnSuccess => (command.command.output().map(|o| o.into()), true),
974+
};
975+
976+
let output = match output {
977+
Ok(output) => output,
978+
Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", command, e)),
979+
};
980+
if !output.is_success() {
981+
if print_error {
982+
println!(
983+
"\n\nCommand did not execute successfully.\
984+
\nExpected success, got: {}",
985+
output.status(),
986+
);
987+
988+
if !self.is_verbose() {
989+
println!("Add `-v` to see more details.\n");
990+
}
991+
992+
self.verbose(|| {
993+
println!(
994+
"\nSTDOUT ----\n{}\n\
995+
STDERR ----\n{}\n",
996+
output.stdout(),
997+
output.stderr(),
998+
)
999+
});
1000+
}
1001+
1002+
match command.failure_behavior {
1003+
BehaviorOnFailure::DelayFail => {
1004+
if self.fail_fast {
1005+
exit!(1);
1006+
}
1007+
1008+
let mut failures = self.delayed_failures.borrow_mut();
1009+
failures.push(format!("{command:?}"));
1010+
}
1011+
BehaviorOnFailure::Exit => {
1012+
exit!(1);
1013+
}
1014+
BehaviorOnFailure::Ignore => {}
1015+
}
1016+
}
1017+
output
1018+
}
1019+
9611020
/// Runs a command, printing out nice contextual information if it fails.
9621021
fn run(&self, cmd: &mut Command) {
9631022
self.run_cmd(BootstrapCommand::from(cmd).fail_fast().output_mode(

src/bootstrap/src/utils/exec.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::process::Command;
1+
use std::process::{Command, ExitStatus, Output};
22

33
/// What should be done when the command fails.
44
#[derive(Debug, Copy, Clone)]
@@ -58,3 +58,46 @@ impl<'a> From<&'a mut Command> for BootstrapCommand<'a> {
5858
}
5959
}
6060
}
61+
62+
/// Represents the output of an executed process.
63+
#[allow(unused)]
64+
#[derive(Default)]
65+
pub struct CommandOutput {
66+
status: ExitStatus,
67+
stdout: Vec<u8>,
68+
stderr: Vec<u8>,
69+
}
70+
71+
impl CommandOutput {
72+
pub fn is_success(&self) -> bool {
73+
self.status.success()
74+
}
75+
76+
pub fn is_failure(&self) -> bool {
77+
!self.is_success()
78+
}
79+
80+
pub fn status(&self) -> ExitStatus {
81+
self.status
82+
}
83+
84+
pub fn stdout(&self) -> String {
85+
String::from_utf8(self.stdout.clone()).expect("Cannot parse process stdout as UTF-8")
86+
}
87+
88+
pub fn stderr(&self) -> String {
89+
String::from_utf8(self.stderr.clone()).expect("Cannot parse process stderr as UTF-8")
90+
}
91+
}
92+
93+
impl From<Output> for CommandOutput {
94+
fn from(output: Output) -> Self {
95+
Self { status: output.status, stdout: output.stdout, stderr: output.stderr }
96+
}
97+
}
98+
99+
impl From<ExitStatus> for CommandOutput {
100+
fn from(status: ExitStatus) -> Self {
101+
Self { status, stdout: Default::default(), stderr: Default::default() }
102+
}
103+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy