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::io;
use std::path::{Path, PathBuf};
use std::process::{Command, Output, Stdio};
use std::process::{Command, Stdio};
use std::str;
use std::sync::OnceLock;
use std::time::SystemTime;
@ -41,7 +41,7 @@ use crate::core::builder::Kind;
use crate::core::config::{flags, LldMode};
use crate::core::config::{DryRun, Target};
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};
mod core;
@ -943,18 +943,10 @@ impl Build {
self.verbose(|| println!("running: {command:?}"));
let output: io::Result<Output> = match command.output_mode {
OutputMode::Print => command.command.status().map(|status| Output {
status,
stdout: vec![],
stderr: vec![],
}),
OutputMode::CaptureAll => command.command.output(),
OutputMode::CaptureStdout => {
command.command.stderr(Stdio::inherit());
command.command.output()
}
};
command.command.stdout(command.stdout.stdio());
command.command.stderr(command.stderr.stdio());
let output = command.command.output();
use std::fmt::Write;
@ -973,16 +965,15 @@ impl Build {
.unwrap();
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 matches!(command.output_mode, OutputMode::CaptureAll) {
writeln!(message, "\nSTDERR ----\n{}", output.stderr().trim()).unwrap();
}
// If the output mode is OutputMode::Capture, we can now print the output.
// If it is OutputMode::Print, then the output has already been printed to
// 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
}

View File

@ -1,6 +1,6 @@
use std::ffi::OsStr;
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.
#[derive(Debug, Copy, Clone)]
@ -13,19 +13,30 @@ pub enum BehaviorOnFailure {
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)]
pub enum OutputMode {
/// Prints the stdout/stderr of the command to stdout/stderr of bootstrap (by inheriting these
/// streams).
/// Corresponds to calling `cmd.status()`.
/// Prints the stream by inheriting it from the bootstrap process.
Print,
/// Captures the stdout and stderr of the command into memory.
/// Corresponds to calling `cmd.output()`.
CaptureAll,
/// Captures the stdout of the command into memory, inherits stderr.
/// Corresponds to calling `cmd.output()`.
CaptureStdout,
/// Captures the stream into memory.
Capture,
}
impl OutputMode {
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`.
@ -45,7 +56,8 @@ pub enum OutputMode {
pub struct BootstrapCommand {
pub command: Command,
pub failure_behavior: BehaviorOnFailure,
pub output_mode: OutputMode,
pub stdout: OutputMode,
pub stderr: OutputMode,
// Run the command even during dry run
pub run_always: bool,
}
@ -113,14 +125,14 @@ impl BootstrapCommand {
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 {
Self { output_mode: OutputMode::CaptureAll, ..self }
Self { stdout: OutputMode::Capture, stderr: OutputMode::Capture, ..self }
}
/// Capture stdout of the command, do not print it.
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 {
command,
failure_behavior: BehaviorOnFailure::Exit,
output_mode: OutputMode::Print,
stdout: OutputMode::Print,
stderr: OutputMode::Print,
run_always: false,
}
}