about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJakub Beránek <berykubik@gmail.com>2024-06-07 14:50:03 +0200
committerJakub Beránek <berykubik@gmail.com>2024-06-08 19:34:02 +0200
commit18ae9afa826006cf2f78a0defda286fcaf4bee99 (patch)
treedfe13da71af03689797b4db6d1fb250a07a11e55 /src
parentcfdb6175c2286acdd0c7d71a2ac9eefb777eec09 (diff)
downloadrust-18ae9afa826006cf2f78a0defda286fcaf4bee99.tar.gz
rust-18ae9afa826006cf2f78a0defda286fcaf4bee99.zip
Introduce a custom `Command` wrapper in `run-make-support`
Diffstat (limited to 'src')
-rw-r--r--src/tools/run-make-support/src/cc.rs2
-rw-r--r--src/tools/run-make-support/src/clang.rs7
-rw-r--r--src/tools/run-make-support/src/command.rs91
-rw-r--r--src/tools/run-make-support/src/lib.rs38
-rw-r--r--src/tools/run-make-support/src/llvm_readobj.rs8
-rw-r--r--src/tools/run-make-support/src/run.rs14
-rw-r--r--src/tools/run-make-support/src/rustc.rs46
-rw-r--r--src/tools/run-make-support/src/rustdoc.rs45
8 files changed, 129 insertions, 122 deletions
diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs
index b33004974bf..bfed6d922ab 100644
--- a/src/tools/run-make-support/src/cc.rs
+++ b/src/tools/run-make-support/src/cc.rs
@@ -1,7 +1,7 @@
 use std::path::Path;
-use std::process::Command;
 
 use crate::{bin_name, cygpath_windows, env_var, handle_failed_output, is_msvc, is_windows, uname};
+use crate::command::Command;
 
 /// Construct a new platform-specific C compiler invocation.
 ///
diff --git a/src/tools/run-make-support/src/clang.rs b/src/tools/run-make-support/src/clang.rs
index 7d9246b5222..2ceea3df95e 100644
--- a/src/tools/run-make-support/src/clang.rs
+++ b/src/tools/run-make-support/src/clang.rs
@@ -1,7 +1,7 @@
 use std::path::Path;
-use std::process::Command;
 
 use crate::{bin_name, env_var, handle_failed_output};
+use crate::command::Command;
 
 /// Construct a new `clang` invocation. `clang` is not always available for all targets.
 pub fn clang() -> Clang {
@@ -68,9 +68,4 @@ impl Clang {
         self.cmd.arg(format!("-fuse-ld={ld}"));
         self
     }
-
-    /// Get the [`Output`][::std::process::Output] of the finished process.
-    pub fn command_output(&mut self) -> ::std::process::Output {
-        self.cmd.output().expect("failed to get output of finished process")
-    }
 }
diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs
new file mode 100644
index 00000000000..c142c80024b
--- /dev/null
+++ b/src/tools/run-make-support/src/command.rs
@@ -0,0 +1,91 @@
+use std::ffi::OsStr;
+use std::io::Write;
+use std::ops::{Deref, DerefMut};
+use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
+
+#[derive(Debug)]
+pub struct Command {
+    cmd: StdCommand,
+    stdin: Option<Box<[u8]>>,
+}
+
+impl Command {
+    pub fn new<S: AsRef<OsStr>>(program: S) -> Self {
+        Self {
+            cmd: StdCommand::new(program),
+            stdin: None,
+        }
+    }
+
+    pub fn set_stdin(&mut self, stdin: Box<[u8]>) {
+        self.stdin = Some(stdin);
+    }
+
+    #[track_caller]
+    pub(crate) fn command_output(&mut self) -> CompletedProcess {
+        // let's make sure we piped all the input and outputs
+        self.cmd.stdin(Stdio::piped());
+        self.cmd.stdout(Stdio::piped());
+        self.cmd.stderr(Stdio::piped());
+
+        let output = if let Some(input) = &self.stdin {
+            let mut child = self.cmd.spawn().unwrap();
+
+            {
+                let mut stdin = child.stdin.take().unwrap();
+                stdin.write_all(input.as_ref()).unwrap();
+            }
+
+            child.wait_with_output().expect("failed to get output of finished process")
+        } else {
+            self.cmd.output().expect("failed to get output of finished process")
+        };
+        output.into()
+    }
+}
+
+impl Deref for Command {
+    type Target = StdCommand;
+
+    fn deref(&self) -> &Self::Target {
+        &self.cmd
+    }
+}
+
+impl DerefMut for Command {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.cmd
+    }
+}
+
+/// Represents the result of an executed process.
+pub struct CompletedProcess {
+    output: Output,
+}
+
+impl CompletedProcess {
+    pub fn stdout_utf8(&self) -> String {
+        String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8")
+    }
+
+    pub fn stderr_utf8(&self) -> String {
+        String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8")
+    }
+
+    pub fn status(&self) -> ExitStatus {
+        self.output.status
+    }
+
+    #[track_caller]
+    pub fn assert_exit_code(&self, code: i32) {
+        assert!(self.output.status.code() == Some(code));
+    }
+}
+
+impl From<Output> for CompletedProcess {
+    fn from(output: Output) -> Self {
+        Self {
+            output
+        }
+    }
+}
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 0d167960c16..c22ff12814b 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -10,13 +10,13 @@ pub mod llvm_readobj;
 pub mod run;
 pub mod rustc;
 pub mod rustdoc;
+mod command;
 
 use std::env;
 use std::ffi::OsString;
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
-use std::process::{Command, Output};
 
 pub use gimli;
 pub use object;
@@ -167,13 +167,12 @@ pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
     let mut cygpath = Command::new("cygpath");
     cygpath.arg("-w");
     cygpath.arg(path.as_ref());
-    let output = cygpath.output().unwrap();
-    if !output.status.success() {
+    let output = cygpath.command_output();
+    if !output.status().success() {
         handle_failed_output(&cygpath, output, caller_line_number);
     }
-    let s = String::from_utf8(output.stdout).unwrap();
     // cygpath -w can attach a newline
-    s.trim().to_string()
+    output.stdout_utf8().trim().to_string()
 }
 
 /// Run `uname`. This assumes that `uname` is available on the platform!
@@ -183,23 +182,23 @@ pub fn uname() -> String {
     let caller_line_number = caller_location.line();
 
     let mut uname = Command::new("uname");
-    let output = uname.output().unwrap();
-    if !output.status.success() {
+    let output = uname.command_output();
+    if !output.status().success() {
         handle_failed_output(&uname, output, caller_line_number);
     }
-    String::from_utf8(output.stdout).unwrap()
+    output.stdout_utf8()
 }
 
-fn handle_failed_output(cmd: &Command, output: Output, caller_line_number: u32) -> ! {
-    if output.status.success() {
+fn handle_failed_output(cmd: &Command, output: CompletedProcess, caller_line_number: u32) -> ! {
+    if output.status().success() {
         eprintln!("command unexpectedly succeeded at line {caller_line_number}");
     } else {
         eprintln!("command failed at line {caller_line_number}");
     }
     eprintln!("{cmd:?}");
-    eprintln!("output status: `{}`", output.status);
-    eprintln!("=== STDOUT ===\n{}\n\n", String::from_utf8(output.stdout).unwrap());
-    eprintln!("=== STDERR ===\n{}\n\n", String::from_utf8(output.stderr).unwrap());
+    eprintln!("output status: `{}`", output.status());
+    eprintln!("=== STDOUT ===\n{}\n\n", output.stdout_utf8());
+    eprintln!("=== STDERR ===\n{}\n\n", output.stderr_utf8());
     std::process::exit(1)
 }
 
@@ -412,12 +411,12 @@ macro_rules! impl_common_helpers {
 
             /// Run the constructed command and assert that it is successfully run.
             #[track_caller]
-            pub fn run(&mut self) -> ::std::process::Output {
+            pub fn run(&mut self) -> crate::command::CompletedProcess {
                 let caller_location = ::std::panic::Location::caller();
                 let caller_line_number = caller_location.line();
 
-                let output = self.command_output();
-                if !output.status.success() {
+                let output = self.cmd.command_output();
+                if !output.status().success() {
                     handle_failed_output(&self.cmd, output, caller_line_number);
                 }
                 output
@@ -425,12 +424,12 @@ macro_rules! impl_common_helpers {
 
             /// Run the constructed command and assert that it does not successfully run.
             #[track_caller]
-            pub fn run_fail(&mut self) -> ::std::process::Output {
+            pub fn run_fail(&mut self) -> crate::command::CompletedProcess {
                 let caller_location = ::std::panic::Location::caller();
                 let caller_line_number = caller_location.line();
 
-                let output = self.command_output();
-                if output.status.success() {
+                let output = self.cmd.command_output();
+                if output.status().success() {
                     handle_failed_output(&self.cmd, output, caller_line_number);
                 }
                 output
@@ -446,3 +445,4 @@ macro_rules! impl_common_helpers {
 }
 
 pub(crate) use impl_common_helpers;
+use crate::command::{Command, CompletedProcess};
diff --git a/src/tools/run-make-support/src/llvm_readobj.rs b/src/tools/run-make-support/src/llvm_readobj.rs
index 77aaadfe18c..a834d3a2e19 100644
--- a/src/tools/run-make-support/src/llvm_readobj.rs
+++ b/src/tools/run-make-support/src/llvm_readobj.rs
@@ -1,7 +1,7 @@
 use std::path::{Path, PathBuf};
-use std::process::Command;
 
 use crate::{env_var, handle_failed_output};
+use crate::command::Command;
 
 /// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
 /// at `$LLVM_BIN_DIR/llvm-readobj`.
@@ -39,10 +39,4 @@ impl LlvmReadobj {
         self.cmd.arg("--file-header");
         self
     }
-
-    /// Get the [`Output`][::std::process::Output] of the finished process.
-    #[track_caller]
-    pub fn command_output(&mut self) -> ::std::process::Output {
-        self.cmd.output().expect("failed to get output of finished process")
-    }
 }
diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs
index b607c583e32..09ad98c2451 100644
--- a/src/tools/run-make-support/src/run.rs
+++ b/src/tools/run-make-support/src/run.rs
@@ -1,12 +1,12 @@
 use std::env;
 use std::path::{Path, PathBuf};
-use std::process::{Command, Output};
 
 use crate::{cwd, env_var, is_windows};
+use crate::command::{Command, CompletedProcess};
 
 use super::handle_failed_output;
 
-fn run_common(name: &str) -> (Command, Output) {
+fn run_common(name: &str) -> (Command, CompletedProcess) {
     let mut bin_path = PathBuf::new();
     bin_path.push(cwd());
     bin_path.push(name);
@@ -33,18 +33,18 @@ fn run_common(name: &str) -> (Command, Output) {
         cmd.env("PATH", env::join_paths(paths.iter()).unwrap());
     }
 
-    let output = cmd.output().unwrap();
+    let output = cmd.command_output();
     (cmd, output)
 }
 
 /// Run a built binary and make sure it succeeds.
 #[track_caller]
-pub fn run(name: &str) -> Output {
+pub fn run(name: &str) -> CompletedProcess {
     let caller_location = std::panic::Location::caller();
     let caller_line_number = caller_location.line();
 
     let (cmd, output) = run_common(name);
-    if !output.status.success() {
+    if !output.status().success() {
         handle_failed_output(&cmd, output, caller_line_number);
     }
     output
@@ -52,12 +52,12 @@ pub fn run(name: &str) -> Output {
 
 /// Run a built binary and make sure it fails.
 #[track_caller]
-pub fn run_fail(name: &str) -> Output {
+pub fn run_fail(name: &str) -> CompletedProcess {
     let caller_location = std::panic::Location::caller();
     let caller_line_number = caller_location.line();
 
     let (cmd, output) = run_common(name);
-    if output.status.success() {
+    if output.status().success() {
         handle_failed_output(&cmd, output, caller_line_number);
     }
     output
diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs
index a64dd9d30cf..9bbe30bcb2d 100644
--- a/src/tools/run-make-support/src/rustc.rs
+++ b/src/tools/run-make-support/src/rustc.rs
@@ -1,9 +1,8 @@
 use std::ffi::{OsStr, OsString};
-use std::io::Write;
 use std::path::Path;
-use std::process::{Command, Output, Stdio};
+use command::Command;
 
-use crate::{cwd, env_var, handle_failed_output, set_host_rpath};
+use crate::{command, cwd, env_var, handle_failed_output, set_host_rpath};
 
 /// Construct a new `rustc` invocation.
 pub fn rustc() -> Rustc {
@@ -19,7 +18,6 @@ pub fn aux_build() -> Rustc {
 #[derive(Debug)]
 pub struct Rustc {
     cmd: Command,
-    stdin: Option<Box<[u8]>>,
 }
 
 crate::impl_common_helpers!(Rustc);
@@ -38,14 +36,14 @@ impl Rustc {
     /// Construct a new `rustc` invocation.
     pub fn new() -> Self {
         let cmd = setup_common();
-        Self { cmd, stdin: None }
+        Self { cmd }
     }
 
     /// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`).
     pub fn new_aux_build() -> Self {
         let mut cmd = setup_common();
         cmd.arg("--crate-type=lib");
-        Self { cmd, stdin: None }
+        Self { cmd }
     }
 
     // Argument provider methods
@@ -197,7 +195,7 @@ impl Rustc {
 
     /// Specify a stdin input
     pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
-        self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
+        self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
         self
     }
 
@@ -213,38 +211,4 @@ impl Rustc {
         self.cmd.arg(format!("-Clinker={linker}"));
         self
     }
-
-    /// Get the [`Output`] of the finished process.
-    #[track_caller]
-    pub fn command_output(&mut self) -> Output {
-        // let's make sure we piped all the input and outputs
-        self.cmd.stdin(Stdio::piped());
-        self.cmd.stdout(Stdio::piped());
-        self.cmd.stderr(Stdio::piped());
-
-        if let Some(input) = &self.stdin {
-            let mut child = self.cmd.spawn().unwrap();
-
-            {
-                let mut stdin = child.stdin.take().unwrap();
-                stdin.write_all(input.as_ref()).unwrap();
-            }
-
-            child.wait_with_output().expect("failed to get output of finished process")
-        } else {
-            self.cmd.output().expect("failed to get output of finished process")
-        }
-    }
-
-    #[track_caller]
-    pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
-        let caller_location = std::panic::Location::caller();
-        let caller_line_number = caller_location.line();
-
-        let output = self.command_output();
-        if output.status.code().unwrap() != code {
-            handle_failed_output(&self.cmd, output, caller_line_number);
-        }
-        output
-    }
 }
diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
index 34d32992e65..c75bb1d1196 100644
--- a/src/tools/run-make-support/src/rustdoc.rs
+++ b/src/tools/run-make-support/src/rustdoc.rs
@@ -1,9 +1,8 @@
 use std::ffi::OsStr;
-use std::io::Write;
 use std::path::Path;
-use std::process::{Command, Output, Stdio};
 
 use crate::{env_var, env_var_os, handle_failed_output, set_host_rpath};
+use crate::command::Command;
 
 /// Construct a plain `rustdoc` invocation with no flags set.
 pub fn bare_rustdoc() -> Rustdoc {
@@ -18,7 +17,6 @@ pub fn rustdoc() -> Rustdoc {
 #[derive(Debug)]
 pub struct Rustdoc {
     cmd: Command,
-    stdin: Option<Box<[u8]>>,
 }
 
 crate::impl_common_helpers!(Rustdoc);
@@ -34,7 +32,7 @@ impl Rustdoc {
     /// Construct a bare `rustdoc` invocation.
     pub fn bare() -> Self {
         let cmd = setup_common();
-        Self { cmd, stdin: None }
+        Self { cmd }
     }
 
     /// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
@@ -42,7 +40,7 @@ impl Rustdoc {
         let mut cmd = setup_common();
         let target_rpath_dir = env_var_os("TARGET_RPATH_DIR");
         cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
-        Self { cmd, stdin: None }
+        Self { cmd }
     }
 
     /// Specify where an external library is located.
@@ -88,33 +86,10 @@ impl Rustdoc {
 
     /// Specify a stdin input
     pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
-        self.cmd.stdin(Stdio::piped());
-        self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
+        self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
         self
     }
 
-    /// Get the [`Output`] of the finished process.
-    #[track_caller]
-    pub fn command_output(&mut self) -> ::std::process::Output {
-        // let's make sure we piped all the input and outputs
-        self.cmd.stdin(Stdio::piped());
-        self.cmd.stdout(Stdio::piped());
-        self.cmd.stderr(Stdio::piped());
-
-        if let Some(input) = &self.stdin {
-            let mut child = self.cmd.spawn().unwrap();
-
-            {
-                let mut stdin = child.stdin.take().unwrap();
-                stdin.write_all(input.as_ref()).unwrap();
-            }
-
-            child.wait_with_output().expect("failed to get output of finished process")
-        } else {
-            self.cmd.output().expect("failed to get output of finished process")
-        }
-    }
-
     /// Specify the edition year.
     pub fn edition(&mut self, edition: &str) -> &mut Self {
         self.cmd.arg("--edition");
@@ -156,16 +131,4 @@ impl Rustdoc {
         self.cmd.arg(format);
         self
     }
-
-    #[track_caller]
-    pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
-        let caller_location = std::panic::Location::caller();
-        let caller_line_number = caller_location.line();
-
-        let output = self.command_output();
-        if output.status.code().unwrap() != code {
-            handle_failed_output(&self.cmd, output, caller_line_number);
-        }
-        output
-    }
 }