Add behavior on failure to BootstrapCommand

This commit is contained in:
Jakub Beránek 2023-10-10 20:19:22 +02:00
parent a69edc68aa
commit 0e090e740c
No known key found for this signature in database
GPG key ID: 909CD0D26483516B
2 changed files with 37 additions and 37 deletions

View file

@ -39,11 +39,8 @@ use crate::core::config::flags;
use crate::core::config::{DryRun, Target};
use crate::core::config::{LlvmLibunwind, TargetSelection};
use crate::utils::cache::{Interned, INTERNER};
use crate::utils::exec::BootstrapCommand;
use crate::utils::helpers::{
self, dir_is_empty, exe, libdir, mtime, output, run, run_suppressed, symlink_dir,
try_run_suppressed,
};
use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand};
use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir};
mod core;
mod utils;
@ -922,44 +919,30 @@ impl Build {
/// Runs a command, printing out nice contextual information if it fails.
fn run(&self, cmd: &mut Command) {
if self.config.dry_run() {
return;
}
self.verbose(&format!("running: {cmd:?}"));
run(cmd, self.is_verbose())
// FIXME: output mode -> status + err if self.is_verbose()
let cmd: BootstrapCommand<'_> = cmd.into();
self.run_cmd(cmd.fail_fast());
}
/// Runs a command, printing out nice contextual information if it fails.
fn run_quiet(&self, cmd: &mut Command) {
if self.config.dry_run() {
return;
}
self.verbose(&format!("running: {cmd:?}"));
run_suppressed(cmd)
// FIXME: output mode -> output + err
let cmd: BootstrapCommand<'_> = cmd.into();
self.run_cmd(cmd.fail_fast());
}
/// Runs a command, printing out nice contextual information if it fails.
/// Exits if the command failed to execute at all, otherwise returns its
/// `status.success()`.
fn run_quiet_delaying_failure(&self, cmd: &mut Command) -> bool {
if self.config.dry_run() {
return true;
}
if !self.fail_fast {
self.verbose(&format!("running: {cmd:?}"));
if !try_run_suppressed(cmd) {
let mut failures = self.delayed_failures.borrow_mut();
failures.push(format!("{cmd:?}"));
return false;
}
} else {
self.run_quiet(cmd);
}
true
// FIXME: output mode -> output + err
let cmd: BootstrapCommand<'_> = cmd.into();
self.run_cmd(cmd.delay_failure())
}
/// Runs a command, printing out contextual info if it fails, and delaying errors until the build finishes.
pub(crate) fn run_delaying_failure(&self, cmd: &mut Command) -> bool {
// FIXME: output mode -> status + err if self.is_verbose()
let cmd: BootstrapCommand<'_> = cmd.into();
self.run_cmd(cmd.delay_failure())
}
@ -975,10 +958,16 @@ impl Build {
match result {
Ok(_) => true,
Err(_) => {
if command.delay_failure {
let mut failures = self.delayed_failures.borrow_mut();
failures.push(format!("{command:?}"));
return false;
if let Some(failure_behavior) = command.failure_behavior {
match failure_behavior {
BehaviorOnFailure::DelayFail => {
let mut failures = self.delayed_failures.borrow_mut();
failures.push(format!("{command:?}"));
}
BehaviorOnFailure::Exit => {
exit!(1);
}
}
}
if self.fail_fast {
exit!(1);

View file

@ -1,21 +1,32 @@
use std::process::Command;
/// What should be done when the command fails.
#[derive(Debug, Copy, Clone)]
pub enum BehaviorOnFailure {
/// Immediately stop bootstrap.
Exit,
/// Delay failure until the end of bootstrap invocation.
DelayFail,
}
/// Wrapper around `std::process::Command`.
#[derive(Debug)]
pub struct BootstrapCommand<'a> {
pub command: &'a mut Command,
/// Report failure later instead of immediately.
pub delay_failure: bool,
pub failure_behavior: Option<BehaviorOnFailure>,
}
impl<'a> BootstrapCommand<'a> {
pub fn delay_failure(self) -> Self {
Self { delay_failure: true, ..self }
Self { failure_behavior: Some(BehaviorOnFailure::DelayFail), ..self }
}
pub fn fail_fast(self) -> Self {
Self { failure_behavior: Some(BehaviorOnFailure::Exit), ..self }
}
}
impl<'a> From<&'a mut Command> for BootstrapCommand<'a> {
fn from(command: &'a mut Command) -> Self {
Self { command, delay_failure: false }
Self { command, failure_behavior: None }
}
}