mirror of
https://github.com/rust-lang/cargo
synced 2024-07-05 01:19:13 +00:00
Move ProcessBuilder to cargo-util.
This commit is contained in:
parent
669340333a
commit
888100352a
1
.github/workflows/main.yml
vendored
1
.github/workflows/main.yml
vendored
|
@ -66,6 +66,7 @@ jobs:
|
|||
- run: cargo test --features 'deny-warnings'
|
||||
- run: cargo test --features 'deny-warnings' -p cargo-test-support
|
||||
- run: cargo test -p cargo-platform
|
||||
- run: cargo test -p cargo-util
|
||||
- run: cargo test --manifest-path crates/mdman/Cargo.toml
|
||||
- run: cargo build --manifest-path crates/credential/cargo-credential-1password/Cargo.toml
|
||||
- run: cargo build --manifest-path crates/credential/cargo-credential-gnome-secret/Cargo.toml
|
||||
|
|
|
@ -56,7 +56,6 @@ semver = { version = "0.10", features = ["serde"] }
|
|||
serde = { version = "1.0.123", features = ["derive"] }
|
||||
serde_ignored = "0.1.0"
|
||||
serde_json = { version = "1.0.30", features = ["raw_value"] }
|
||||
shell-escape = "0.1.4"
|
||||
strip-ansi-escapes = "0.1.0"
|
||||
tar = { version = "0.4.26", default-features = false }
|
||||
tempfile = "3.0"
|
||||
|
@ -80,7 +79,6 @@ rand = "0.8.3"
|
|||
core-foundation = { version = "0.9.0", features = ["mac_os_10_7_support"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
miow = "0.3.6"
|
||||
fwdansi = "1.1.0"
|
||||
|
||||
[target.'cfg(windows)'.dependencies.winapi]
|
||||
|
|
|
@ -11,6 +11,7 @@ doctest = false
|
|||
[dependencies]
|
||||
cargo = { path = "../.." }
|
||||
cargo-test-macro = { path = "../cargo-test-macro" }
|
||||
cargo-util = { path = "../cargo-util" }
|
||||
filetime = "0.2"
|
||||
flate2 = { version = "1.0", default-features = false, features = ["zlib"] }
|
||||
git2 = "0.13.16"
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
//! These tests are all disabled on rust-lang/rust's CI, but run in Cargo's CI.
|
||||
|
||||
use crate::{basic_manifest, main_file, project};
|
||||
use cargo::util::ProcessError;
|
||||
use cargo::CargoResult;
|
||||
use cargo_util::ProcessError;
|
||||
use std::env;
|
||||
use std::fmt::Write;
|
||||
use std::process::{Command, Output};
|
||||
|
|
|
@ -15,7 +15,8 @@ use std::process::{Command, Output};
|
|||
use std::str;
|
||||
use std::time::{self, Duration};
|
||||
|
||||
use cargo::util::{is_ci, CargoResult, ProcessBuilder, ProcessError, Rustc};
|
||||
use cargo::util::{is_ci, CargoResult, Rustc};
|
||||
use cargo_util::{ProcessBuilder, ProcessError};
|
||||
use serde_json::{self, Value};
|
||||
use url::Url;
|
||||
|
||||
|
@ -1569,12 +1570,12 @@ pub fn is_nightly() -> bool {
|
|||
.with(|r| r.verbose_version.contains("-nightly") || r.verbose_version.contains("-dev"))
|
||||
}
|
||||
|
||||
pub fn process<T: AsRef<OsStr>>(t: T) -> cargo::util::ProcessBuilder {
|
||||
pub fn process<T: AsRef<OsStr>>(t: T) -> ProcessBuilder {
|
||||
_process(t.as_ref())
|
||||
}
|
||||
|
||||
fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
|
||||
let mut p = cargo::util::process(t);
|
||||
fn _process(t: &OsStr) -> ProcessBuilder {
|
||||
let mut p = ProcessBuilder::new(t);
|
||||
|
||||
// In general just clear out all cargo-specific configuration already in the
|
||||
// environment. Our tests all assume a "default configuration" unless
|
||||
|
@ -1643,7 +1644,7 @@ pub trait ChannelChanger: Sized {
|
|||
fn masquerade_as_nightly_cargo(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl ChannelChanger for cargo::util::ProcessBuilder {
|
||||
impl ChannelChanger for ProcessBuilder {
|
||||
fn masquerade_as_nightly_cargo(&mut self) -> &mut Self {
|
||||
self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly")
|
||||
}
|
||||
|
|
|
@ -9,3 +9,11 @@ repository = "https://github.com/rust-lang/cargo"
|
|||
description = "Miscellaneous support code used by Cargo."
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
jobserver = "0.1.21"
|
||||
libc = "0.2"
|
||||
shell-escape = "0.1.4"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
miow = "0.3.6"
|
||||
winapi = { version = "0.3", features = ["consoleapi", "minwindef"] }
|
||||
|
|
1
crates/cargo-util/LICENSE-APACHE
Symbolic link
1
crates/cargo-util/LICENSE-APACHE
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE-APACHE
|
1
crates/cargo-util/LICENSE-MIT
Symbolic link
1
crates/cargo-util/LICENSE-MIT
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE-MIT
|
|
@ -1 +1,9 @@
|
|||
//! Miscellaneous support code used by Cargo.
|
||||
|
||||
pub use self::read2::read2;
|
||||
pub use process_builder::ProcessBuilder;
|
||||
pub use process_error::{exit_status_to_string, is_simple_exit_code, ProcessError};
|
||||
|
||||
mod process_builder;
|
||||
mod process_error;
|
||||
mod read2;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::util::{process_error, read2, CargoResult, CargoResultExt};
|
||||
use anyhow::bail;
|
||||
use crate::process_error::ProcessError;
|
||||
use crate::read2;
|
||||
use anyhow::{bail, Context, Result};
|
||||
use jobserver::Client;
|
||||
use shell_escape::escape;
|
||||
use std::collections::BTreeMap;
|
||||
|
@ -10,7 +11,7 @@ use std::iter::once;
|
|||
use std::path::Path;
|
||||
use std::process::{Command, Output, Stdio};
|
||||
|
||||
/// A builder object for an external process, similar to `std::process::Command`.
|
||||
/// A builder object for an external process, similar to [`std::process::Command`].
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ProcessBuilder {
|
||||
/// The program to execute.
|
||||
|
@ -21,10 +22,10 @@ pub struct ProcessBuilder {
|
|||
env: BTreeMap<String, Option<OsString>>,
|
||||
/// The directory to run the program from.
|
||||
cwd: Option<OsString>,
|
||||
/// The `make` jobserver. See the [jobserver crate][jobserver_docs] for
|
||||
/// The `make` jobserver. See the [jobserver crate] for
|
||||
/// more information.
|
||||
///
|
||||
/// [jobserver_docs]: https://docs.rs/jobserver/0.1.6/jobserver/
|
||||
/// [jobserver crate]: https://docs.rs/jobserver/
|
||||
jobserver: Option<Client>,
|
||||
/// `true` to include environment variable in display.
|
||||
display_env_vars: bool,
|
||||
|
@ -58,6 +59,18 @@ impl fmt::Display for ProcessBuilder {
|
|||
}
|
||||
|
||||
impl ProcessBuilder {
|
||||
/// Creates a new [`ProcessBuilder`] with the given executable path.
|
||||
pub fn new<T: AsRef<OsStr>>(cmd: T) -> ProcessBuilder {
|
||||
ProcessBuilder {
|
||||
program: cmd.as_ref().to_os_string(),
|
||||
args: Vec::new(),
|
||||
cwd: None,
|
||||
env: BTreeMap::new(),
|
||||
jobserver: None,
|
||||
display_env_vars: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// (chainable) Sets the executable for the process.
|
||||
pub fn program<T: AsRef<OsStr>>(&mut self, program: T) -> &mut ProcessBuilder {
|
||||
self.program = program.as_ref().to_os_string();
|
||||
|
@ -149,16 +162,16 @@ impl ProcessBuilder {
|
|||
}
|
||||
|
||||
/// Runs the process, waiting for completion, and mapping non-success exit codes to an error.
|
||||
pub fn exec(&self) -> CargoResult<()> {
|
||||
pub fn exec(&self) -> Result<()> {
|
||||
let mut command = self.build_command();
|
||||
let exit = command.status().chain_err(|| {
|
||||
process_error(&format!("could not execute process {}", self), None, None)
|
||||
let exit = command.status().with_context(|| {
|
||||
ProcessError::new(&format!("could not execute process {}", self), None, None)
|
||||
})?;
|
||||
|
||||
if exit.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(process_error(
|
||||
Err(ProcessError::new(
|
||||
&format!("process didn't exit successfully: {}", self),
|
||||
Some(exit),
|
||||
None,
|
||||
|
@ -182,22 +195,22 @@ impl ProcessBuilder {
|
|||
/// include our child process. If the child terminates then we'll reap them in Cargo
|
||||
/// pretty quickly, and if the child handles the signal then we won't terminate
|
||||
/// (and we shouldn't!) until the process itself later exits.
|
||||
pub fn exec_replace(&self) -> CargoResult<()> {
|
||||
pub fn exec_replace(&self) -> Result<()> {
|
||||
imp::exec_replace(self)
|
||||
}
|
||||
|
||||
/// Executes the process, returning the stdio output, or an error if non-zero exit status.
|
||||
pub fn exec_with_output(&self) -> CargoResult<Output> {
|
||||
pub fn exec_with_output(&self) -> Result<Output> {
|
||||
let mut command = self.build_command();
|
||||
|
||||
let output = command.output().chain_err(|| {
|
||||
process_error(&format!("could not execute process {}", self), None, None)
|
||||
let output = command.output().with_context(|| {
|
||||
ProcessError::new(&format!("could not execute process {}", self), None, None)
|
||||
})?;
|
||||
|
||||
if output.status.success() {
|
||||
Ok(output)
|
||||
} else {
|
||||
Err(process_error(
|
||||
Err(ProcessError::new(
|
||||
&format!("process didn't exit successfully: {}", self),
|
||||
Some(output.status),
|
||||
Some(&output),
|
||||
|
@ -217,10 +230,10 @@ impl ProcessBuilder {
|
|||
/// output.
|
||||
pub fn exec_with_streaming(
|
||||
&self,
|
||||
on_stdout_line: &mut dyn FnMut(&str) -> CargoResult<()>,
|
||||
on_stderr_line: &mut dyn FnMut(&str) -> CargoResult<()>,
|
||||
on_stdout_line: &mut dyn FnMut(&str) -> Result<()>,
|
||||
on_stderr_line: &mut dyn FnMut(&str) -> Result<()>,
|
||||
capture_output: bool,
|
||||
) -> CargoResult<Output> {
|
||||
) -> Result<Output> {
|
||||
let mut stdout = Vec::new();
|
||||
let mut stderr = Vec::new();
|
||||
|
||||
|
@ -274,7 +287,9 @@ impl ProcessBuilder {
|
|||
})?;
|
||||
child.wait()
|
||||
})()
|
||||
.chain_err(|| process_error(&format!("could not execute process {}", self), None, None))?;
|
||||
.with_context(|| {
|
||||
ProcessError::new(&format!("could not execute process {}", self), None, None)
|
||||
})?;
|
||||
let output = Output {
|
||||
status,
|
||||
stdout,
|
||||
|
@ -284,14 +299,14 @@ impl ProcessBuilder {
|
|||
{
|
||||
let to_print = if capture_output { Some(&output) } else { None };
|
||||
if let Some(e) = callback_error {
|
||||
let cx = process_error(
|
||||
let cx = ProcessError::new(
|
||||
&format!("failed to parse process output: {}", self),
|
||||
Some(output.status),
|
||||
to_print,
|
||||
);
|
||||
bail!(anyhow::Error::new(cx).context(e));
|
||||
} else if !output.status.success() {
|
||||
bail!(process_error(
|
||||
bail!(ProcessError::new(
|
||||
&format!("process didn't exit successfully: {}", self),
|
||||
Some(output.status),
|
||||
to_print,
|
||||
|
@ -333,9 +348,9 @@ impl ProcessBuilder {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use cargo::util::{ProcessBuilder, process};
|
||||
/// use cargo_util::ProcessBuilder;
|
||||
/// // Running this would execute `rustc`
|
||||
/// let cmd: ProcessBuilder = process("rustc");
|
||||
/// let cmd = ProcessBuilder::new("rustc");
|
||||
///
|
||||
/// // Running this will execute `sccache rustc`
|
||||
/// let cmd = cmd.wrapped(Some("sccache"));
|
||||
|
@ -360,28 +375,16 @@ impl ProcessBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/// A helper function to create a `ProcessBuilder`.
|
||||
pub fn process<T: AsRef<OsStr>>(cmd: T) -> ProcessBuilder {
|
||||
ProcessBuilder {
|
||||
program: cmd.as_ref().to_os_string(),
|
||||
args: Vec::new(),
|
||||
cwd: None,
|
||||
env: BTreeMap::new(),
|
||||
jobserver: None,
|
||||
display_env_vars: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
mod imp {
|
||||
use crate::util::{process_error, ProcessBuilder};
|
||||
use crate::CargoResult;
|
||||
use super::{ProcessBuilder, ProcessError};
|
||||
use anyhow::Result;
|
||||
use std::os::unix::process::CommandExt;
|
||||
|
||||
pub fn exec_replace(process_builder: &ProcessBuilder) -> CargoResult<()> {
|
||||
pub fn exec_replace(process_builder: &ProcessBuilder) -> Result<()> {
|
||||
let mut command = process_builder.build_command();
|
||||
let error = command.exec();
|
||||
Err(anyhow::Error::from(error).context(process_error(
|
||||
Err(anyhow::Error::from(error).context(ProcessError::new(
|
||||
&format!("could not execute process {}", process_builder),
|
||||
None,
|
||||
None,
|
||||
|
@ -391,8 +394,8 @@ mod imp {
|
|||
|
||||
#[cfg(windows)]
|
||||
mod imp {
|
||||
use crate::util::{process_error, ProcessBuilder};
|
||||
use crate::CargoResult;
|
||||
use super::{ProcessBuilder, ProcessError};
|
||||
use anyhow::Result;
|
||||
use winapi::shared::minwindef::{BOOL, DWORD, FALSE, TRUE};
|
||||
use winapi::um::consoleapi::SetConsoleCtrlHandler;
|
||||
|
||||
|
@ -401,10 +404,10 @@ mod imp {
|
|||
TRUE
|
||||
}
|
||||
|
||||
pub fn exec_replace(process_builder: &ProcessBuilder) -> CargoResult<()> {
|
||||
pub fn exec_replace(process_builder: &ProcessBuilder) -> Result<()> {
|
||||
unsafe {
|
||||
if SetConsoleCtrlHandler(Some(ctrlc_handler), TRUE) == FALSE {
|
||||
return Err(process_error("Could not set Ctrl-C handler.", None, None).into());
|
||||
return Err(ProcessError::new("Could not set Ctrl-C handler.", None, None).into());
|
||||
}
|
||||
}
|
||||
|
194
crates/cargo-util/src/process_error.rs
Normal file
194
crates/cargo-util/src/process_error.rs
Normal file
|
@ -0,0 +1,194 @@
|
|||
//! Error value for [`crate::ProcessBuilder`] when a process fails.
|
||||
|
||||
use std::fmt;
|
||||
use std::process::{ExitStatus, Output};
|
||||
use std::str;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProcessError {
|
||||
/// A detailed description to show to the user why the process failed.
|
||||
pub desc: String,
|
||||
|
||||
/// The exit status of the process.
|
||||
///
|
||||
/// This can be `None` if the process failed to launch (like process not
|
||||
/// found) or if the exit status wasn't a code but was instead something
|
||||
/// like termination via a signal.
|
||||
pub code: Option<i32>,
|
||||
|
||||
/// The stdout from the process.
|
||||
///
|
||||
/// This can be `None` if the process failed to launch, or the output was
|
||||
/// not captured.
|
||||
pub stdout: Option<Vec<u8>>,
|
||||
|
||||
/// The stderr from the process.
|
||||
///
|
||||
/// This can be `None` if the process failed to launch, or the output was
|
||||
/// not captured.
|
||||
pub stderr: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl fmt::Display for ProcessError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.desc.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for ProcessError {}
|
||||
|
||||
impl ProcessError {
|
||||
/// Creates a new [`ProcessError`].
|
||||
///
|
||||
/// * `status` can be `None` if the process did not launch.
|
||||
/// * `output` can be `None` if the process did not launch, or output was not captured.
|
||||
pub fn new(msg: &str, status: Option<ExitStatus>, output: Option<&Output>) -> ProcessError {
|
||||
let exit = match status {
|
||||
Some(s) => exit_status_to_string(s),
|
||||
None => "never executed".to_string(),
|
||||
};
|
||||
|
||||
Self::new_raw(
|
||||
msg,
|
||||
status.and_then(|s| s.code()),
|
||||
&exit,
|
||||
output.map(|s| s.stdout.as_slice()),
|
||||
output.map(|s| s.stderr.as_slice()),
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a new [`ProcessError`] with the raw output data.
|
||||
///
|
||||
/// * `code` can be `None` for situations like being killed by a signal on unix.
|
||||
pub fn new_raw(
|
||||
msg: &str,
|
||||
code: Option<i32>,
|
||||
status: &str,
|
||||
stdout: Option<&[u8]>,
|
||||
stderr: Option<&[u8]>,
|
||||
) -> ProcessError {
|
||||
let mut desc = format!("{} ({})", msg, status);
|
||||
|
||||
if let Some(out) = stdout {
|
||||
match str::from_utf8(out) {
|
||||
Ok(s) if !s.trim().is_empty() => {
|
||||
desc.push_str("\n--- stdout\n");
|
||||
desc.push_str(s);
|
||||
}
|
||||
Ok(..) | Err(..) => {}
|
||||
}
|
||||
}
|
||||
if let Some(out) = stderr {
|
||||
match str::from_utf8(out) {
|
||||
Ok(s) if !s.trim().is_empty() => {
|
||||
desc.push_str("\n--- stderr\n");
|
||||
desc.push_str(s);
|
||||
}
|
||||
Ok(..) | Err(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
ProcessError {
|
||||
desc,
|
||||
code,
|
||||
stdout: stdout.map(|s| s.to_vec()),
|
||||
stderr: stderr.map(|s| s.to_vec()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts an [`ExitStatus`] to a human-readable string suitable for
|
||||
/// displaying to a user.
|
||||
pub fn exit_status_to_string(status: ExitStatus) -> String {
|
||||
return status_to_string(status);
|
||||
|
||||
#[cfg(unix)]
|
||||
fn status_to_string(status: ExitStatus) -> String {
|
||||
use std::os::unix::process::*;
|
||||
|
||||
if let Some(signal) = status.signal() {
|
||||
let name = match signal as libc::c_int {
|
||||
libc::SIGABRT => ", SIGABRT: process abort signal",
|
||||
libc::SIGALRM => ", SIGALRM: alarm clock",
|
||||
libc::SIGFPE => ", SIGFPE: erroneous arithmetic operation",
|
||||
libc::SIGHUP => ", SIGHUP: hangup",
|
||||
libc::SIGILL => ", SIGILL: illegal instruction",
|
||||
libc::SIGINT => ", SIGINT: terminal interrupt signal",
|
||||
libc::SIGKILL => ", SIGKILL: kill",
|
||||
libc::SIGPIPE => ", SIGPIPE: write on a pipe with no one to read",
|
||||
libc::SIGQUIT => ", SIGQUIT: terminal quit signal",
|
||||
libc::SIGSEGV => ", SIGSEGV: invalid memory reference",
|
||||
libc::SIGTERM => ", SIGTERM: termination signal",
|
||||
libc::SIGBUS => ", SIGBUS: access to undefined memory",
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
libc::SIGSYS => ", SIGSYS: bad system call",
|
||||
libc::SIGTRAP => ", SIGTRAP: trace/breakpoint trap",
|
||||
_ => "",
|
||||
};
|
||||
format!("signal: {}{}", signal, name)
|
||||
} else {
|
||||
status.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn status_to_string(status: ExitStatus) -> String {
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::winnt::*;
|
||||
|
||||
let mut base = status.to_string();
|
||||
let extra = match status.code().unwrap() as DWORD {
|
||||
STATUS_ACCESS_VIOLATION => "STATUS_ACCESS_VIOLATION",
|
||||
STATUS_IN_PAGE_ERROR => "STATUS_IN_PAGE_ERROR",
|
||||
STATUS_INVALID_HANDLE => "STATUS_INVALID_HANDLE",
|
||||
STATUS_INVALID_PARAMETER => "STATUS_INVALID_PARAMETER",
|
||||
STATUS_NO_MEMORY => "STATUS_NO_MEMORY",
|
||||
STATUS_ILLEGAL_INSTRUCTION => "STATUS_ILLEGAL_INSTRUCTION",
|
||||
STATUS_NONCONTINUABLE_EXCEPTION => "STATUS_NONCONTINUABLE_EXCEPTION",
|
||||
STATUS_INVALID_DISPOSITION => "STATUS_INVALID_DISPOSITION",
|
||||
STATUS_ARRAY_BOUNDS_EXCEEDED => "STATUS_ARRAY_BOUNDS_EXCEEDED",
|
||||
STATUS_FLOAT_DENORMAL_OPERAND => "STATUS_FLOAT_DENORMAL_OPERAND",
|
||||
STATUS_FLOAT_DIVIDE_BY_ZERO => "STATUS_FLOAT_DIVIDE_BY_ZERO",
|
||||
STATUS_FLOAT_INEXACT_RESULT => "STATUS_FLOAT_INEXACT_RESULT",
|
||||
STATUS_FLOAT_INVALID_OPERATION => "STATUS_FLOAT_INVALID_OPERATION",
|
||||
STATUS_FLOAT_OVERFLOW => "STATUS_FLOAT_OVERFLOW",
|
||||
STATUS_FLOAT_STACK_CHECK => "STATUS_FLOAT_STACK_CHECK",
|
||||
STATUS_FLOAT_UNDERFLOW => "STATUS_FLOAT_UNDERFLOW",
|
||||
STATUS_INTEGER_DIVIDE_BY_ZERO => "STATUS_INTEGER_DIVIDE_BY_ZERO",
|
||||
STATUS_INTEGER_OVERFLOW => "STATUS_INTEGER_OVERFLOW",
|
||||
STATUS_PRIVILEGED_INSTRUCTION => "STATUS_PRIVILEGED_INSTRUCTION",
|
||||
STATUS_STACK_OVERFLOW => "STATUS_STACK_OVERFLOW",
|
||||
STATUS_DLL_NOT_FOUND => "STATUS_DLL_NOT_FOUND",
|
||||
STATUS_ORDINAL_NOT_FOUND => "STATUS_ORDINAL_NOT_FOUND",
|
||||
STATUS_ENTRYPOINT_NOT_FOUND => "STATUS_ENTRYPOINT_NOT_FOUND",
|
||||
STATUS_CONTROL_C_EXIT => "STATUS_CONTROL_C_EXIT",
|
||||
STATUS_DLL_INIT_FAILED => "STATUS_DLL_INIT_FAILED",
|
||||
STATUS_FLOAT_MULTIPLE_FAULTS => "STATUS_FLOAT_MULTIPLE_FAULTS",
|
||||
STATUS_FLOAT_MULTIPLE_TRAPS => "STATUS_FLOAT_MULTIPLE_TRAPS",
|
||||
STATUS_REG_NAT_CONSUMPTION => "STATUS_REG_NAT_CONSUMPTION",
|
||||
STATUS_HEAP_CORRUPTION => "STATUS_HEAP_CORRUPTION",
|
||||
STATUS_STACK_BUFFER_OVERRUN => "STATUS_STACK_BUFFER_OVERRUN",
|
||||
STATUS_ASSERTION_FAILURE => "STATUS_ASSERTION_FAILURE",
|
||||
_ => return base,
|
||||
};
|
||||
base.push_str(", ");
|
||||
base.push_str(extra);
|
||||
base
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the given process exit code is something a normal
|
||||
/// process would exit with.
|
||||
///
|
||||
/// This helps differentiate from abnormal termination codes, such as
|
||||
/// segmentation faults or signals.
|
||||
pub fn is_simple_exit_code(code: i32) -> bool {
|
||||
// Typical unix exit codes are 0 to 127.
|
||||
// Windows doesn't have anything "typical", and is a
|
||||
// 32-bit number (which appears signed here, but is really
|
||||
// unsigned). However, most of the interesting NTSTATUS
|
||||
// codes are very large. This is just a rough
|
||||
// approximation of which codes are "normal" and which
|
||||
// ones are abnormal termination.
|
||||
code >= 0 && code <= 127
|
||||
}
|
|
@ -12,6 +12,7 @@ from urllib.error import HTTPError
|
|||
|
||||
TO_PUBLISH = [
|
||||
'crates/cargo-platform',
|
||||
'crates/cargo-util',
|
||||
'crates/crates-io',
|
||||
'.',
|
||||
]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::command_prelude::*;
|
||||
use crate::util::restricted_names::is_glob_pattern;
|
||||
use crate::util::ProcessError;
|
||||
use cargo::core::Verbosity;
|
||||
use cargo::ops::{self, CompileFilter, Packages};
|
||||
use cargo_util::ProcessError;
|
||||
|
||||
pub fn cli() -> App {
|
||||
subcommand("run")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::command_prelude::*;
|
||||
use anyhow::Error;
|
||||
use cargo::ops::{self, CompileFilter, FilterRule, LibRule};
|
||||
use cargo::util::errors;
|
||||
|
||||
pub fn cli() -> App {
|
||||
subcommand("test")
|
||||
|
@ -128,7 +127,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
|
|||
let context = anyhow::format_err!("{}", err.hint(&ws, &ops.compile_opts));
|
||||
let e = match err.code {
|
||||
// Don't show "process didn't exit successfully" for simple errors.
|
||||
Some(i) if errors::is_simple_exit_code(i) => CliError::new(context, i),
|
||||
Some(i) if cargo_util::is_simple_exit_code(i) => CliError::new(context, i),
|
||||
Some(i) => CliError::new(Error::from(err).context(context), i),
|
||||
None => CliError::new(Error::from(err).context(context), 101),
|
||||
};
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
#![warn(clippy::needless_borrow)]
|
||||
#![warn(clippy::redundant_clone)]
|
||||
|
||||
use cargo::core::shell::Shell;
|
||||
use cargo::util::CliError;
|
||||
use cargo::util::{self, closest_msg, command_prelude, CargoResult, CliResult, Config};
|
||||
use cargo_util::{ProcessBuilder, ProcessError};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use cargo::core::shell::Shell;
|
||||
use cargo::util::{self, closest_msg, command_prelude, CargoResult, CliResult, Config};
|
||||
use cargo::util::{CliError, ProcessError};
|
||||
|
||||
mod cli;
|
||||
mod commands;
|
||||
|
||||
|
@ -159,7 +159,7 @@ fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> Cli
|
|||
};
|
||||
|
||||
let cargo_exe = config.cargo_exe()?;
|
||||
let err = match util::process(&command)
|
||||
let err = match ProcessBuilder::new(&command)
|
||||
.env(cargo::CARGO_ENV, cargo_exe)
|
||||
.args(args)
|
||||
.exec_replace()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::core::compiler::CompileKind;
|
||||
use crate::util::interning::InternedString;
|
||||
use crate::util::ProcessBuilder;
|
||||
use crate::util::{CargoResult, Config, RustfixDiagnosticServer};
|
||||
use anyhow::bail;
|
||||
use cargo_util::ProcessBuilder;
|
||||
use serde::ser;
|
||||
use std::cell::RefCell;
|
||||
use std::path::PathBuf;
|
||||
|
|
|
@ -3,8 +3,9 @@ use crate::core::compiler::{
|
|||
};
|
||||
use crate::core::{Dependency, Target, TargetKind, Workspace};
|
||||
use crate::util::config::{Config, StringList, TargetConfig};
|
||||
use crate::util::{paths, CargoResult, CargoResultExt, ProcessBuilder, Rustc};
|
||||
use crate::util::{paths, CargoResult, CargoResultExt, Rustc};
|
||||
use cargo_platform::{Cfg, CfgExpr};
|
||||
use cargo_util::ProcessBuilder;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::hash_map::{Entry, HashMap};
|
||||
|
|
|
@ -14,7 +14,8 @@ use serde::Serialize;
|
|||
use super::context::OutputFile;
|
||||
use super::{CompileKind, CompileMode, Context, Unit};
|
||||
use crate::core::TargetKind;
|
||||
use crate::util::{internal, CargoResult, Config, ProcessBuilder};
|
||||
use crate::util::{internal, CargoResult, Config};
|
||||
use cargo_util::ProcessBuilder;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
struct Invocation {
|
||||
|
|
|
@ -4,12 +4,13 @@ use std::ffi::{OsStr, OsString};
|
|||
use std::path::PathBuf;
|
||||
|
||||
use cargo_platform::CfgExpr;
|
||||
use cargo_util::ProcessBuilder;
|
||||
use semver::Version;
|
||||
|
||||
use super::BuildContext;
|
||||
use crate::core::compiler::{CompileKind, Metadata, Unit};
|
||||
use crate::core::Package;
|
||||
use crate::util::{self, config, join_paths, process, CargoResult, Config, ProcessBuilder};
|
||||
use crate::util::{self, config, join_paths, CargoResult, Config};
|
||||
|
||||
/// Structure with enough information to run `rustdoc --test`.
|
||||
pub struct Doctest {
|
||||
|
@ -184,7 +185,7 @@ impl<'cfg> Compilation<'cfg> {
|
|||
unit: &Unit,
|
||||
script_meta: Option<Metadata>,
|
||||
) -> CargoResult<ProcessBuilder> {
|
||||
let rustdoc = process(&*self.config.rustdoc()?);
|
||||
let rustdoc = ProcessBuilder::new(&*self.config.rustdoc()?);
|
||||
let cmd = fill_rustc_tool_env(rustdoc, unit);
|
||||
let mut p = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, true)?;
|
||||
unit.target.edition().cmd_edition_arg(&mut p);
|
||||
|
@ -207,7 +208,13 @@ impl<'cfg> Compilation<'cfg> {
|
|||
cmd: T,
|
||||
pkg: &Package,
|
||||
) -> CargoResult<ProcessBuilder> {
|
||||
self.fill_env(process(cmd), pkg, None, CompileKind::Host, false)
|
||||
self.fill_env(
|
||||
ProcessBuilder::new(cmd),
|
||||
pkg,
|
||||
None,
|
||||
CompileKind::Host,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn target_runner(&self, kind: CompileKind) -> Option<&(PathBuf, Vec<String>)> {
|
||||
|
@ -229,12 +236,12 @@ impl<'cfg> Compilation<'cfg> {
|
|||
script_meta: Option<Metadata>,
|
||||
) -> CargoResult<ProcessBuilder> {
|
||||
let builder = if let Some((runner, args)) = self.target_runner(kind) {
|
||||
let mut builder = process(runner);
|
||||
let mut builder = ProcessBuilder::new(runner);
|
||||
builder.args(args);
|
||||
builder.arg(cmd);
|
||||
builder
|
||||
} else {
|
||||
process(cmd)
|
||||
ProcessBuilder::new(cmd)
|
||||
};
|
||||
self.fill_env(builder, pkg, script_meta, kind, false)
|
||||
}
|
||||
|
|
|
@ -322,6 +322,7 @@ use std::sync::{Arc, Mutex};
|
|||
use std::time::SystemTime;
|
||||
|
||||
use anyhow::{bail, format_err};
|
||||
use cargo_util::ProcessBuilder;
|
||||
use filetime::FileTime;
|
||||
use log::{debug, info};
|
||||
use serde::de;
|
||||
|
@ -334,7 +335,7 @@ use crate::util;
|
|||
use crate::util::errors::{CargoResult, CargoResultExt};
|
||||
use crate::util::interning::InternedString;
|
||||
use crate::util::paths;
|
||||
use crate::util::{internal, path_args, profile, ProcessBuilder};
|
||||
use crate::util::{internal, path_args, profile};
|
||||
|
||||
use super::custom_build::BuildDeps;
|
||||
use super::job::{Job, Work};
|
||||
|
|
|
@ -57,6 +57,7 @@ use std::sync::Arc;
|
|||
use std::time::Duration;
|
||||
|
||||
use anyhow::format_err;
|
||||
use cargo_util::ProcessBuilder;
|
||||
use crossbeam_utils::thread::Scope;
|
||||
use jobserver::{Acquired, Client, HelperThread};
|
||||
use log::{debug, info, trace};
|
||||
|
@ -78,7 +79,7 @@ use crate::drop_eprint;
|
|||
use crate::util::diagnostic_server::{self, DiagnosticPrinter};
|
||||
use crate::util::machine_message::{self, Message as _};
|
||||
use crate::util::{self, internal, profile};
|
||||
use crate::util::{CargoResult, CargoResultExt, ProcessBuilder};
|
||||
use crate::util::{CargoResult, CargoResultExt};
|
||||
use crate::util::{Config, DependencyQueue, Progress, ProgressStyle, Queue};
|
||||
|
||||
/// This structure is backed by the `DependencyQueue` type and manages the
|
||||
|
|
|
@ -54,11 +54,12 @@ pub use crate::core::compiler::unit::{Unit, UnitInterner};
|
|||
use crate::core::manifest::TargetSourcePath;
|
||||
use crate::core::profiles::{PanicStrategy, Profile, Strip};
|
||||
use crate::core::{Feature, PackageId, Target};
|
||||
use crate::util::errors::{self, CargoResult, CargoResultExt, ProcessError, VerboseError};
|
||||
use crate::util::errors::{CargoResult, CargoResultExt, VerboseError};
|
||||
use crate::util::interning::InternedString;
|
||||
use crate::util::machine_message::Message;
|
||||
use crate::util::{self, machine_message, ProcessBuilder};
|
||||
use crate::util::{self, machine_message};
|
||||
use crate::util::{add_path_args, internal, join_paths, paths, profile};
|
||||
use cargo_util::{ProcessBuilder, ProcessError};
|
||||
|
||||
const RUSTDOC_CRATE_VERSION_FLAG: &str = "--crate-version";
|
||||
|
||||
|
@ -303,7 +304,7 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc<dyn Executor>) -> Car
|
|||
.as_ref()
|
||||
.and_then(|perr| perr.code)
|
||||
{
|
||||
Some(n) if errors::is_simple_exit_code(n) => VerboseError::new(err).into(),
|
||||
Some(n) if cargo_util::is_simple_exit_code(n) => VerboseError::new(err).into(),
|
||||
_ => err,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::core::compiler::unit::Unit;
|
|||
use crate::core::compiler::CompileKind;
|
||||
use crate::sources::CRATES_IO_REGISTRY;
|
||||
use crate::util::errors::{internal, CargoResult};
|
||||
use crate::util::ProcessBuilder;
|
||||
use cargo_util::ProcessBuilder;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::hash;
|
||||
|
|
|
@ -97,10 +97,11 @@ use std::fmt;
|
|||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{bail, Error};
|
||||
use cargo_util::ProcessBuilder;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::util::errors::CargoResult;
|
||||
use crate::util::{indented_lines, ProcessBuilder};
|
||||
use crate::util::indented_lines;
|
||||
use crate::Config;
|
||||
|
||||
pub const SEE_CHANNELS: &str =
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use std::ffi::OsString;
|
||||
|
||||
use crate::core::compiler::{Compilation, CompileKind, Doctest, UnitOutput};
|
||||
use crate::core::shell::Verbosity;
|
||||
use crate::core::{TargetKind, Workspace};
|
||||
use crate::ops;
|
||||
use crate::util::errors::CargoResult;
|
||||
use crate::util::{add_path_args, CargoTestError, Config, ProcessError, Test};
|
||||
use crate::util::{add_path_args, CargoTestError, Config, Test};
|
||||
use cargo_util::ProcessError;
|
||||
use std::ffi::OsString;
|
||||
|
||||
pub struct TestOptions {
|
||||
pub compile_opts: ops::CompileOptions,
|
||||
|
|
|
@ -46,6 +46,7 @@ use std::process::{self, Command, ExitStatus};
|
|||
use std::str;
|
||||
|
||||
use anyhow::{bail, Context, Error};
|
||||
use cargo_util::ProcessBuilder;
|
||||
use log::{debug, trace, warn};
|
||||
use rustfix::diagnostics::Diagnostic;
|
||||
use rustfix::{self, CodeFix};
|
||||
|
@ -57,7 +58,7 @@ use crate::core::{Edition, MaybePackage, Workspace};
|
|||
use crate::ops::{self, CompileOptions};
|
||||
use crate::util::diagnostic_server::{Message, RustfixDiagnosticServer};
|
||||
use crate::util::errors::CargoResult;
|
||||
use crate::util::{self, paths, Config, ProcessBuilder};
|
||||
use crate::util::{self, paths, Config};
|
||||
use crate::util::{existing_vcs_repo, LockServer, LockServerClient};
|
||||
use crate::{drop_eprint, drop_eprintln};
|
||||
|
||||
|
@ -84,7 +85,7 @@ pub fn fix(ws: &Workspace<'_>, opts: &mut FixOptions) -> CargoResult<()> {
|
|||
|
||||
// Spin up our lock server, which our subprocesses will use to synchronize fixes.
|
||||
let lock_server = LockServer::new()?;
|
||||
let mut wrapper = util::process(env::current_exe()?);
|
||||
let mut wrapper = ProcessBuilder::new(env::current_exe()?);
|
||||
wrapper.env(FIX_ENV, lock_server.addr().to_string());
|
||||
let _started = lock_server.start()?;
|
||||
|
||||
|
@ -322,7 +323,7 @@ pub fn fix_maybe_exec_rustc(config: &Config) -> CargoResult<bool> {
|
|||
let workspace_rustc = std::env::var("RUSTC_WORKSPACE_WRAPPER")
|
||||
.map(PathBuf::from)
|
||||
.ok();
|
||||
let rustc = util::process(&args.rustc).wrapped(workspace_rustc.as_ref());
|
||||
let rustc = ProcessBuilder::new(&args.rustc).wrapped(workspace_rustc.as_ref());
|
||||
|
||||
trace!("start rustfixing {:?}", args.file);
|
||||
let fixes = rustfix_crate(&lock_addr, &rustc, &args.file, &args, config)?;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
//! Registry authentication support.
|
||||
|
||||
use crate::sources::CRATES_IO_REGISTRY;
|
||||
use crate::util::{config, process_error, CargoResult, CargoResultExt, Config};
|
||||
use crate::util::{config, CargoResult, CargoResultExt, Config};
|
||||
use anyhow::bail;
|
||||
use anyhow::format_err;
|
||||
use cargo_util::ProcessError;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Command, Stdio};
|
||||
|
@ -197,7 +198,7 @@ fn run_command(
|
|||
Action::Store(_) => "failed to store token to registry",
|
||||
Action::Erase => "failed to erase token from registry",
|
||||
};
|
||||
return Err(process_error(
|
||||
return Err(ProcessError::new(
|
||||
&format!(
|
||||
"registry credential process `{}` {} `{}`",
|
||||
exe.display(),
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
use crate::core::GitReference;
|
||||
use crate::util::errors::{CargoResult, CargoResultExt};
|
||||
use crate::util::paths;
|
||||
use crate::util::process_builder::process;
|
||||
use crate::util::{network, Config, IntoUrl, Progress};
|
||||
use anyhow::{anyhow, Context};
|
||||
use cargo_util::ProcessBuilder;
|
||||
use curl::easy::List;
|
||||
use git2::{self, ErrorClass, ObjectType};
|
||||
use log::{debug, info};
|
||||
|
@ -835,7 +835,7 @@ fn fetch_with_cli(
|
|||
tags: bool,
|
||||
config: &Config,
|
||||
) -> CargoResult<()> {
|
||||
let mut cmd = process("git");
|
||||
let mut cmd = ProcessBuilder::new("git");
|
||||
cmd.arg("fetch");
|
||||
if tags {
|
||||
cmd.arg("--tags");
|
||||
|
|
|
@ -10,12 +10,13 @@ use std::sync::Arc;
|
|||
use std::thread::{self, JoinHandle};
|
||||
|
||||
use anyhow::{Context, Error};
|
||||
use cargo_util::ProcessBuilder;
|
||||
use log::warn;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::core::Edition;
|
||||
use crate::util::errors::CargoResult;
|
||||
use crate::util::{Config, ProcessBuilder};
|
||||
use crate::util::Config;
|
||||
|
||||
const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
|
||||
const PLEASE_REPORT_THIS_BUG: &str =
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
use crate::core::{TargetKind, Workspace};
|
||||
use crate::ops::CompileOptions;
|
||||
use anyhow::Error;
|
||||
use cargo_util::ProcessError;
|
||||
use std::fmt;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{ExitStatus, Output};
|
||||
use std::str;
|
||||
|
||||
pub type CargoResult<T> = anyhow::Result<T>;
|
||||
|
||||
|
@ -186,41 +185,6 @@ impl<'a> Iterator for ManifestCauses<'a> {
|
|||
|
||||
impl<'a> ::std::iter::FusedIterator for ManifestCauses<'a> {}
|
||||
|
||||
// =============================================================================
|
||||
// Process errors
|
||||
#[derive(Debug)]
|
||||
pub struct ProcessError {
|
||||
/// A detailed description to show to the user why the process failed.
|
||||
pub desc: String,
|
||||
|
||||
/// The exit status of the process.
|
||||
///
|
||||
/// This can be `None` if the process failed to launch (like process not
|
||||
/// found) or if the exit status wasn't a code but was instead something
|
||||
/// like termination via a signal.
|
||||
pub code: Option<i32>,
|
||||
|
||||
/// The stdout from the process.
|
||||
///
|
||||
/// This can be `None` if the process failed to launch, or the output was
|
||||
/// not captured.
|
||||
pub stdout: Option<Vec<u8>>,
|
||||
|
||||
/// The stderr from the process.
|
||||
///
|
||||
/// This can be `None` if the process failed to launch, or the output was
|
||||
/// not captured.
|
||||
pub stderr: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl fmt::Display for ProcessError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.desc.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for ProcessError {}
|
||||
|
||||
// =============================================================================
|
||||
// Cargo test errors.
|
||||
|
||||
|
@ -360,154 +324,6 @@ impl From<clap::Error> for CliError {
|
|||
// =============================================================================
|
||||
// Construction helpers
|
||||
|
||||
/// Creates a new process error.
|
||||
///
|
||||
/// `status` can be `None` if the process did not launch.
|
||||
/// `output` can be `None` if the process did not launch, or output was not captured.
|
||||
pub fn process_error(
|
||||
msg: &str,
|
||||
status: Option<ExitStatus>,
|
||||
output: Option<&Output>,
|
||||
) -> ProcessError {
|
||||
let exit = match status {
|
||||
Some(s) => exit_status_to_string(s),
|
||||
None => "never executed".to_string(),
|
||||
};
|
||||
|
||||
process_error_raw(
|
||||
msg,
|
||||
status.and_then(|s| s.code()),
|
||||
&exit,
|
||||
output.map(|s| s.stdout.as_slice()),
|
||||
output.map(|s| s.stderr.as_slice()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn process_error_raw(
|
||||
msg: &str,
|
||||
code: Option<i32>,
|
||||
status: &str,
|
||||
stdout: Option<&[u8]>,
|
||||
stderr: Option<&[u8]>,
|
||||
) -> ProcessError {
|
||||
let mut desc = format!("{} ({})", msg, status);
|
||||
|
||||
if let Some(out) = stdout {
|
||||
match str::from_utf8(out) {
|
||||
Ok(s) if !s.trim().is_empty() => {
|
||||
desc.push_str("\n--- stdout\n");
|
||||
desc.push_str(s);
|
||||
}
|
||||
Ok(..) | Err(..) => {}
|
||||
}
|
||||
}
|
||||
if let Some(out) = stderr {
|
||||
match str::from_utf8(out) {
|
||||
Ok(s) if !s.trim().is_empty() => {
|
||||
desc.push_str("\n--- stderr\n");
|
||||
desc.push_str(s);
|
||||
}
|
||||
Ok(..) | Err(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
ProcessError {
|
||||
desc,
|
||||
code,
|
||||
stdout: stdout.map(|s| s.to_vec()),
|
||||
stderr: stderr.map(|s| s.to_vec()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit_status_to_string(status: ExitStatus) -> String {
|
||||
return status_to_string(status);
|
||||
|
||||
#[cfg(unix)]
|
||||
fn status_to_string(status: ExitStatus) -> String {
|
||||
use std::os::unix::process::*;
|
||||
|
||||
if let Some(signal) = status.signal() {
|
||||
let name = match signal as libc::c_int {
|
||||
libc::SIGABRT => ", SIGABRT: process abort signal",
|
||||
libc::SIGALRM => ", SIGALRM: alarm clock",
|
||||
libc::SIGFPE => ", SIGFPE: erroneous arithmetic operation",
|
||||
libc::SIGHUP => ", SIGHUP: hangup",
|
||||
libc::SIGILL => ", SIGILL: illegal instruction",
|
||||
libc::SIGINT => ", SIGINT: terminal interrupt signal",
|
||||
libc::SIGKILL => ", SIGKILL: kill",
|
||||
libc::SIGPIPE => ", SIGPIPE: write on a pipe with no one to read",
|
||||
libc::SIGQUIT => ", SIGQUIT: terminal quit signal",
|
||||
libc::SIGSEGV => ", SIGSEGV: invalid memory reference",
|
||||
libc::SIGTERM => ", SIGTERM: termination signal",
|
||||
libc::SIGBUS => ", SIGBUS: access to undefined memory",
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
libc::SIGSYS => ", SIGSYS: bad system call",
|
||||
libc::SIGTRAP => ", SIGTRAP: trace/breakpoint trap",
|
||||
_ => "",
|
||||
};
|
||||
format!("signal: {}{}", signal, name)
|
||||
} else {
|
||||
status.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn status_to_string(status: ExitStatus) -> String {
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::winnt::*;
|
||||
|
||||
let mut base = status.to_string();
|
||||
let extra = match status.code().unwrap() as DWORD {
|
||||
STATUS_ACCESS_VIOLATION => "STATUS_ACCESS_VIOLATION",
|
||||
STATUS_IN_PAGE_ERROR => "STATUS_IN_PAGE_ERROR",
|
||||
STATUS_INVALID_HANDLE => "STATUS_INVALID_HANDLE",
|
||||
STATUS_INVALID_PARAMETER => "STATUS_INVALID_PARAMETER",
|
||||
STATUS_NO_MEMORY => "STATUS_NO_MEMORY",
|
||||
STATUS_ILLEGAL_INSTRUCTION => "STATUS_ILLEGAL_INSTRUCTION",
|
||||
STATUS_NONCONTINUABLE_EXCEPTION => "STATUS_NONCONTINUABLE_EXCEPTION",
|
||||
STATUS_INVALID_DISPOSITION => "STATUS_INVALID_DISPOSITION",
|
||||
STATUS_ARRAY_BOUNDS_EXCEEDED => "STATUS_ARRAY_BOUNDS_EXCEEDED",
|
||||
STATUS_FLOAT_DENORMAL_OPERAND => "STATUS_FLOAT_DENORMAL_OPERAND",
|
||||
STATUS_FLOAT_DIVIDE_BY_ZERO => "STATUS_FLOAT_DIVIDE_BY_ZERO",
|
||||
STATUS_FLOAT_INEXACT_RESULT => "STATUS_FLOAT_INEXACT_RESULT",
|
||||
STATUS_FLOAT_INVALID_OPERATION => "STATUS_FLOAT_INVALID_OPERATION",
|
||||
STATUS_FLOAT_OVERFLOW => "STATUS_FLOAT_OVERFLOW",
|
||||
STATUS_FLOAT_STACK_CHECK => "STATUS_FLOAT_STACK_CHECK",
|
||||
STATUS_FLOAT_UNDERFLOW => "STATUS_FLOAT_UNDERFLOW",
|
||||
STATUS_INTEGER_DIVIDE_BY_ZERO => "STATUS_INTEGER_DIVIDE_BY_ZERO",
|
||||
STATUS_INTEGER_OVERFLOW => "STATUS_INTEGER_OVERFLOW",
|
||||
STATUS_PRIVILEGED_INSTRUCTION => "STATUS_PRIVILEGED_INSTRUCTION",
|
||||
STATUS_STACK_OVERFLOW => "STATUS_STACK_OVERFLOW",
|
||||
STATUS_DLL_NOT_FOUND => "STATUS_DLL_NOT_FOUND",
|
||||
STATUS_ORDINAL_NOT_FOUND => "STATUS_ORDINAL_NOT_FOUND",
|
||||
STATUS_ENTRYPOINT_NOT_FOUND => "STATUS_ENTRYPOINT_NOT_FOUND",
|
||||
STATUS_CONTROL_C_EXIT => "STATUS_CONTROL_C_EXIT",
|
||||
STATUS_DLL_INIT_FAILED => "STATUS_DLL_INIT_FAILED",
|
||||
STATUS_FLOAT_MULTIPLE_FAULTS => "STATUS_FLOAT_MULTIPLE_FAULTS",
|
||||
STATUS_FLOAT_MULTIPLE_TRAPS => "STATUS_FLOAT_MULTIPLE_TRAPS",
|
||||
STATUS_REG_NAT_CONSUMPTION => "STATUS_REG_NAT_CONSUMPTION",
|
||||
STATUS_HEAP_CORRUPTION => "STATUS_HEAP_CORRUPTION",
|
||||
STATUS_STACK_BUFFER_OVERRUN => "STATUS_STACK_BUFFER_OVERRUN",
|
||||
STATUS_ASSERTION_FAILURE => "STATUS_ASSERTION_FAILURE",
|
||||
_ => return base,
|
||||
};
|
||||
base.push_str(", ");
|
||||
base.push_str(extra);
|
||||
base
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_simple_exit_code(code: i32) -> bool {
|
||||
// Typical unix exit codes are 0 to 127.
|
||||
// Windows doesn't have anything "typical", and is a
|
||||
// 32-bit number (which appears signed here, but is really
|
||||
// unsigned). However, most of the interesting NTSTATUS
|
||||
// codes are very large. This is just a rough
|
||||
// approximation of which codes are "normal" and which
|
||||
// ones are abnormal termination.
|
||||
code >= 0 && code <= 127
|
||||
}
|
||||
|
||||
pub fn internal<S: fmt::Display>(error: S) -> anyhow::Error {
|
||||
InternalError::new(anyhow::format_err!("{}", error)).into()
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ pub use self::canonical_url::CanonicalUrl;
|
|||
pub use self::config::{homedir, Config, ConfigValue};
|
||||
pub use self::dependency_queue::DependencyQueue;
|
||||
pub use self::diagnostic_server::RustfixDiagnosticServer;
|
||||
pub use self::errors::{exit_status_to_string, internal, process_error, process_error_raw};
|
||||
pub use self::errors::{CargoResult, CargoResultExt, CliResult, Test};
|
||||
pub use self::errors::{CargoTestError, CliError, ProcessError};
|
||||
pub use self::errors::{internal, CargoResult, CargoResultExt, CliResult, Test};
|
||||
pub use self::errors::{CargoTestError, CliError};
|
||||
pub use self::flock::{FileLock, Filesystem};
|
||||
pub use self::graph::Graph;
|
||||
pub use self::hasher::StableHasher;
|
||||
|
@ -17,10 +16,8 @@ pub use self::lev_distance::{closest, closest_msg, lev_distance};
|
|||
pub use self::lockserver::{LockServer, LockServerClient, LockServerStarted};
|
||||
pub use self::paths::{bytes2path, dylib_path, join_paths, path2bytes};
|
||||
pub use self::paths::{dylib_path_envvar, normalize_path};
|
||||
pub use self::process_builder::{process, ProcessBuilder};
|
||||
pub use self::progress::{Progress, ProgressStyle};
|
||||
pub use self::queue::Queue;
|
||||
pub use self::read2::read2;
|
||||
pub use self::restricted_names::validate_package_name;
|
||||
pub use self::rustc::Rustc;
|
||||
pub use self::sha256::Sha256;
|
||||
|
@ -52,11 +49,9 @@ mod lockserver;
|
|||
pub mod machine_message;
|
||||
pub mod network;
|
||||
pub mod paths;
|
||||
pub mod process_builder;
|
||||
pub mod profile;
|
||||
mod progress;
|
||||
mod queue;
|
||||
mod read2;
|
||||
pub mod restricted_names;
|
||||
pub mod rustc;
|
||||
mod sha256;
|
||||
|
|
|
@ -4,12 +4,13 @@ use std::hash::{Hash, Hasher};
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Mutex;
|
||||
|
||||
use cargo_util::{ProcessBuilder, ProcessError};
|
||||
use log::{debug, info, warn};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::util::interning::InternedString;
|
||||
use crate::util::paths;
|
||||
use crate::util::{self, profile, CargoResult, CargoResultExt, ProcessBuilder, StableHasher};
|
||||
use crate::util::{profile, CargoResult, CargoResultExt, StableHasher};
|
||||
|
||||
/// Information on the `rustc` executable
|
||||
#[derive(Debug)]
|
||||
|
@ -47,7 +48,7 @@ impl Rustc {
|
|||
|
||||
let mut cache = Cache::load(&path, rustup_rustc, cache_location);
|
||||
|
||||
let mut cmd = util::process(&path);
|
||||
let mut cmd = ProcessBuilder::new(&path);
|
||||
cmd.arg("-vV");
|
||||
let verbose_version = cache.cached_output(&cmd, 0)?.0;
|
||||
|
||||
|
@ -86,18 +87,18 @@ impl Rustc {
|
|||
|
||||
/// Gets a process builder set up to use the found rustc version, with a wrapper if `Some`.
|
||||
pub fn process(&self) -> ProcessBuilder {
|
||||
util::process(self.path.as_path()).wrapped(self.wrapper.as_ref())
|
||||
ProcessBuilder::new(self.path.as_path()).wrapped(self.wrapper.as_ref())
|
||||
}
|
||||
|
||||
/// Gets a process builder set up to use the found rustc version, with a wrapper if `Some`.
|
||||
pub fn workspace_process(&self) -> ProcessBuilder {
|
||||
util::process(self.path.as_path())
|
||||
ProcessBuilder::new(self.path.as_path())
|
||||
.wrapped(self.workspace_wrapper.as_ref())
|
||||
.wrapped(self.wrapper.as_ref())
|
||||
}
|
||||
|
||||
pub fn process_no_wrapper(&self) -> ProcessBuilder {
|
||||
util::process(&self.path)
|
||||
ProcessBuilder::new(&self.path)
|
||||
}
|
||||
|
||||
/// Gets the output for the given command.
|
||||
|
@ -232,7 +233,7 @@ impl Cache {
|
|||
status: if output.status.success() {
|
||||
String::new()
|
||||
} else {
|
||||
util::exit_status_to_string(output.status)
|
||||
cargo_util::exit_status_to_string(output.status)
|
||||
},
|
||||
code: output.status.code(),
|
||||
stdout,
|
||||
|
@ -245,7 +246,7 @@ impl Cache {
|
|||
if output.success {
|
||||
Ok((output.stdout.clone(), output.stderr.clone()))
|
||||
} else {
|
||||
Err(util::process_error_raw(
|
||||
Err(ProcessError::new_raw(
|
||||
&format!("process didn't exit successfully: {}", cmd),
|
||||
output.code,
|
||||
&output.status,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::util::paths;
|
||||
use crate::util::{process, CargoResult};
|
||||
use crate::util::CargoResult;
|
||||
use cargo_util::ProcessBuilder;
|
||||
use std::path::Path;
|
||||
|
||||
// Check if we are in an existing repo. We define that to be true if either:
|
||||
|
@ -41,11 +42,15 @@ impl GitRepo {
|
|||
|
||||
impl HgRepo {
|
||||
pub fn init(path: &Path, cwd: &Path) -> CargoResult<HgRepo> {
|
||||
process("hg").cwd(cwd).arg("init").arg(path).exec()?;
|
||||
ProcessBuilder::new("hg")
|
||||
.cwd(cwd)
|
||||
.arg("init")
|
||||
.arg(path)
|
||||
.exec()?;
|
||||
Ok(HgRepo)
|
||||
}
|
||||
pub fn discover(path: &Path, cwd: &Path) -> CargoResult<HgRepo> {
|
||||
process("hg")
|
||||
ProcessBuilder::new("hg")
|
||||
.cwd(cwd)
|
||||
.arg("--cwd")
|
||||
.arg(path)
|
||||
|
@ -57,7 +62,11 @@ impl HgRepo {
|
|||
|
||||
impl PijulRepo {
|
||||
pub fn init(path: &Path, cwd: &Path) -> CargoResult<PijulRepo> {
|
||||
process("pijul").cwd(cwd).arg("init").arg(path).exec()?;
|
||||
ProcessBuilder::new("pijul")
|
||||
.cwd(cwd)
|
||||
.arg("init")
|
||||
.arg(path)
|
||||
.exec()?;
|
||||
Ok(PijulRepo)
|
||||
}
|
||||
}
|
||||
|
@ -73,28 +82,28 @@ impl FossilRepo {
|
|||
db_path.push(db_fname);
|
||||
|
||||
// then create the fossil DB in that location
|
||||
process("fossil")
|
||||
ProcessBuilder::new("fossil")
|
||||
.cwd(cwd)
|
||||
.arg("init")
|
||||
.arg(&db_path)
|
||||
.exec()?;
|
||||
|
||||
// open it in that new directory
|
||||
process("fossil")
|
||||
ProcessBuilder::new("fossil")
|
||||
.cwd(&path)
|
||||
.arg("open")
|
||||
.arg(db_fname)
|
||||
.exec()?;
|
||||
|
||||
// set `target` as ignoreable and cleanable
|
||||
process("fossil")
|
||||
ProcessBuilder::new("fossil")
|
||||
.cwd(cwd)
|
||||
.arg("settings")
|
||||
.arg("ignore-glob")
|
||||
.arg("target")
|
||||
.exec()?;
|
||||
|
||||
process("fossil")
|
||||
ProcessBuilder::new("fossil")
|
||||
.cwd(cwd)
|
||||
.arg("settings")
|
||||
.arg("clean-glob")
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use super::ProcessBuilder;
|
||||
use crate::core::compiler::Unit;
|
||||
use crate::core::manifest::TargetSourcePath;
|
||||
use crate::core::{Target, Workspace};
|
||||
use crate::ops::CompileOptions;
|
||||
use crate::util::CargoResult;
|
||||
use anyhow::bail;
|
||||
use cargo_util::ProcessBuilder;
|
||||
use std::fmt::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
//! cargo test --test testsuite -- old_cargos --nocapture --ignored
|
||||
//! ```
|
||||
|
||||
use cargo::util::{ProcessBuilder, ProcessError};
|
||||
use cargo::CargoResult;
|
||||
use cargo_test_support::paths::CargoPathExt;
|
||||
use cargo_test_support::registry::{self, Dependency, Package};
|
||||
use cargo_test_support::{cargo_exe, execs, paths, process, project, rustc_host};
|
||||
use cargo_util::{ProcessBuilder, ProcessError};
|
||||
use semver::Version;
|
||||
use std::fs;
|
||||
|
||||
|
@ -68,7 +68,7 @@ fn collect_all_toolchains() -> Vec<(Version, String)> {
|
|||
format!("nightly-{}", host),
|
||||
];
|
||||
|
||||
let output = cargo::util::process("rustup")
|
||||
let output = ProcessBuilder::new("rustup")
|
||||
.args(&["toolchain", "list"])
|
||||
.exec_with_output()
|
||||
.expect("rustup should be installed");
|
||||
|
|
Loading…
Reference in New Issue
Block a user