Simplify and generalize implementation of output mode

This commit is contained in:
Jakub Beránek 2024-07-03 21:04:02 +02:00
parent b90129dd21
commit b618fea358
2 changed files with 43 additions and 39 deletions

View File

@ -23,7 +23,7 @@ use std::fmt::Display;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io; use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::{Command, Output, Stdio}; use std::process::{Command, Stdio};
use std::str; use std::str;
use std::sync::OnceLock; use std::sync::OnceLock;
use std::time::SystemTime; use std::time::SystemTime;
@ -41,7 +41,7 @@ use crate::core::builder::Kind;
use crate::core::config::{flags, LldMode}; use crate::core::config::{flags, LldMode};
use crate::core::config::{DryRun, Target}; use crate::core::config::{DryRun, Target};
use crate::core::config::{LlvmLibunwind, TargetSelection}; use crate::core::config::{LlvmLibunwind, TargetSelection};
use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, CommandOutput, OutputMode}; use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, CommandOutput};
use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir}; use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir};
mod core; mod core;
@ -943,18 +943,10 @@ impl Build {
self.verbose(|| println!("running: {command:?}")); self.verbose(|| println!("running: {command:?}"));
let output: io::Result<Output> = match command.output_mode { command.command.stdout(command.stdout.stdio());
OutputMode::Print => command.command.status().map(|status| Output { command.command.stderr(command.stderr.stdio());
status,
stdout: vec![], let output = command.command.output();
stderr: vec![],
}),
OutputMode::CaptureAll => command.command.output(),
OutputMode::CaptureStdout => {
command.command.stderr(Stdio::inherit());
command.command.output()
}
};
use std::fmt::Write; use std::fmt::Write;
@ -973,16 +965,15 @@ impl Build {
.unwrap(); .unwrap();
let output: CommandOutput = output.into(); let output: CommandOutput = output.into();
// If the output mode is OutputMode::Print, the output has already been printed to
// stdout/stderr, and we thus don't have anything captured to print anyway.
if matches!(command.output_mode, OutputMode::CaptureAll | OutputMode::CaptureStdout)
{
writeln!(message, "\nSTDOUT ----\n{}", output.stdout().trim()).unwrap();
// Stderr is added to the message only if it was captured // If the output mode is OutputMode::Capture, we can now print the output.
if matches!(command.output_mode, OutputMode::CaptureAll) { // If it is OutputMode::Print, then the output has already been printed to
writeln!(message, "\nSTDERR ----\n{}", output.stderr().trim()).unwrap(); // stdout/stderr, and we thus don't have anything captured to print anyway.
} if command.stdout.captures() {
writeln!(message, "\nSTDOUT ----\n{}", output.stdout().trim()).unwrap();
}
if command.stderr.captures() {
writeln!(message, "\nSTDERR ----\n{}", output.stderr().trim()).unwrap();
} }
output output
} }

View File

@ -1,6 +1,6 @@
use std::ffi::OsStr; use std::ffi::OsStr;
use std::path::Path; use std::path::Path;
use std::process::{Command, CommandArgs, CommandEnvs, ExitStatus, Output}; use std::process::{Command, CommandArgs, CommandEnvs, ExitStatus, Output, Stdio};
/// What should be done when the command fails. /// What should be done when the command fails.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -13,19 +13,30 @@ pub enum BehaviorOnFailure {
Ignore, Ignore,
} }
/// How should the output of the command be handled (whether it should be captured or printed). /// How should the output of a specific stream of the command (stdout/stderr) be handled
/// (whether it should be captured or printed).
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum OutputMode { pub enum OutputMode {
/// Prints the stdout/stderr of the command to stdout/stderr of bootstrap (by inheriting these /// Prints the stream by inheriting it from the bootstrap process.
/// streams).
/// Corresponds to calling `cmd.status()`.
Print, Print,
/// Captures the stdout and stderr of the command into memory. /// Captures the stream into memory.
/// Corresponds to calling `cmd.output()`. Capture,
CaptureAll, }
/// Captures the stdout of the command into memory, inherits stderr.
/// Corresponds to calling `cmd.output()`. impl OutputMode {
CaptureStdout, pub fn captures(&self) -> bool {
match self {
OutputMode::Print => false,
OutputMode::Capture => true,
}
}
pub fn stdio(&self) -> Stdio {
match self {
OutputMode::Print => Stdio::inherit(),
OutputMode::Capture => Stdio::piped(),
}
}
} }
/// Wrapper around `std::process::Command`. /// Wrapper around `std::process::Command`.
@ -45,7 +56,8 @@ pub enum OutputMode {
pub struct BootstrapCommand { pub struct BootstrapCommand {
pub command: Command, pub command: Command,
pub failure_behavior: BehaviorOnFailure, pub failure_behavior: BehaviorOnFailure,
pub output_mode: OutputMode, pub stdout: OutputMode,
pub stderr: OutputMode,
// Run the command even during dry run // Run the command even during dry run
pub run_always: bool, pub run_always: bool,
} }
@ -113,14 +125,14 @@ impl BootstrapCommand {
self self
} }
/// Capture the output of the command, do not print it. /// Capture all output of the command, do not print it.
pub fn capture(self) -> Self { pub fn capture(self) -> Self {
Self { output_mode: OutputMode::CaptureAll, ..self } Self { stdout: OutputMode::Capture, stderr: OutputMode::Capture, ..self }
} }
/// Capture stdout of the command, do not print it. /// Capture stdout of the command, do not print it.
pub fn capture_stdout(self) -> Self { pub fn capture_stdout(self) -> Self {
Self { output_mode: OutputMode::CaptureStdout, ..self } Self { stdout: OutputMode::Capture, ..self }
} }
} }
@ -137,7 +149,8 @@ impl From<Command> for BootstrapCommand {
Self { Self {
command, command,
failure_behavior: BehaviorOnFailure::Exit, failure_behavior: BehaviorOnFailure::Exit,
output_mode: OutputMode::Print, stdout: OutputMode::Print,
stderr: OutputMode::Print,
run_always: false, run_always: false,
} }
} }