mirror of https://github.com/rust-lang/cargo
Move ProcessBuilder to cargo-util.
This commit is contained in:
parent
669340333a
commit
888100352a
|
@ -66,6 +66,7 @@ jobs:
|
||||||
- run: cargo test --features 'deny-warnings'
|
- run: cargo test --features 'deny-warnings'
|
||||||
- run: cargo test --features 'deny-warnings' -p cargo-test-support
|
- run: cargo test --features 'deny-warnings' -p cargo-test-support
|
||||||
- run: cargo test -p cargo-platform
|
- run: cargo test -p cargo-platform
|
||||||
|
- run: cargo test -p cargo-util
|
||||||
- run: cargo test --manifest-path crates/mdman/Cargo.toml
|
- 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-1password/Cargo.toml
|
||||||
- run: cargo build --manifest-path crates/credential/cargo-credential-gnome-secret/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 = { version = "1.0.123", features = ["derive"] }
|
||||||
serde_ignored = "0.1.0"
|
serde_ignored = "0.1.0"
|
||||||
serde_json = { version = "1.0.30", features = ["raw_value"] }
|
serde_json = { version = "1.0.30", features = ["raw_value"] }
|
||||||
shell-escape = "0.1.4"
|
|
||||||
strip-ansi-escapes = "0.1.0"
|
strip-ansi-escapes = "0.1.0"
|
||||||
tar = { version = "0.4.26", default-features = false }
|
tar = { version = "0.4.26", default-features = false }
|
||||||
tempfile = "3.0"
|
tempfile = "3.0"
|
||||||
|
@ -80,7 +79,6 @@ rand = "0.8.3"
|
||||||
core-foundation = { version = "0.9.0", features = ["mac_os_10_7_support"] }
|
core-foundation = { version = "0.9.0", features = ["mac_os_10_7_support"] }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
miow = "0.3.6"
|
|
||||||
fwdansi = "1.1.0"
|
fwdansi = "1.1.0"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies.winapi]
|
[target.'cfg(windows)'.dependencies.winapi]
|
||||||
|
|
|
@ -11,6 +11,7 @@ doctest = false
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cargo = { path = "../.." }
|
cargo = { path = "../.." }
|
||||||
cargo-test-macro = { path = "../cargo-test-macro" }
|
cargo-test-macro = { path = "../cargo-test-macro" }
|
||||||
|
cargo-util = { path = "../cargo-util" }
|
||||||
filetime = "0.2"
|
filetime = "0.2"
|
||||||
flate2 = { version = "1.0", default-features = false, features = ["zlib"] }
|
flate2 = { version = "1.0", default-features = false, features = ["zlib"] }
|
||||||
git2 = "0.13.16"
|
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.
|
//! 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 crate::{basic_manifest, main_file, project};
|
||||||
use cargo::util::ProcessError;
|
|
||||||
use cargo::CargoResult;
|
use cargo::CargoResult;
|
||||||
|
use cargo_util::ProcessError;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::process::{Command, Output};
|
use std::process::{Command, Output};
|
||||||
|
|
|
@ -15,7 +15,8 @@ use std::process::{Command, Output};
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::time::{self, Duration};
|
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 serde_json::{self, Value};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -1569,12 +1570,12 @@ pub fn is_nightly() -> bool {
|
||||||
.with(|r| r.verbose_version.contains("-nightly") || r.verbose_version.contains("-dev"))
|
.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())
|
_process(t.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
|
fn _process(t: &OsStr) -> ProcessBuilder {
|
||||||
let mut p = cargo::util::process(t);
|
let mut p = ProcessBuilder::new(t);
|
||||||
|
|
||||||
// In general just clear out all cargo-specific configuration already in the
|
// In general just clear out all cargo-specific configuration already in the
|
||||||
// environment. Our tests all assume a "default configuration" unless
|
// 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;
|
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 {
|
fn masquerade_as_nightly_cargo(&mut self) -> &mut Self {
|
||||||
self.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly")
|
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."
|
description = "Miscellaneous support code used by Cargo."
|
||||||
|
|
||||||
[dependencies]
|
[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"] }
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
../../LICENSE-APACHE
|
|
@ -0,0 +1 @@
|
||||||
|
../../LICENSE-MIT
|
|
@ -1 +1,9 @@
|
||||||
//! Miscellaneous support code used by Cargo.
|
//! 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 crate::process_error::ProcessError;
|
||||||
use anyhow::bail;
|
use crate::read2;
|
||||||
|
use anyhow::{bail, Context, Result};
|
||||||
use jobserver::Client;
|
use jobserver::Client;
|
||||||
use shell_escape::escape;
|
use shell_escape::escape;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
@ -10,7 +11,7 @@ use std::iter::once;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::{Command, Output, Stdio};
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ProcessBuilder {
|
pub struct ProcessBuilder {
|
||||||
/// The program to execute.
|
/// The program to execute.
|
||||||
|
@ -21,10 +22,10 @@ pub struct ProcessBuilder {
|
||||||
env: BTreeMap<String, Option<OsString>>,
|
env: BTreeMap<String, Option<OsString>>,
|
||||||
/// The directory to run the program from.
|
/// The directory to run the program from.
|
||||||
cwd: Option<OsString>,
|
cwd: Option<OsString>,
|
||||||
/// The `make` jobserver. See the [jobserver crate][jobserver_docs] for
|
/// The `make` jobserver. See the [jobserver crate] for
|
||||||
/// more information.
|
/// more information.
|
||||||
///
|
///
|
||||||
/// [jobserver_docs]: https://docs.rs/jobserver/0.1.6/jobserver/
|
/// [jobserver crate]: https://docs.rs/jobserver/
|
||||||
jobserver: Option<Client>,
|
jobserver: Option<Client>,
|
||||||
/// `true` to include environment variable in display.
|
/// `true` to include environment variable in display.
|
||||||
display_env_vars: bool,
|
display_env_vars: bool,
|
||||||
|
@ -58,6 +59,18 @@ impl fmt::Display for ProcessBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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.
|
/// (chainable) Sets the executable for the process.
|
||||||
pub fn program<T: AsRef<OsStr>>(&mut self, program: T) -> &mut ProcessBuilder {
|
pub fn program<T: AsRef<OsStr>>(&mut self, program: T) -> &mut ProcessBuilder {
|
||||||
self.program = program.as_ref().to_os_string();
|
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.
|
/// 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 mut command = self.build_command();
|
||||||
let exit = command.status().chain_err(|| {
|
let exit = command.status().with_context(|| {
|
||||||
process_error(&format!("could not execute process {}", self), None, None)
|
ProcessError::new(&format!("could not execute process {}", self), None, None)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if exit.success() {
|
if exit.success() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(process_error(
|
Err(ProcessError::new(
|
||||||
&format!("process didn't exit successfully: {}", self),
|
&format!("process didn't exit successfully: {}", self),
|
||||||
Some(exit),
|
Some(exit),
|
||||||
None,
|
None,
|
||||||
|
@ -182,22 +195,22 @@ impl ProcessBuilder {
|
||||||
/// include our child process. If the child terminates then we'll reap them in Cargo
|
/// 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
|
/// pretty quickly, and if the child handles the signal then we won't terminate
|
||||||
/// (and we shouldn't!) until the process itself later exits.
|
/// (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)
|
imp::exec_replace(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes the process, returning the stdio output, or an error if non-zero exit status.
|
/// 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 mut command = self.build_command();
|
||||||
|
|
||||||
let output = command.output().chain_err(|| {
|
let output = command.output().with_context(|| {
|
||||||
process_error(&format!("could not execute process {}", self), None, None)
|
ProcessError::new(&format!("could not execute process {}", self), None, None)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
Ok(output)
|
Ok(output)
|
||||||
} else {
|
} else {
|
||||||
Err(process_error(
|
Err(ProcessError::new(
|
||||||
&format!("process didn't exit successfully: {}", self),
|
&format!("process didn't exit successfully: {}", self),
|
||||||
Some(output.status),
|
Some(output.status),
|
||||||
Some(&output),
|
Some(&output),
|
||||||
|
@ -217,10 +230,10 @@ impl ProcessBuilder {
|
||||||
/// output.
|
/// output.
|
||||||
pub fn exec_with_streaming(
|
pub fn exec_with_streaming(
|
||||||
&self,
|
&self,
|
||||||
on_stdout_line: &mut dyn FnMut(&str) -> CargoResult<()>,
|
on_stdout_line: &mut dyn FnMut(&str) -> Result<()>,
|
||||||
on_stderr_line: &mut dyn FnMut(&str) -> CargoResult<()>,
|
on_stderr_line: &mut dyn FnMut(&str) -> Result<()>,
|
||||||
capture_output: bool,
|
capture_output: bool,
|
||||||
) -> CargoResult<Output> {
|
) -> Result<Output> {
|
||||||
let mut stdout = Vec::new();
|
let mut stdout = Vec::new();
|
||||||
let mut stderr = Vec::new();
|
let mut stderr = Vec::new();
|
||||||
|
|
||||||
|
@ -274,7 +287,9 @@ impl ProcessBuilder {
|
||||||
})?;
|
})?;
|
||||||
child.wait()
|
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 {
|
let output = Output {
|
||||||
status,
|
status,
|
||||||
stdout,
|
stdout,
|
||||||
|
@ -284,14 +299,14 @@ impl ProcessBuilder {
|
||||||
{
|
{
|
||||||
let to_print = if capture_output { Some(&output) } else { None };
|
let to_print = if capture_output { Some(&output) } else { None };
|
||||||
if let Some(e) = callback_error {
|
if let Some(e) = callback_error {
|
||||||
let cx = process_error(
|
let cx = ProcessError::new(
|
||||||
&format!("failed to parse process output: {}", self),
|
&format!("failed to parse process output: {}", self),
|
||||||
Some(output.status),
|
Some(output.status),
|
||||||
to_print,
|
to_print,
|
||||||
);
|
);
|
||||||
bail!(anyhow::Error::new(cx).context(e));
|
bail!(anyhow::Error::new(cx).context(e));
|
||||||
} else if !output.status.success() {
|
} else if !output.status.success() {
|
||||||
bail!(process_error(
|
bail!(ProcessError::new(
|
||||||
&format!("process didn't exit successfully: {}", self),
|
&format!("process didn't exit successfully: {}", self),
|
||||||
Some(output.status),
|
Some(output.status),
|
||||||
to_print,
|
to_print,
|
||||||
|
@ -333,9 +348,9 @@ impl ProcessBuilder {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use cargo::util::{ProcessBuilder, process};
|
/// use cargo_util::ProcessBuilder;
|
||||||
/// // Running this would execute `rustc`
|
/// // Running this would execute `rustc`
|
||||||
/// let cmd: ProcessBuilder = process("rustc");
|
/// let cmd = ProcessBuilder::new("rustc");
|
||||||
///
|
///
|
||||||
/// // Running this will execute `sccache rustc`
|
/// // Running this will execute `sccache rustc`
|
||||||
/// let cmd = cmd.wrapped(Some("sccache"));
|
/// 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)]
|
#[cfg(unix)]
|
||||||
mod imp {
|
mod imp {
|
||||||
use crate::util::{process_error, ProcessBuilder};
|
use super::{ProcessBuilder, ProcessError};
|
||||||
use crate::CargoResult;
|
use anyhow::Result;
|
||||||
use std::os::unix::process::CommandExt;
|
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 mut command = process_builder.build_command();
|
||||||
let error = command.exec();
|
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),
|
&format!("could not execute process {}", process_builder),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
@ -391,8 +394,8 @@ mod imp {
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
mod imp {
|
mod imp {
|
||||||
use crate::util::{process_error, ProcessBuilder};
|
use super::{ProcessBuilder, ProcessError};
|
||||||
use crate::CargoResult;
|
use anyhow::Result;
|
||||||
use winapi::shared::minwindef::{BOOL, DWORD, FALSE, TRUE};
|
use winapi::shared::minwindef::{BOOL, DWORD, FALSE, TRUE};
|
||||||
use winapi::um::consoleapi::SetConsoleCtrlHandler;
|
use winapi::um::consoleapi::SetConsoleCtrlHandler;
|
||||||
|
|
||||||
|
@ -401,10 +404,10 @@ mod imp {
|
||||||
TRUE
|
TRUE
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exec_replace(process_builder: &ProcessBuilder) -> CargoResult<()> {
|
pub fn exec_replace(process_builder: &ProcessBuilder) -> Result<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if SetConsoleCtrlHandler(Some(ctrlc_handler), TRUE) == FALSE {
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = [
|
TO_PUBLISH = [
|
||||||
'crates/cargo-platform',
|
'crates/cargo-platform',
|
||||||
|
'crates/cargo-util',
|
||||||
'crates/crates-io',
|
'crates/crates-io',
|
||||||
'.',
|
'.',
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::command_prelude::*;
|
use crate::command_prelude::*;
|
||||||
use crate::util::restricted_names::is_glob_pattern;
|
use crate::util::restricted_names::is_glob_pattern;
|
||||||
use crate::util::ProcessError;
|
|
||||||
use cargo::core::Verbosity;
|
use cargo::core::Verbosity;
|
||||||
use cargo::ops::{self, CompileFilter, Packages};
|
use cargo::ops::{self, CompileFilter, Packages};
|
||||||
|
use cargo_util::ProcessError;
|
||||||
|
|
||||||
pub fn cli() -> App {
|
pub fn cli() -> App {
|
||||||
subcommand("run")
|
subcommand("run")
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::command_prelude::*;
|
use crate::command_prelude::*;
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use cargo::ops::{self, CompileFilter, FilterRule, LibRule};
|
use cargo::ops::{self, CompileFilter, FilterRule, LibRule};
|
||||||
use cargo::util::errors;
|
|
||||||
|
|
||||||
pub fn cli() -> App {
|
pub fn cli() -> App {
|
||||||
subcommand("test")
|
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 context = anyhow::format_err!("{}", err.hint(&ws, &ops.compile_opts));
|
||||||
let e = match err.code {
|
let e = match err.code {
|
||||||
// Don't show "process didn't exit successfully" for simple errors.
|
// 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),
|
Some(i) => CliError::new(Error::from(err).context(context), i),
|
||||||
None => CliError::new(Error::from(err).context(context), 101),
|
None => CliError::new(Error::from(err).context(context), 101),
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,15 +3,15 @@
|
||||||
#![warn(clippy::needless_borrow)]
|
#![warn(clippy::needless_borrow)]
|
||||||
#![warn(clippy::redundant_clone)]
|
#![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::collections::{BTreeMap, BTreeSet};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
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 cli;
|
||||||
mod commands;
|
mod commands;
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> Cli
|
||||||
};
|
};
|
||||||
|
|
||||||
let cargo_exe = config.cargo_exe()?;
|
let cargo_exe = config.cargo_exe()?;
|
||||||
let err = match util::process(&command)
|
let err = match ProcessBuilder::new(&command)
|
||||||
.env(cargo::CARGO_ENV, cargo_exe)
|
.env(cargo::CARGO_ENV, cargo_exe)
|
||||||
.args(args)
|
.args(args)
|
||||||
.exec_replace()
|
.exec_replace()
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::core::compiler::CompileKind;
|
use crate::core::compiler::CompileKind;
|
||||||
use crate::util::interning::InternedString;
|
use crate::util::interning::InternedString;
|
||||||
use crate::util::ProcessBuilder;
|
|
||||||
use crate::util::{CargoResult, Config, RustfixDiagnosticServer};
|
use crate::util::{CargoResult, Config, RustfixDiagnosticServer};
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
use serde::ser;
|
use serde::ser;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
|
@ -3,8 +3,9 @@ use crate::core::compiler::{
|
||||||
};
|
};
|
||||||
use crate::core::{Dependency, Target, TargetKind, Workspace};
|
use crate::core::{Dependency, Target, TargetKind, Workspace};
|
||||||
use crate::util::config::{Config, StringList, TargetConfig};
|
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_platform::{Cfg, CfgExpr};
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::hash_map::{Entry, HashMap};
|
use std::collections::hash_map::{Entry, HashMap};
|
||||||
|
|
|
@ -14,7 +14,8 @@ use serde::Serialize;
|
||||||
use super::context::OutputFile;
|
use super::context::OutputFile;
|
||||||
use super::{CompileKind, CompileMode, Context, Unit};
|
use super::{CompileKind, CompileMode, Context, Unit};
|
||||||
use crate::core::TargetKind;
|
use crate::core::TargetKind;
|
||||||
use crate::util::{internal, CargoResult, Config, ProcessBuilder};
|
use crate::util::{internal, CargoResult, Config};
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
struct Invocation {
|
struct Invocation {
|
||||||
|
|
|
@ -4,12 +4,13 @@ use std::ffi::{OsStr, OsString};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use cargo_platform::CfgExpr;
|
use cargo_platform::CfgExpr;
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
|
|
||||||
use super::BuildContext;
|
use super::BuildContext;
|
||||||
use crate::core::compiler::{CompileKind, Metadata, Unit};
|
use crate::core::compiler::{CompileKind, Metadata, Unit};
|
||||||
use crate::core::Package;
|
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`.
|
/// Structure with enough information to run `rustdoc --test`.
|
||||||
pub struct Doctest {
|
pub struct Doctest {
|
||||||
|
@ -184,7 +185,7 @@ impl<'cfg> Compilation<'cfg> {
|
||||||
unit: &Unit,
|
unit: &Unit,
|
||||||
script_meta: Option<Metadata>,
|
script_meta: Option<Metadata>,
|
||||||
) -> CargoResult<ProcessBuilder> {
|
) -> CargoResult<ProcessBuilder> {
|
||||||
let rustdoc = process(&*self.config.rustdoc()?);
|
let rustdoc = ProcessBuilder::new(&*self.config.rustdoc()?);
|
||||||
let cmd = fill_rustc_tool_env(rustdoc, unit);
|
let cmd = fill_rustc_tool_env(rustdoc, unit);
|
||||||
let mut p = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, true)?;
|
let mut p = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, true)?;
|
||||||
unit.target.edition().cmd_edition_arg(&mut p);
|
unit.target.edition().cmd_edition_arg(&mut p);
|
||||||
|
@ -207,7 +208,13 @@ impl<'cfg> Compilation<'cfg> {
|
||||||
cmd: T,
|
cmd: T,
|
||||||
pkg: &Package,
|
pkg: &Package,
|
||||||
) -> CargoResult<ProcessBuilder> {
|
) -> 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>)> {
|
pub fn target_runner(&self, kind: CompileKind) -> Option<&(PathBuf, Vec<String>)> {
|
||||||
|
@ -229,12 +236,12 @@ impl<'cfg> Compilation<'cfg> {
|
||||||
script_meta: Option<Metadata>,
|
script_meta: Option<Metadata>,
|
||||||
) -> CargoResult<ProcessBuilder> {
|
) -> CargoResult<ProcessBuilder> {
|
||||||
let builder = if let Some((runner, args)) = self.target_runner(kind) {
|
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.args(args);
|
||||||
builder.arg(cmd);
|
builder.arg(cmd);
|
||||||
builder
|
builder
|
||||||
} else {
|
} else {
|
||||||
process(cmd)
|
ProcessBuilder::new(cmd)
|
||||||
};
|
};
|
||||||
self.fill_env(builder, pkg, script_meta, kind, false)
|
self.fill_env(builder, pkg, script_meta, kind, false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,6 +322,7 @@ use std::sync::{Arc, Mutex};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use anyhow::{bail, format_err};
|
use anyhow::{bail, format_err};
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
use filetime::FileTime;
|
use filetime::FileTime;
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use serde::de;
|
use serde::de;
|
||||||
|
@ -334,7 +335,7 @@ use crate::util;
|
||||||
use crate::util::errors::{CargoResult, CargoResultExt};
|
use crate::util::errors::{CargoResult, CargoResultExt};
|
||||||
use crate::util::interning::InternedString;
|
use crate::util::interning::InternedString;
|
||||||
use crate::util::paths;
|
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::custom_build::BuildDeps;
|
||||||
use super::job::{Job, Work};
|
use super::job::{Job, Work};
|
||||||
|
|
|
@ -57,6 +57,7 @@ use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::format_err;
|
use anyhow::format_err;
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
use crossbeam_utils::thread::Scope;
|
use crossbeam_utils::thread::Scope;
|
||||||
use jobserver::{Acquired, Client, HelperThread};
|
use jobserver::{Acquired, Client, HelperThread};
|
||||||
use log::{debug, info, trace};
|
use log::{debug, info, trace};
|
||||||
|
@ -78,7 +79,7 @@ use crate::drop_eprint;
|
||||||
use crate::util::diagnostic_server::{self, DiagnosticPrinter};
|
use crate::util::diagnostic_server::{self, DiagnosticPrinter};
|
||||||
use crate::util::machine_message::{self, Message as _};
|
use crate::util::machine_message::{self, Message as _};
|
||||||
use crate::util::{self, internal, profile};
|
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};
|
use crate::util::{Config, DependencyQueue, Progress, ProgressStyle, Queue};
|
||||||
|
|
||||||
/// This structure is backed by the `DependencyQueue` type and manages the
|
/// 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::manifest::TargetSourcePath;
|
||||||
use crate::core::profiles::{PanicStrategy, Profile, Strip};
|
use crate::core::profiles::{PanicStrategy, Profile, Strip};
|
||||||
use crate::core::{Feature, PackageId, Target};
|
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::interning::InternedString;
|
||||||
use crate::util::machine_message::Message;
|
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 crate::util::{add_path_args, internal, join_paths, paths, profile};
|
||||||
|
use cargo_util::{ProcessBuilder, ProcessError};
|
||||||
|
|
||||||
const RUSTDOC_CRATE_VERSION_FLAG: &str = "--crate-version";
|
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()
|
.as_ref()
|
||||||
.and_then(|perr| perr.code)
|
.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,
|
_ => err,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::core::compiler::unit::Unit;
|
||||||
use crate::core::compiler::CompileKind;
|
use crate::core::compiler::CompileKind;
|
||||||
use crate::sources::CRATES_IO_REGISTRY;
|
use crate::sources::CRATES_IO_REGISTRY;
|
||||||
use crate::util::errors::{internal, CargoResult};
|
use crate::util::errors::{internal, CargoResult};
|
||||||
use crate::util::ProcessBuilder;
|
use cargo_util::ProcessBuilder;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash;
|
use std::hash;
|
||||||
|
|
|
@ -97,10 +97,11 @@ use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use anyhow::{bail, Error};
|
use anyhow::{bail, Error};
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::util::errors::CargoResult;
|
use crate::util::errors::CargoResult;
|
||||||
use crate::util::{indented_lines, ProcessBuilder};
|
use crate::util::indented_lines;
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
|
|
||||||
pub const SEE_CHANNELS: &str =
|
pub const SEE_CHANNELS: &str =
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use std::ffi::OsString;
|
|
||||||
|
|
||||||
use crate::core::compiler::{Compilation, CompileKind, Doctest, UnitOutput};
|
use crate::core::compiler::{Compilation, CompileKind, Doctest, UnitOutput};
|
||||||
use crate::core::shell::Verbosity;
|
use crate::core::shell::Verbosity;
|
||||||
use crate::core::{TargetKind, Workspace};
|
use crate::core::{TargetKind, Workspace};
|
||||||
use crate::ops;
|
use crate::ops;
|
||||||
use crate::util::errors::CargoResult;
|
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 struct TestOptions {
|
||||||
pub compile_opts: ops::CompileOptions,
|
pub compile_opts: ops::CompileOptions,
|
||||||
|
|
|
@ -46,6 +46,7 @@ use std::process::{self, Command, ExitStatus};
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use anyhow::{bail, Context, Error};
|
use anyhow::{bail, Context, Error};
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
use log::{debug, trace, warn};
|
use log::{debug, trace, warn};
|
||||||
use rustfix::diagnostics::Diagnostic;
|
use rustfix::diagnostics::Diagnostic;
|
||||||
use rustfix::{self, CodeFix};
|
use rustfix::{self, CodeFix};
|
||||||
|
@ -57,7 +58,7 @@ use crate::core::{Edition, MaybePackage, Workspace};
|
||||||
use crate::ops::{self, CompileOptions};
|
use crate::ops::{self, CompileOptions};
|
||||||
use crate::util::diagnostic_server::{Message, RustfixDiagnosticServer};
|
use crate::util::diagnostic_server::{Message, RustfixDiagnosticServer};
|
||||||
use crate::util::errors::CargoResult;
|
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::util::{existing_vcs_repo, LockServer, LockServerClient};
|
||||||
use crate::{drop_eprint, drop_eprintln};
|
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.
|
// Spin up our lock server, which our subprocesses will use to synchronize fixes.
|
||||||
let lock_server = LockServer::new()?;
|
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());
|
wrapper.env(FIX_ENV, lock_server.addr().to_string());
|
||||||
let _started = lock_server.start()?;
|
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")
|
let workspace_rustc = std::env::var("RUSTC_WORKSPACE_WRAPPER")
|
||||||
.map(PathBuf::from)
|
.map(PathBuf::from)
|
||||||
.ok();
|
.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);
|
trace!("start rustfixing {:?}", args.file);
|
||||||
let fixes = rustfix_crate(&lock_addr, &rustc, &args.file, &args, config)?;
|
let fixes = rustfix_crate(&lock_addr, &rustc, &args.file, &args, config)?;
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
//! Registry authentication support.
|
//! Registry authentication support.
|
||||||
|
|
||||||
use crate::sources::CRATES_IO_REGISTRY;
|
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::bail;
|
||||||
use anyhow::format_err;
|
use anyhow::format_err;
|
||||||
|
use cargo_util::ProcessError;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
@ -197,7 +198,7 @@ fn run_command(
|
||||||
Action::Store(_) => "failed to store token to registry",
|
Action::Store(_) => "failed to store token to registry",
|
||||||
Action::Erase => "failed to erase token from registry",
|
Action::Erase => "failed to erase token from registry",
|
||||||
};
|
};
|
||||||
return Err(process_error(
|
return Err(ProcessError::new(
|
||||||
&format!(
|
&format!(
|
||||||
"registry credential process `{}` {} `{}`",
|
"registry credential process `{}` {} `{}`",
|
||||||
exe.display(),
|
exe.display(),
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
use crate::core::GitReference;
|
use crate::core::GitReference;
|
||||||
use crate::util::errors::{CargoResult, CargoResultExt};
|
use crate::util::errors::{CargoResult, CargoResultExt};
|
||||||
use crate::util::paths;
|
use crate::util::paths;
|
||||||
use crate::util::process_builder::process;
|
|
||||||
use crate::util::{network, Config, IntoUrl, Progress};
|
use crate::util::{network, Config, IntoUrl, Progress};
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
use curl::easy::List;
|
use curl::easy::List;
|
||||||
use git2::{self, ErrorClass, ObjectType};
|
use git2::{self, ErrorClass, ObjectType};
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
|
@ -835,7 +835,7 @@ fn fetch_with_cli(
|
||||||
tags: bool,
|
tags: bool,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
) -> CargoResult<()> {
|
) -> CargoResult<()> {
|
||||||
let mut cmd = process("git");
|
let mut cmd = ProcessBuilder::new("git");
|
||||||
cmd.arg("fetch");
|
cmd.arg("fetch");
|
||||||
if tags {
|
if tags {
|
||||||
cmd.arg("--tags");
|
cmd.arg("--tags");
|
||||||
|
|
|
@ -10,12 +10,13 @@ use std::sync::Arc;
|
||||||
use std::thread::{self, JoinHandle};
|
use std::thread::{self, JoinHandle};
|
||||||
|
|
||||||
use anyhow::{Context, Error};
|
use anyhow::{Context, Error};
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::core::Edition;
|
use crate::core::Edition;
|
||||||
use crate::util::errors::CargoResult;
|
use crate::util::errors::CargoResult;
|
||||||
use crate::util::{Config, ProcessBuilder};
|
use crate::util::Config;
|
||||||
|
|
||||||
const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
|
const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
|
||||||
const PLEASE_REPORT_THIS_BUG: &str =
|
const PLEASE_REPORT_THIS_BUG: &str =
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
use crate::core::{TargetKind, Workspace};
|
use crate::core::{TargetKind, Workspace};
|
||||||
use crate::ops::CompileOptions;
|
use crate::ops::CompileOptions;
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
|
use cargo_util::ProcessError;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::{ExitStatus, Output};
|
|
||||||
use std::str;
|
|
||||||
|
|
||||||
pub type CargoResult<T> = anyhow::Result<T>;
|
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> {}
|
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.
|
// Cargo test errors.
|
||||||
|
|
||||||
|
@ -360,154 +324,6 @@ impl From<clap::Error> for CliError {
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Construction helpers
|
// 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 {
|
pub fn internal<S: fmt::Display>(error: S) -> anyhow::Error {
|
||||||
InternalError::new(anyhow::format_err!("{}", error)).into()
|
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::config::{homedir, Config, ConfigValue};
|
||||||
pub use self::dependency_queue::DependencyQueue;
|
pub use self::dependency_queue::DependencyQueue;
|
||||||
pub use self::diagnostic_server::RustfixDiagnosticServer;
|
pub use self::diagnostic_server::RustfixDiagnosticServer;
|
||||||
pub use self::errors::{exit_status_to_string, internal, process_error, process_error_raw};
|
pub use self::errors::{internal, CargoResult, CargoResultExt, CliResult, Test};
|
||||||
pub use self::errors::{CargoResult, CargoResultExt, CliResult, Test};
|
pub use self::errors::{CargoTestError, CliError};
|
||||||
pub use self::errors::{CargoTestError, CliError, ProcessError};
|
|
||||||
pub use self::flock::{FileLock, Filesystem};
|
pub use self::flock::{FileLock, Filesystem};
|
||||||
pub use self::graph::Graph;
|
pub use self::graph::Graph;
|
||||||
pub use self::hasher::StableHasher;
|
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::lockserver::{LockServer, LockServerClient, LockServerStarted};
|
||||||
pub use self::paths::{bytes2path, dylib_path, join_paths, path2bytes};
|
pub use self::paths::{bytes2path, dylib_path, join_paths, path2bytes};
|
||||||
pub use self::paths::{dylib_path_envvar, normalize_path};
|
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::progress::{Progress, ProgressStyle};
|
||||||
pub use self::queue::Queue;
|
pub use self::queue::Queue;
|
||||||
pub use self::read2::read2;
|
|
||||||
pub use self::restricted_names::validate_package_name;
|
pub use self::restricted_names::validate_package_name;
|
||||||
pub use self::rustc::Rustc;
|
pub use self::rustc::Rustc;
|
||||||
pub use self::sha256::Sha256;
|
pub use self::sha256::Sha256;
|
||||||
|
@ -52,11 +49,9 @@ mod lockserver;
|
||||||
pub mod machine_message;
|
pub mod machine_message;
|
||||||
pub mod network;
|
pub mod network;
|
||||||
pub mod paths;
|
pub mod paths;
|
||||||
pub mod process_builder;
|
|
||||||
pub mod profile;
|
pub mod profile;
|
||||||
mod progress;
|
mod progress;
|
||||||
mod queue;
|
mod queue;
|
||||||
mod read2;
|
|
||||||
pub mod restricted_names;
|
pub mod restricted_names;
|
||||||
pub mod rustc;
|
pub mod rustc;
|
||||||
mod sha256;
|
mod sha256;
|
||||||
|
|
|
@ -4,12 +4,13 @@ use std::hash::{Hash, Hasher};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use cargo_util::{ProcessBuilder, ProcessError};
|
||||||
use log::{debug, info, warn};
|
use log::{debug, info, warn};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::util::interning::InternedString;
|
use crate::util::interning::InternedString;
|
||||||
use crate::util::paths;
|
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
|
/// Information on the `rustc` executable
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -47,7 +48,7 @@ impl Rustc {
|
||||||
|
|
||||||
let mut cache = Cache::load(&path, rustup_rustc, cache_location);
|
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");
|
cmd.arg("-vV");
|
||||||
let verbose_version = cache.cached_output(&cmd, 0)?.0;
|
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`.
|
/// Gets a process builder set up to use the found rustc version, with a wrapper if `Some`.
|
||||||
pub fn process(&self) -> ProcessBuilder {
|
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`.
|
/// Gets a process builder set up to use the found rustc version, with a wrapper if `Some`.
|
||||||
pub fn workspace_process(&self) -> ProcessBuilder {
|
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.workspace_wrapper.as_ref())
|
||||||
.wrapped(self.wrapper.as_ref())
|
.wrapped(self.wrapper.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_no_wrapper(&self) -> ProcessBuilder {
|
pub fn process_no_wrapper(&self) -> ProcessBuilder {
|
||||||
util::process(&self.path)
|
ProcessBuilder::new(&self.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the output for the given command.
|
/// Gets the output for the given command.
|
||||||
|
@ -232,7 +233,7 @@ impl Cache {
|
||||||
status: if output.status.success() {
|
status: if output.status.success() {
|
||||||
String::new()
|
String::new()
|
||||||
} else {
|
} else {
|
||||||
util::exit_status_to_string(output.status)
|
cargo_util::exit_status_to_string(output.status)
|
||||||
},
|
},
|
||||||
code: output.status.code(),
|
code: output.status.code(),
|
||||||
stdout,
|
stdout,
|
||||||
|
@ -245,7 +246,7 @@ impl Cache {
|
||||||
if output.success {
|
if output.success {
|
||||||
Ok((output.stdout.clone(), output.stderr.clone()))
|
Ok((output.stdout.clone(), output.stderr.clone()))
|
||||||
} else {
|
} else {
|
||||||
Err(util::process_error_raw(
|
Err(ProcessError::new_raw(
|
||||||
&format!("process didn't exit successfully: {}", cmd),
|
&format!("process didn't exit successfully: {}", cmd),
|
||||||
output.code,
|
output.code,
|
||||||
&output.status,
|
&output.status,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::util::paths;
|
use crate::util::paths;
|
||||||
use crate::util::{process, CargoResult};
|
use crate::util::CargoResult;
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
// Check if we are in an existing repo. We define that to be true if either:
|
// Check if we are in an existing repo. We define that to be true if either:
|
||||||
|
@ -41,11 +42,15 @@ impl GitRepo {
|
||||||
|
|
||||||
impl HgRepo {
|
impl HgRepo {
|
||||||
pub fn init(path: &Path, cwd: &Path) -> CargoResult<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)
|
Ok(HgRepo)
|
||||||
}
|
}
|
||||||
pub fn discover(path: &Path, cwd: &Path) -> CargoResult<HgRepo> {
|
pub fn discover(path: &Path, cwd: &Path) -> CargoResult<HgRepo> {
|
||||||
process("hg")
|
ProcessBuilder::new("hg")
|
||||||
.cwd(cwd)
|
.cwd(cwd)
|
||||||
.arg("--cwd")
|
.arg("--cwd")
|
||||||
.arg(path)
|
.arg(path)
|
||||||
|
@ -57,7 +62,11 @@ impl HgRepo {
|
||||||
|
|
||||||
impl PijulRepo {
|
impl PijulRepo {
|
||||||
pub fn init(path: &Path, cwd: &Path) -> CargoResult<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)
|
Ok(PijulRepo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,28 +82,28 @@ impl FossilRepo {
|
||||||
db_path.push(db_fname);
|
db_path.push(db_fname);
|
||||||
|
|
||||||
// then create the fossil DB in that location
|
// then create the fossil DB in that location
|
||||||
process("fossil")
|
ProcessBuilder::new("fossil")
|
||||||
.cwd(cwd)
|
.cwd(cwd)
|
||||||
.arg("init")
|
.arg("init")
|
||||||
.arg(&db_path)
|
.arg(&db_path)
|
||||||
.exec()?;
|
.exec()?;
|
||||||
|
|
||||||
// open it in that new directory
|
// open it in that new directory
|
||||||
process("fossil")
|
ProcessBuilder::new("fossil")
|
||||||
.cwd(&path)
|
.cwd(&path)
|
||||||
.arg("open")
|
.arg("open")
|
||||||
.arg(db_fname)
|
.arg(db_fname)
|
||||||
.exec()?;
|
.exec()?;
|
||||||
|
|
||||||
// set `target` as ignoreable and cleanable
|
// set `target` as ignoreable and cleanable
|
||||||
process("fossil")
|
ProcessBuilder::new("fossil")
|
||||||
.cwd(cwd)
|
.cwd(cwd)
|
||||||
.arg("settings")
|
.arg("settings")
|
||||||
.arg("ignore-glob")
|
.arg("ignore-glob")
|
||||||
.arg("target")
|
.arg("target")
|
||||||
.exec()?;
|
.exec()?;
|
||||||
|
|
||||||
process("fossil")
|
ProcessBuilder::new("fossil")
|
||||||
.cwd(cwd)
|
.cwd(cwd)
|
||||||
.arg("settings")
|
.arg("settings")
|
||||||
.arg("clean-glob")
|
.arg("clean-glob")
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use super::ProcessBuilder;
|
|
||||||
use crate::core::compiler::Unit;
|
use crate::core::compiler::Unit;
|
||||||
use crate::core::manifest::TargetSourcePath;
|
use crate::core::manifest::TargetSourcePath;
|
||||||
use crate::core::{Target, Workspace};
|
use crate::core::{Target, Workspace};
|
||||||
use crate::ops::CompileOptions;
|
use crate::ops::CompileOptions;
|
||||||
use crate::util::CargoResult;
|
use crate::util::CargoResult;
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
|
use cargo_util::ProcessBuilder;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
//! cargo test --test testsuite -- old_cargos --nocapture --ignored
|
//! cargo test --test testsuite -- old_cargos --nocapture --ignored
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use cargo::util::{ProcessBuilder, ProcessError};
|
|
||||||
use cargo::CargoResult;
|
use cargo::CargoResult;
|
||||||
use cargo_test_support::paths::CargoPathExt;
|
use cargo_test_support::paths::CargoPathExt;
|
||||||
use cargo_test_support::registry::{self, Dependency, Package};
|
use cargo_test_support::registry::{self, Dependency, Package};
|
||||||
use cargo_test_support::{cargo_exe, execs, paths, process, project, rustc_host};
|
use cargo_test_support::{cargo_exe, execs, paths, process, project, rustc_host};
|
||||||
|
use cargo_util::{ProcessBuilder, ProcessError};
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ fn collect_all_toolchains() -> Vec<(Version, String)> {
|
||||||
format!("nightly-{}", host),
|
format!("nightly-{}", host),
|
||||||
];
|
];
|
||||||
|
|
||||||
let output = cargo::util::process("rustup")
|
let output = ProcessBuilder::new("rustup")
|
||||||
.args(&["toolchain", "list"])
|
.args(&["toolchain", "list"])
|
||||||
.exec_with_output()
|
.exec_with_output()
|
||||||
.expect("rustup should be installed");
|
.expect("rustup should be installed");
|
||||||
|
|
Loading…
Reference in New Issue