summaryrefslogtreecommitdiffstats
path: root/vendor/escargot/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/escargot/src')
-rw-r--r--vendor/escargot/src/bin/bin_fixture.rs33
-rw-r--r--vendor/escargot/src/build.rs340
-rw-r--r--vendor/escargot/src/cargo.rs60
-rw-r--r--vendor/escargot/src/error.rs91
-rw-r--r--vendor/escargot/src/format/diagnostic.rs158
-rw-r--r--vendor/escargot/src/format/mod.rs266
-rw-r--r--vendor/escargot/src/format/test.rs242
-rw-r--r--vendor/escargot/src/lib.rs59
-rw-r--r--vendor/escargot/src/msg.rs117
-rw-r--r--vendor/escargot/src/run.rs195
-rw-r--r--vendor/escargot/src/test.rs201
11 files changed, 1762 insertions, 0 deletions
diff --git a/vendor/escargot/src/bin/bin_fixture.rs b/vendor/escargot/src/bin/bin_fixture.rs
new file mode 100644
index 000000000..f47540f85
--- /dev/null
+++ b/vendor/escargot/src/bin/bin_fixture.rs
@@ -0,0 +1,33 @@
+use std::env;
+use std::error::Error;
+use std::io;
+use std::io::Write;
+use std::process;
+
+fn run() -> Result<(), Box<dyn Error>> {
+ if let Ok(text) = env::var("stdout") {
+ println!("{}", text);
+ }
+ if let Ok(text) = env::var("stderr") {
+ eprintln!("{}", text);
+ }
+
+ let code = env::var("exit")
+ .ok()
+ .map(|v| v.parse::<i32>())
+ .map(|r| r.map(Some))
+ .unwrap_or(Ok(None))?
+ .unwrap_or(0);
+ process::exit(code);
+}
+
+fn main() {
+ let code = match run() {
+ Ok(_) => 0,
+ Err(ref e) => {
+ write!(&mut io::stderr(), "{}", e).expect("writing to stderr won't fail");
+ 1
+ }
+ };
+ process::exit(code);
+}
diff --git a/vendor/escargot/src/build.rs b/vendor/escargot/src/build.rs
new file mode 100644
index 000000000..f37c1fb9e
--- /dev/null
+++ b/vendor/escargot/src/build.rs
@@ -0,0 +1,340 @@
+use std::ffi::{self, OsStr};
+use std::process;
+
+use crate::cargo::Cargo;
+use crate::cargo::CURRENT_TARGET;
+use crate::error::*;
+use crate::msg::*;
+use crate::run::CargoRun;
+#[cfg(feature = "test_unstable")]
+use crate::test::CargoTest;
+
+/// The `build` subcommand.
+///
+/// # Example
+///
+/// ```rust
+/// extern crate escargot;
+/// extern crate assert_fs;
+///
+/// let temp = assert_fs::TempDir::new().unwrap();
+/// escargot::CargoBuild::new()
+/// .bin("bin")
+/// .current_release()
+/// .current_target()
+/// .manifest_path("tests/fixtures/bin/Cargo.toml")
+/// .target_dir(temp.path())
+/// .exec()
+/// .unwrap();
+/// ```
+pub struct CargoBuild {
+ cmd: process::Command,
+ bin: bool,
+ example: bool,
+}
+
+impl CargoBuild {
+ /// Shortcut to create a `build` subcommand.
+ ///
+ /// See also [`Cargo`].
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// escargot::CargoBuild::new()
+ /// .bin("bin")
+ /// .manifest_path("tests/fixtures/bin/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .exec()
+ /// .unwrap();
+ /// ```
+ ///
+ pub fn new() -> Self {
+ Cargo::new().build()
+ }
+
+ pub(crate) fn with_command(cmd: process::Command) -> Self {
+ Self {
+ cmd,
+ bin: false,
+ example: false,
+ }
+ }
+
+ /// Build from `name` package in workspaces.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// escargot::CargoBuild::new()
+ /// .package("bin")
+ /// .bin("bin")
+ /// .manifest_path("tests/fixtures/bin/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .exec()
+ /// .unwrap();
+ /// ```
+ pub fn package<S: AsRef<ffi::OsStr>>(self, name: S) -> Self {
+ self.arg("--package").arg(name)
+ }
+ /// Build only `name` binary.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// escargot::CargoBuild::new()
+ /// .bin("bin")
+ /// .manifest_path("tests/fixtures/bin/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .exec()
+ /// .unwrap();
+ /// ```
+ pub fn bin<S: AsRef<ffi::OsStr>>(mut self, name: S) -> Self {
+ self.bin = true;
+ self.arg("--bin").arg(name)
+ }
+
+ /// Build all examples
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// escargot::CargoBuild::new()
+ /// .examples()
+ /// .manifest_path("tests/fixtures/example/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .exec()
+ /// .unwrap();
+ /// ```
+ pub fn examples(mut self) -> Self {
+ self.example = true;
+ self.arg("--examples")
+ }
+
+ /// Build only `name` example.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// escargot::CargoBuild::new()
+ /// .example("example_fixture")
+ /// .manifest_path("tests/fixtures/example/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .exec()
+ /// .unwrap();
+ /// ```
+ pub fn example<S: AsRef<ffi::OsStr>>(mut self, name: S) -> Self {
+ self.example = true;
+ self.arg("--example").arg(name)
+ }
+
+ /// Build all tests
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// escargot::CargoBuild::new()
+ /// .tests()
+ /// .manifest_path("tests/fixtures/test/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .exec()
+ /// .unwrap();
+ /// ```
+ pub fn tests(self) -> Self {
+ self.arg("--tests")
+ }
+
+ /// Build only `name` test.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// escargot::CargoBuild::new()
+ /// .test("test")
+ /// .manifest_path("tests/fixtures/test/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .exec()
+ /// .unwrap();
+ /// ```
+ pub fn test<S: AsRef<ffi::OsStr>>(self, name: S) -> Self {
+ self.arg("--test").arg(name)
+ }
+
+ /// Path to Cargo.toml
+ pub fn manifest_path<S: AsRef<ffi::OsStr>>(self, path: S) -> Self {
+ self.arg("--manifest-path").arg(path)
+ }
+
+ /// Build artifacts in release mode, with optimizations.
+ pub fn release(self) -> Self {
+ self.arg("--release")
+ }
+
+ /// Inserts or updates an environment variable mapping.
+ pub fn env<K, V>(mut self, key: K, val: V) -> Self
+ where
+ K: AsRef<OsStr>,
+ V: AsRef<OsStr>,
+ {
+ self.cmd.env(key, val);
+
+ self
+ }
+
+ /// Removes an environment variable
+ pub fn env_remove<K>(mut self, key: K) -> Self
+ where
+ K: AsRef<OsStr>,
+ {
+ self.cmd.env_remove(key);
+ self
+ }
+
+ /// Build artifacts in release mode if the current process has, with optimizations.
+ #[cfg(debug_assertions)]
+ pub fn current_release(self) -> Self {
+ self
+ }
+
+ /// Build artifacts in release mode if the current process has, with optimizations.
+ #[cfg(not(debug_assertions))]
+ pub fn current_release(self) -> Self {
+ self.release()
+ }
+
+ /// Build for the target triplet.
+ pub fn target<S: AsRef<ffi::OsStr>>(self, triplet: S) -> Self {
+ self.arg("--target").arg(triplet)
+ }
+
+ /// Build for the current process' triplet.
+ pub fn current_target(self) -> Self {
+ self.target(CURRENT_TARGET)
+ }
+
+ /// Directory for all generated artifacts
+ pub fn target_dir<S: AsRef<ffi::OsStr>>(self, dir: S) -> Self {
+ self.arg("--target-dir").arg(dir)
+ }
+
+ /// Activate all available features
+ pub fn all_features(self) -> Self {
+ self.arg("--all-features")
+ }
+
+ /// Do not activate the `default` feature
+ pub fn no_default_features(self) -> Self {
+ self.arg("--no-default-features")
+ }
+
+ /// Space-separated list of features to activate
+ pub fn features<S: AsRef<ffi::OsStr>>(self, features: S) -> Self {
+ self.arg("--features").arg(features)
+ }
+
+ /// Manually pass an argument that is unsupported.
+ ///
+ /// Caution: Passing in `--` can throw off the API.
+ pub fn arg<S: AsRef<ffi::OsStr>>(mut self, arg: S) -> Self {
+ self.cmd.arg(arg);
+ self
+ }
+
+ /// Manually pass arguments that are unsupported.
+ ///
+ /// Caution: Passing in `--` can throw off the API.
+ pub fn args<I: IntoIterator<Item = S>, S: AsRef<ffi::OsStr>>(mut self, args: I) -> Self {
+ self.cmd.args(args);
+ self
+ }
+
+ /// Build the configured target, returning compiler messages.
+ pub fn exec(self) -> CargoResult<CommandMessages> {
+ CommandMessages::with_command(self.cmd)
+ }
+
+ /// Provide a proxy for running the built target.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// let run = escargot::CargoBuild::new()
+ /// .bin("bin")
+ /// .current_release()
+ /// .current_target()
+ /// .manifest_path("tests/fixtures/bin/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .run()
+ /// .unwrap();
+ /// println!("artifact={}", run.path().display());
+ /// ```
+ pub fn run(self) -> CargoResult<CargoRun> {
+ let msgs = CommandMessages::with_command(self.cmd)?;
+ CargoRun::from_message(msgs, self.bin, self.example)
+ }
+
+ /// Provide a proxy for running the built target.
+ ///
+ /// Required feature: `test_unstable` since the format parsed is unstable.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// let run = escargot::CargoBuild::new()
+ /// .test("test")
+ /// .current_release()
+ /// .current_target()
+ /// .manifest_path("tests/fixtures/test/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .run_tests().unwrap()
+ /// .next().unwrap().unwrap();
+ /// println!("artifact={}", run.path().display());
+ /// ```
+ #[cfg(feature = "test_unstable")]
+ pub fn run_tests(self) -> CargoResult<impl Iterator<Item = Result<CargoTest, CargoError>>> {
+ let msgs = CommandMessages::with_command(self.cmd)?;
+ Ok(CargoTest::with_messages(msgs))
+ }
+}
+
+impl Default for CargoBuild {
+ fn default() -> Self {
+ Self::new()
+ }
+}
diff --git a/vendor/escargot/src/cargo.rs b/vendor/escargot/src/cargo.rs
new file mode 100644
index 000000000..6e8efd220
--- /dev/null
+++ b/vendor/escargot/src/cargo.rs
@@ -0,0 +1,60 @@
+use std::env;
+use std::ffi;
+use std::process;
+use std::str;
+
+use crate::build::CargoBuild;
+
+/// The current process' target triplet.
+pub const CURRENT_TARGET: &str = include_str!(concat!(env!("OUT_DIR"), "/current_target.txt"));
+
+static CARBO_BIN: once_cell::sync::Lazy<ffi::OsString> =
+ once_cell::sync::Lazy::new(|| env::var_os("CARGO").unwrap_or_else(|| "cargo".into()));
+
+/// Top-level command.
+#[derive(Debug)]
+pub struct Cargo {
+ cmd: process::Command,
+}
+
+impl Cargo {
+ /// Create a top-level command.
+ pub fn new() -> Self {
+ Self {
+ cmd: process::Command::new(CARBO_BIN.as_os_str()),
+ }
+ }
+
+ /// Manually pass an argument that is unsupported.
+ ///
+ /// Caution: Passing in a sub-command or `--` can throw off the API.
+ pub fn arg<S: AsRef<ffi::OsStr>>(mut self, arg: S) -> Self {
+ self.cmd.arg(arg);
+ self
+ }
+
+ /// Manually pass arguments that are unsupported.
+ ///
+ /// Caution: Passing in a sub-command or `--` can throw off the API.
+ pub fn args<I: IntoIterator<Item = S>, S: AsRef<ffi::OsStr>>(mut self, args: I) -> Self {
+ self.cmd.args(args);
+ self
+ }
+
+ /// Run the `build` subcommand.
+ pub fn build(self) -> CargoBuild {
+ self.build_with("build")
+ }
+
+ /// Run a custom `build` subcommand.
+ pub fn build_with<S: AsRef<ffi::OsStr>>(mut self, name: S) -> CargoBuild {
+ self.cmd.arg(name).arg("--message-format=json");
+ CargoBuild::with_command(self.cmd)
+ }
+}
+
+impl Default for Cargo {
+ fn default() -> Self {
+ Self::new()
+ }
+}
diff --git a/vendor/escargot/src/error.rs b/vendor/escargot/src/error.rs
new file mode 100644
index 000000000..4f19c4013
--- /dev/null
+++ b/vendor/escargot/src/error.rs
@@ -0,0 +1,91 @@
+//! Error reporting API.
+
+use std::error::Error;
+use std::fmt;
+
+/// Result of a cargo command.
+pub type CargoResult<T> = Result<T, CargoError>;
+
+/// For programmatically processing failures.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum ErrorKind {
+ /// Spawning the cargo subommand failed.
+ InvalidCommand,
+ /// The cargo subcommand returned an error.
+ CommandFailed,
+ /// Parsing the cargo subcommand's output failed.
+ InvalidOutput,
+}
+
+impl fmt::Display for ErrorKind {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *self {
+ ErrorKind::InvalidOutput => write!(f, "Spawning the cargo subommand failed."),
+ ErrorKind::CommandFailed => write!(f, "The cargo subcommand returned an error."),
+ ErrorKind::InvalidCommand => write!(f, "Parsing the cargo subcommand's output failed."),
+ }
+ }
+}
+
+/// Cargo command failure information.
+#[derive(Debug)]
+pub struct CargoError {
+ kind: ErrorKind,
+ context: Option<String>,
+ cause: Option<Box<dyn Error + Send + Sync + 'static>>,
+}
+
+impl CargoError {
+ pub(crate) fn new(kind: ErrorKind) -> Self {
+ Self {
+ kind,
+ context: None,
+ cause: None,
+ }
+ }
+
+ pub(crate) fn set_context<S>(mut self, context: S) -> Self
+ where
+ S: Into<String>,
+ {
+ let context = context.into();
+ self.context = Some(context);
+ self
+ }
+
+ pub(crate) fn set_cause<E>(mut self, cause: E) -> Self
+ where
+ E: Error + Send + Sync + 'static,
+ {
+ let cause = Box::new(cause);
+ self.cause = Some(cause);
+ self
+ }
+
+ /// For programmatically processing failures.
+ pub fn kind(&self) -> ErrorKind {
+ self.kind
+ }
+}
+
+impl Error for CargoError {
+ fn cause(&self) -> Option<&dyn Error> {
+ self.cause.as_ref().map(|c| {
+ let c: &dyn Error = c.as_ref();
+ c
+ })
+ }
+}
+
+impl fmt::Display for CargoError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ writeln!(f, "Cargo command failed: {}", self.kind)?;
+ if let Some(ref context) = self.context {
+ writeln!(f, "{}", context)?;
+ }
+ if let Some(ref cause) = self.cause {
+ writeln!(f, "Cause: {}", cause)?;
+ }
+ Ok(())
+ }
+}
diff --git a/vendor/escargot/src/format/diagnostic.rs b/vendor/escargot/src/format/diagnostic.rs
new file mode 100644
index 000000000..0a2698d17
--- /dev/null
+++ b/vendor/escargot/src/format/diagnostic.rs
@@ -0,0 +1,158 @@
+//! This module contains `Diagnostic` and the types/functions it uses for deserialization.
+
+use std::borrow;
+use std::path;
+
+type CowPath<'a> = borrow::Cow<'a, path::Path>;
+type CowStr<'a> = borrow::Cow<'a, str>;
+
+/// The error code associated to this diagnostic.
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+#[non_exhaustive]
+pub struct DiagnosticCode<'a> {
+ /// The code itself.
+ #[serde(borrow)]
+ pub code: CowStr<'a>,
+ /// An explanation for the code
+ #[serde(borrow)]
+ pub explanation: Option<CowStr<'a>>,
+}
+
+/// A line of code associated with the Diagnostic
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+#[non_exhaustive]
+pub struct DiagnosticSpanLine<'a> {
+ /// The line of code associated with the error
+ #[serde(borrow)]
+ pub text: CowStr<'a>,
+ /// Start of the section of the line to highlight. 1-based, character offset in self.text
+ pub highlight_start: usize,
+ /// End of the section of the line to highlight. 1-based, character offset in self.text
+ pub highlight_end: usize,
+}
+
+/// Macro expansion information associated with a diagnostic.
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+#[non_exhaustive]
+pub struct DiagnosticSpanMacroExpansion<'a> {
+ /// span where macro was applied to generate this code; note that
+ /// this may itself derive from a macro (if
+ /// `span.expansion.is_some()`)
+ #[serde(borrow)]
+ pub span: DiagnosticSpan<'a>,
+
+ /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]")
+ #[serde(borrow)]
+ pub macro_decl_name: CowStr<'a>,
+
+ /// span where macro was defined (if known)
+ #[serde(borrow)]
+ pub def_site_span: Option<DiagnosticSpan<'a>>,
+}
+
+/// A section of the source code associated with a Diagnostic
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+#[non_exhaustive]
+pub struct DiagnosticSpan<'a> {
+ /// The file name this diagnostic comes from.
+ #[serde(borrow)]
+ pub file_name: CowPath<'a>,
+ /// The byte offset in the file where this diagnostic starts from.
+ pub byte_start: u32,
+ /// The byte offset in the file where this diagnostic ends.
+ pub byte_end: u32,
+ /// 1-based. The line in the file.
+ pub line_start: usize,
+ /// 1-based. The line in the file.
+ pub line_end: usize,
+ /// 1-based, character offset.
+ pub column_start: usize,
+ /// 1-based, character offset.
+ pub column_end: usize,
+ /// Is this a "primary" span -- meaning the point, or one of the points,
+ /// where the error occurred?
+ pub is_primary: bool,
+ /// Source text from the start of line_start to the end of line_end.
+ #[serde(borrow)]
+ pub text: Vec<DiagnosticSpanLine<'a>>,
+ /// Label that should be placed at this location (if any)
+ #[serde(borrow)]
+ pub label: Option<CowStr<'a>>,
+ /// If we are suggesting a replacement, this will contain text
+ /// that should be sliced in atop this span.
+ #[serde(borrow)]
+ pub suggested_replacement: Option<CowStr<'a>>,
+ /// If the suggestion is approximate
+ pub suggestion_applicability: Option<Applicability>,
+ /// Macro invocations that created the code at this span, if any.
+ #[serde(borrow)]
+ pub expansion: Option<Box<DiagnosticSpanMacroExpansion<'a>>>,
+}
+
+/// Whether a suggestion can be safely applied.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
+pub enum Applicability {
+ /// The suggested replacement can be applied automatically safely
+ MachineApplicable,
+ /// The suggested replacement has placeholders that will need to be manually
+ /// replaced.
+ HasPlaceholders,
+ /// The suggested replacement may be incorrect in some circumstances. Needs
+ /// human review.
+ MaybeIncorrect,
+ /// The suggested replacement will probably not work.
+ Unspecified,
+ #[cfg(not(feature = "strict_unstable"))]
+ #[doc(hidden)]
+ #[serde(other)]
+ Unknown,
+}
+
+/// A diagnostic message generated by rustc
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+#[non_exhaustive]
+pub struct Diagnostic<'a> {
+ /// The error message of this diagnostic.
+ #[serde(borrow)]
+ pub message: CowStr<'a>,
+ /// The associated error code for this diagnostic
+ #[serde(borrow)]
+ pub code: Option<DiagnosticCode<'a>>,
+ /// The severity of the diagnostic.
+ pub level: DiagnosticLevel,
+ /// A list of source code spans this diagnostic is associated with.
+ #[serde(borrow)]
+ pub spans: Vec<DiagnosticSpan<'a>>,
+ /// Associated diagnostic messages.
+ #[serde(borrow)]
+ pub children: Vec<Diagnostic<'a>>,
+ /// The message as rustc would render it
+ #[serde(borrow)]
+ pub rendered: Option<CowStr<'a>>,
+}
+
+/// The diagnostic level
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "lowercase")]
+pub enum DiagnosticLevel {
+ /// Internal compiler error
+ #[serde(rename = "error: internal compiler error")]
+ Ice,
+ /// Error
+ Error,
+ /// Warning
+ Warning,
+ /// Note
+ Note,
+ /// Help
+ Help,
+ #[cfg(not(feature = "strict_unstable"))]
+ #[doc(hidden)]
+ #[serde(other)]
+ Unknown,
+}
diff --git a/vendor/escargot/src/format/mod.rs b/vendor/escargot/src/format/mod.rs
new file mode 100644
index 000000000..9c9686139
--- /dev/null
+++ b/vendor/escargot/src/format/mod.rs
@@ -0,0 +1,266 @@
+//! Serialization formats for cargo messages.
+
+use std::borrow;
+use std::path;
+
+pub mod diagnostic;
+
+#[cfg(feature = "test_unstable")]
+pub mod test;
+
+type CowPath<'a> = borrow::Cow<'a, path::Path>;
+type CowStr<'a> = borrow::Cow<'a, str>;
+
+/// A cargo message
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(tag = "reason", rename_all = "kebab-case")]
+#[allow(clippy::large_enum_variant)]
+pub enum Message<'a> {
+ /// Build completed, all further output should not be parsed
+ BuildFinished(BuildFinished),
+ /// The compiler generated an artifact
+ #[serde(borrow)]
+ CompilerArtifact(Artifact<'a>),
+ /// The compiler wants to display a message
+ #[serde(borrow)]
+ CompilerMessage(FromCompiler<'a>),
+ /// A build script successfully executed.
+ #[serde(borrow)]
+ BuildScriptExecuted(BuildScript<'a>),
+ #[cfg(not(feature = "strict_unstable"))]
+ #[doc(hidden)]
+ #[serde(other)]
+ Unknown,
+}
+
+/// Build completed, all further output should not be parsed
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+#[non_exhaustive]
+pub struct BuildFinished {
+ success: bool,
+}
+
+/// A compiler-generated file.
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+#[non_exhaustive]
+pub struct Artifact<'a> {
+ /// The workspace member this artifact belongs to
+ #[serde(borrow)]
+ pub package_id: WorkspaceMember<'a>,
+ /// The full path to the artifact's manifest
+ #[serde(borrow)]
+ pub manifest_path: Option<CowPath<'a>>,
+ /// The target this artifact was compiled for
+ #[serde(borrow)]
+ pub target: Target<'a>,
+ /// The profile this artifact was compiled with
+ #[serde(borrow)]
+ pub profile: ArtifactProfile<'a>,
+ /// The enabled features for this artifact
+ #[serde(borrow)]
+ pub features: Vec<CowStr<'a>>,
+ /// The full paths to the generated artifacts
+ #[serde(borrow)]
+ pub filenames: Vec<CowPath<'a>>,
+ /// The full paths to the generated artifacts
+ #[serde(borrow)]
+ #[serde(default)]
+ pub executable: Option<CowPath<'a>>,
+ /// If true, then the files were already generated
+ pub fresh: bool,
+}
+
+/// A single target (lib, bin, example, ...) provided by a crate
+#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+#[non_exhaustive]
+pub struct Target<'a> {
+ /// Name as given in the `Cargo.toml` or generated from the file name
+ #[serde(borrow)]
+ pub name: CowStr<'a>,
+ /// Kind of target ("bin", "example", "test", "bench", "lib")
+ #[serde(borrow)]
+ pub kind: Vec<CowStr<'a>>,
+ /// Almost the same as `kind`, except when an example is a library instead of an executable.
+ /// In that case `crate_types` contains things like `rlib` and `dylib` while `kind` is `example`
+ #[serde(default)]
+ #[serde(borrow)]
+ pub crate_types: Vec<CowStr<'a>>,
+ /// Whether this is a doctest or not
+ #[serde(default)]
+ pub doctest: Option<bool>,
+ /// Whether this is documentation or not
+ #[serde(default)]
+ pub doc: Option<bool>,
+ /// Whether this is a test file
+ #[serde(default)]
+ pub test: bool,
+
+ #[serde(default)]
+ #[serde(rename = "required-features")]
+ /// This target is built only if these features are enabled.
+ /// It doesn't apply to `lib` targets.
+ #[serde(borrow)]
+ pub required_features: Vec<CowStr<'a>>,
+ /// Path to the main source file of the target
+ #[serde(borrow)]
+ pub src_path: CowPath<'a>,
+ /// Rust edition for this target
+ #[serde(default = "edition_default")]
+ #[serde(borrow)]
+ pub edition: CowStr<'a>,
+}
+
+fn edition_default() -> CowStr<'static> {
+ "2015".into()
+}
+
+/// A workspace member. This is basically identical to `cargo::core::package_id::PackageId`, except
+/// that this does not use `Arc` internally.
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
+#[serde(transparent)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+pub struct WorkspaceMember<'a> {
+ /// The raw package id as given by cargo
+ #[serde(borrow)]
+ raw: CowStr<'a>,
+}
+
+/// Profile settings used to determine which compiler flags to use for a
+/// target.
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+#[non_exhaustive]
+pub struct ArtifactProfile<'a> {
+ /// Optimization level. Possible values are 0-3, s or z.
+ #[serde(borrow)]
+ pub opt_level: CowStr<'a>,
+ /// The amount of debug info. 0 for none, 1 for limited, 2 for full
+ pub debuginfo: Option<u32>,
+ /// State of the `cfg(debug_assertions)` directive, enabling macros like
+ /// `debug_assert!`
+ pub debug_assertions: bool,
+ /// State of the overflow checks.
+ pub overflow_checks: bool,
+ /// Whether this profile is a test
+ pub test: bool,
+}
+
+/// Message left by the compiler
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+#[non_exhaustive]
+pub struct FromCompiler<'a> {
+ /// The workspace member this message belongs to
+ #[serde(borrow)]
+ pub package_id: WorkspaceMember<'a>,
+ /// The full path to the artifact's manifest
+ #[serde(borrow)]
+ pub manifest_path: Option<CowPath<'a>>,
+ /// The target this message is aimed at
+ #[serde(borrow)]
+ pub target: Target<'a>,
+ /// The message the compiler sent.
+ #[serde(borrow)]
+ pub message: diagnostic::Diagnostic<'a>,
+}
+
+/// Output of a Build Script execution.
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))]
+#[non_exhaustive]
+pub struct BuildScript<'a> {
+ /// The workspace member this build script execution belongs to
+ #[serde(borrow)]
+ pub package_id: WorkspaceMember<'a>,
+ /// The outdir used.
+ #[serde(borrow)]
+ #[serde(default)]
+ pub out_dir: Option<CowPath<'a>>,
+ /// The libs to link
+ #[serde(borrow)]
+ pub linked_libs: Vec<CowStr<'a>>,
+ /// The paths to search when resolving libs
+ #[serde(borrow)]
+ pub linked_paths: Vec<CowPath<'a>>,
+ /// The paths to search when resolving libs
+ #[serde(borrow)]
+ pub cfgs: Vec<CowPath<'a>>,
+ /// The environment variables to add to the compilation
+ #[serde(borrow)]
+ pub env: Vec<(CowStr<'a>, CowStr<'a>)>,
+}
+
+#[cfg(not(feature = "print"))]
+pub(crate) fn log_message(msg: &Message<'_>) {
+ match msg {
+ Message::BuildFinished(ref finished) => {
+ log::trace!("Build Finished: {:?}", finished.success);
+ }
+ Message::CompilerArtifact(ref art) => {
+ log::trace!("Building {:#?}", art.package_id,);
+ }
+ Message::CompilerMessage(ref comp) => {
+ let content = comp
+ .message
+ .rendered
+ .as_ref()
+ .map(|s| s.as_ref())
+ .unwrap_or_else(|| comp.message.message.as_ref());
+ match comp.message.level {
+ diagnostic::DiagnosticLevel::Ice => log::error!("{}", content),
+ diagnostic::DiagnosticLevel::Error => log::error!("{}", content),
+ diagnostic::DiagnosticLevel::Warning => log::warn!("{}", content),
+ diagnostic::DiagnosticLevel::Note => log::info!("{}", content),
+ diagnostic::DiagnosticLevel::Help => log::info!("{}", content),
+ #[cfg(not(feature = "strict_unstable"))]
+ _ => log::warn!("Unknown message: {:#?}", msg),
+ }
+ }
+ Message::BuildScriptExecuted(ref script) => {
+ log::trace!("Ran script from {:#?}", script.package_id);
+ }
+ #[cfg(not(feature = "strict_unstable"))]
+ _ => {
+ log::warn!("Unknown message: {:#?}", msg);
+ }
+ }
+}
+
+#[cfg(feature = "print")]
+pub(crate) fn log_message(msg: &Message<'_>) {
+ match msg {
+ Message::BuildFinished(ref finished) => {
+ eprintln!("Build Finished: {:?}", finished.success);
+ }
+ Message::CompilerArtifact(ref art) => {
+ eprintln!("Building {:#?}", art.package_id,);
+ }
+ Message::CompilerMessage(ref comp) => {
+ let content = comp
+ .message
+ .rendered
+ .as_ref()
+ .map(|s| s.as_ref())
+ .unwrap_or_else(|| comp.message.message.as_ref());
+ match comp.message.level {
+ diagnostic::DiagnosticLevel::Ice => eprintln!("{}", content),
+ diagnostic::DiagnosticLevel::Error => eprintln!("{}", content),
+ diagnostic::DiagnosticLevel::Warning => eprintln!("{}", content),
+ diagnostic::DiagnosticLevel::Note => eprintln!("{}", content),
+ diagnostic::DiagnosticLevel::Help => eprintln!("{}", content),
+ #[cfg(not(feature = "strict_unstable"))]
+ _ => eprintln!("Unknown message: {:#?}", msg),
+ }
+ }
+ Message::BuildScriptExecuted(ref script) => {
+ eprintln!("Ran script from {:#?}", script.package_id);
+ }
+ #[cfg(not(feature = "strict_unstable"))]
+ _ => {
+ eprintln!("Unknown message: {:#?}", msg);
+ }
+ }
+}
diff --git a/vendor/escargot/src/format/test.rs b/vendor/escargot/src/format/test.rs
new file mode 100644
index 000000000..f046df9cf
--- /dev/null
+++ b/vendor/escargot/src/format/test.rs
@@ -0,0 +1,242 @@
+//! Test runner emitted events.
+//!
+//! Required feature: `test_unstable` since the format parsed is unstable.
+
+use serde::Deserialize;
+
+// See https://github.com/rust-lang/rust/tree/master/src/libtest/formatters/json.rs
+
+/// Test-runner event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[serde(rename_all = "snake_case")]
+#[serde(tag = "type")]
+pub enum Event {
+ /// Suite event.
+ Suite(Suite),
+ /// Test case event.
+ Test(Test),
+ /// Benchmark event.
+ Bench(Bench),
+ #[cfg(not(feature = "strict_unstable"))]
+ #[doc(hidden)]
+ #[serde(other)]
+ Unknown,
+}
+
+/// Suite event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[serde(rename_all = "snake_case")]
+#[serde(tag = "event")]
+pub enum Suite {
+ /// Suite-started event.
+ Started(SuiteStarted),
+ /// Suite-finished successfully event.
+ Ok(SuiteOk),
+ /// Suite-finished with failure event.
+ Failed(SuiteFailed),
+ #[cfg(not(feature = "strict_unstable"))]
+ #[doc(hidden)]
+ #[serde(other)]
+ Unknown,
+}
+
+/// Suite-started event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub struct SuiteStarted {
+ /// Number of test cases in the suite.
+ pub test_count: usize,
+}
+
+/// Suite-finished successfully event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub struct SuiteOk {
+ /// Cases that passed.
+ pub passed: usize,
+ /// Cases that failed.
+ pub failed: usize,
+ /// Cases that were allowed to fail.
+ pub allowed_fail: usize,
+ /// Ignored cases.
+ pub ignored: usize,
+ /// Benchmarks
+ pub measured: usize,
+ /// Cases filtered out by caller.
+ pub filtered_out: usize,
+}
+
+/// Suite-finished with failure event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub struct SuiteFailed {
+ /// Cases that passed.
+ pub passed: usize,
+ /// Cases that failed.
+ pub failed: usize,
+ /// Cases that were allowed to fail.
+ pub allowed_fail: usize,
+ /// Ignored cases.
+ pub ignored: usize,
+ /// Benchmarks
+ pub measured: usize,
+ /// Cases filtered out by caller.
+ pub filtered_out: usize,
+}
+
+/// Test case event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[serde(rename_all = "snake_case")]
+#[serde(tag = "event")]
+pub enum Test {
+ /// Case-started event.
+ Started(TestStarted),
+ /// Case-finished successfully event.
+ Ok(TestOk),
+ /// Case-finished with failure event.
+ Failed(TestFailed),
+ /// Case-ignored event.
+ Ignored(TestIgnored),
+ /// Case-allowed-failure event.
+ AllowedFailure(TestAllowedFailured),
+ /// Case-timeout event.
+ Timeout(TestTimeout),
+ #[cfg(not(feature = "strict_unstable"))]
+ #[doc(hidden)]
+ #[serde(other)]
+ Unknown,
+}
+
+/// Case-started event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub struct TestStarted {
+ /// Test case name.
+ pub name: String,
+}
+
+/// Case-finished successfully event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub struct TestOk {
+ /// Test case name.
+ pub name: String,
+}
+
+/// Case-finished with failure event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub struct TestFailed {
+ /// Test case name.
+ pub name: String,
+ /// Test's stdout
+ pub stdout: Option<String>,
+ /// Test failure mssage
+ pub message: Option<String>,
+}
+
+/// Case-ignored event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub struct TestIgnored {
+ /// Test case name.
+ pub name: String,
+}
+
+/// Case-allowed-failure event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub struct TestAllowedFailured {
+ /// Test case name.
+ pub name: String,
+}
+
+/// Case-timeout event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub struct TestTimeout {
+ /// Test case name.
+ pub name: String,
+}
+
+/// Benchmark event.
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
+#[non_exhaustive]
+pub struct Bench {
+ /// Benchmark name.
+ pub name: String,
+ /// Median performance.
+ pub median: usize,
+ /// Deviation from median.
+ pub deviation: usize,
+ /// Mb/s
+ pub mib_per_second: Option<usize>,
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn suite_started() {
+ let input = r#"{ "type": "suite", "event": "started", "test_count": 10 }"#;
+ let _data: Event = serde_json::from_str(input).unwrap();
+ }
+
+ #[test]
+ fn suite_ok() {
+ let input = "{ \"type\": \"suite\", \
+ \"event\": \"ok\", \
+ \"passed\": 6, \
+ \"failed\": 5, \
+ \"allowed_fail\": 4, \
+ \"ignored\": 3, \
+ \"measured\": 2, \
+ \"filtered_out\": 1 }";
+ let _data: Event = serde_json::from_str(input).unwrap();
+ }
+
+ #[test]
+ fn suite_failed() {
+ let input = "{ \"type\": \"suite\", \
+ \"event\": \"failed\", \
+ \"passed\": 6, \
+ \"failed\": 5, \
+ \"allowed_fail\": 4, \
+ \"ignored\": 3, \
+ \"measured\": 2, \
+ \"filtered_out\": 1 }";
+ let _data: Event = serde_json::from_str(input).unwrap();
+ }
+
+ #[test]
+ fn test_started() {
+ let input = r#"{ "type": "test", "event": "started", "name": "foo" }"#;
+ let _data: Event = serde_json::from_str(input).unwrap();
+ }
+
+ #[test]
+ fn test_timeout() {
+ let input = r#"{ "type": "test", "event": "timeout", "name": "foo" }"#;
+ let _data: Event = serde_json::from_str(input).unwrap();
+ }
+
+ #[test]
+ fn bench() {
+ let input = "{ \"type\": \"bench\", \
+ \"name\": \"foo\", \
+ \"median\": 10, \
+ \"deviation\": 2 }";
+ let _data: Event = serde_json::from_str(input).unwrap();
+ }
+
+ #[test]
+ fn bench_full() {
+ let input = "{ \"type\": \"bench\", \
+ \"name\": \"foo\", \
+ \"median\": 10, \
+ \"deviation\": 2, \
+ \"mib_per_second\": 1 }";
+ let _data: Event = serde_json::from_str(input).unwrap();
+ }
+}
diff --git a/vendor/escargot/src/lib.rs b/vendor/escargot/src/lib.rs
new file mode 100644
index 000000000..dd6559131
--- /dev/null
+++ b/vendor/escargot/src/lib.rs
@@ -0,0 +1,59 @@
+//! # Escargot: A Cargo API
+//!
+//! ## Features
+//!
+//! Features:
+//! - `print` for logged output to be printed instead, generally for test writing.
+//!
+//! ## Why escargot
+//!
+//! Compared to depending on `cargo`:
+//! - Faster compile times.
+//! - Simpler API.
+//! - Better interop with projects relying on other cargo versions.
+//! - Probably slower execution, especially on platforms without an optimized `fork` (e.g. Windows).
+//!
+//! ## Relevant crates
+//!
+//! Other related crates:
+//! * [cargo](https://crates.io/crates/cargo) for the real thing
+//! * [cargo-metadata](https://crates.io/crates/cargo_metadata) for a similar project specifically geared to the `metadata` subcommand.
+//!
+//! # Example
+//!
+//! ```rust
+//! extern crate escargot;
+//! extern crate assert_fs;
+//!
+//! let temp = assert_fs::TempDir::new().unwrap();
+//! escargot::CargoBuild::new()
+//! .bin("bin")
+//! .current_release()
+//! .current_target()
+//! .manifest_path("tests/fixtures/bin/Cargo.toml")
+//! .target_dir(temp.path())
+//! .exec()
+//! .unwrap();
+//! ```
+
+#![warn(missing_docs)]
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+
+#[macro_use]
+extern crate serde;
+
+mod build;
+pub use crate::build::*;
+mod cargo;
+pub use crate::cargo::*;
+mod msg;
+pub use crate::msg::*;
+mod run;
+pub use crate::run::*;
+#[cfg(feature = "test_unstable")]
+mod test;
+#[cfg(feature = "test_unstable")]
+pub use test::*;
+
+pub mod error;
+pub mod format;
diff --git a/vendor/escargot/src/msg.rs b/vendor/escargot/src/msg.rs
new file mode 100644
index 000000000..b54a1d410
--- /dev/null
+++ b/vendor/escargot/src/msg.rs
@@ -0,0 +1,117 @@
+use std::io;
+use std::io::BufRead;
+use std::io::Read;
+use std::process;
+
+use crate::error::*;
+use crate::format;
+
+/// Messages returned from a cargo sub-command.
+pub struct CommandMessages(InnerCommandMessages);
+
+struct InnerCommandMessages {
+ done: bool,
+ child: process::Child,
+ stdout: io::BufReader<process::ChildStdout>,
+ stderr: io::BufReader<process::ChildStderr>,
+}
+
+impl CommandMessages {
+ /// Run the command, allowing iteration over ndjson messages.
+ pub fn with_command(mut cmd: process::Command) -> CargoResult<Self> {
+ let mut child = cmd
+ .stdout(process::Stdio::piped())
+ .stderr(process::Stdio::piped())
+ .spawn()
+ .map_err(|e| CargoError::new(ErrorKind::InvalidCommand).set_cause(e))?;
+ let stdout = child.stdout.take().expect("piped above");
+ let stdout = io::BufReader::new(stdout);
+ let stderr = child.stderr.take().expect("piped above");
+ let stderr = io::BufReader::new(stderr);
+ let msgs = InnerCommandMessages {
+ done: false,
+ child,
+ stdout,
+ stderr,
+ };
+ Ok(CommandMessages(msgs))
+ }
+
+ #[inline]
+ fn next_msg(&mut self) -> CargoResult<Option<Message>> {
+ #![allow(clippy::branches_sharing_code)]
+
+ let mut content = String::new();
+ let len = self
+ .0
+ .stdout
+ .read_line(&mut content)
+ .map_err(|e| CargoError::new(ErrorKind::InvalidOutput).set_cause(e))?;
+ if 0 < len {
+ Ok(Some(Message(content)))
+ } else {
+ let status = self
+ .0
+ .child
+ .wait()
+ .map_err(|e| CargoError::new(ErrorKind::InvalidOutput).set_cause(e))?;
+ if !status.success() && !self.0.done {
+ self.0.done = true;
+
+ let mut data = vec![];
+ self.0
+ .stderr
+ .read_to_end(&mut data)
+ .map_err(|e| CargoError::new(ErrorKind::InvalidOutput).set_cause(e))?;
+ let err = CargoError::new(ErrorKind::CommandFailed)
+ .set_context(String::from_utf8_lossy(&data));
+ Err(err)
+ } else {
+ self.0.done = true;
+ Ok(None)
+ }
+ }
+ }
+}
+
+impl Drop for CommandMessages {
+ fn drop(&mut self) {
+ if !self.0.done {
+ let _ = self.0.child.wait();
+ }
+ }
+}
+
+impl Iterator for CommandMessages {
+ type Item = CargoResult<Message>;
+
+ #[inline]
+ fn next(&mut self) -> Option<CargoResult<Message>> {
+ match self.next_msg() {
+ Ok(Some(x)) => Some(Ok(x)),
+ Ok(None) => None,
+ Err(e) => Some(Err(e)),
+ }
+ }
+}
+
+/// An individual message from a cargo sub-command.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Message(String);
+
+impl Message {
+ /// Deserialize the message.
+ pub fn decode(&self) -> CargoResult<format::Message<'_>> {
+ self.decode_custom()
+ }
+
+ /// Deserialize the message.
+ pub fn decode_custom<'a, T>(&'a self) -> CargoResult<T>
+ where
+ T: serde::Deserialize<'a>,
+ {
+ let data = serde_json::from_str(self.0.as_str())
+ .map_err(|e| CargoError::new(ErrorKind::InvalidOutput).set_cause(e))?;
+ Ok(data)
+ }
+}
diff --git a/vendor/escargot/src/run.rs b/vendor/escargot/src/run.rs
new file mode 100644
index 000000000..e8aed96bb
--- /dev/null
+++ b/vendor/escargot/src/run.rs
@@ -0,0 +1,195 @@
+use std::path;
+use std::process;
+
+use crate::error::*;
+use crate::format;
+use crate::msg::*;
+
+/// The `run` subcommand (emulated).
+///
+/// Created via [`CargoBuild::run`][crate::CargoBuild::run].
+///
+/// Benefits over spawning `cargo run`:
+/// - Able to cache binary path, avoiding cargo overhead.
+/// - Independent of CWD.
+/// - stdout/stderr are clean of `cargo run` output.
+///
+/// Relevant features
+/// - `print` for logged output to be printed instead, generally for test writing.
+///
+/// # Example
+///
+/// To create a [`CargoRun`]:
+/// ```rust
+/// let temp = assert_fs::TempDir::new().unwrap();
+/// let run = escargot::CargoBuild::new()
+/// .bin("bin")
+/// .current_release()
+/// .current_target()
+/// .manifest_path("tests/fixtures/bin/Cargo.toml")
+/// .target_dir(temp.path())
+/// .run()
+/// .unwrap();
+/// println!("artifact={}", run.path().display());
+/// ```
+/// See [`CargoRun::path`] for how to then run the newly compiled
+/// program.
+pub struct CargoRun {
+ bin_path: path::PathBuf,
+}
+
+impl CargoRun {
+ pub(crate) fn from_message(
+ msgs: CommandMessages,
+ is_bin: bool,
+ is_example: bool,
+ ) -> CargoResult<Self> {
+ let kind = match (is_bin, is_example) {
+ (true, true) => {
+ return Err(CargoError::new(ErrorKind::CommandFailed)
+ .set_context("Ambiguous which binary is intended, multiple selected"));
+ }
+ (false, true) => "example",
+ _ => "bin",
+ };
+ let bin_path = extract_binary_path(msgs, kind)?;
+ Ok(Self { bin_path })
+ }
+
+ /// Path to the specified binary.
+ ///
+ /// This is to support alternative ways of launching the binary besides [`Command`].
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// let run = escargot::CargoBuild::new()
+ /// .bin("bin")
+ /// .current_release()
+ /// .current_target()
+ /// .manifest_path("tests/fixtures/bin/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .run()
+ /// .unwrap();
+ /// println!("artifact={}", run.path().display());
+ /// ```
+ /// or
+ /// ```rust,no_run
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// let run = escargot::CargoBuild::new()
+ /// .example("example_fixture")
+ /// .current_release()
+ /// .current_target()
+ /// .manifest_path("tests/fixtures/example/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .run()
+ /// .unwrap();
+ /// println!("artifact={}", run.path().display());
+ /// ```
+ ///
+ /// [`Command`]: std::process::Command
+ pub fn path(&self) -> &path::Path {
+ &self.bin_path
+ }
+
+ /// Run the build artifact.
+ ///
+ /// # Example
+ ///
+ /// ```rust,no_run
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// let run = escargot::CargoBuild::new()
+ /// .bin("bin")
+ /// .current_release()
+ /// .current_target()
+ /// .manifest_path("tests/fixtures/bin/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .run()
+ /// .unwrap()
+ /// .command()
+ /// .arg("--help")
+ /// .status()
+ /// .unwrap();
+ /// ```
+ /// or
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// let run = escargot::CargoBuild::new()
+ /// .example("example_fixture")
+ /// .current_release()
+ /// .current_target()
+ /// .manifest_path("tests/fixtures/example/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .run()
+ /// .unwrap()
+ /// .command()
+ /// .arg("--help")
+ /// .status()
+ /// .unwrap();
+ /// ```
+ pub fn command(&self) -> process::Command {
+ process::Command::new(self.path())
+ }
+}
+
+fn extract_bin<'a>(msg: &'a format::Message<'_>, desired_kind: &str) -> Option<&'a path::Path> {
+ match msg {
+ format::Message::CompilerArtifact(art) => {
+ if !art.profile.test
+ && art.target.crate_types == ["bin"]
+ && art.target.kind == [desired_kind]
+ {
+ Some(art.filenames.get(0).expect("files must exist"))
+ } else {
+ None
+ }
+ }
+ _ => None,
+ }
+}
+
+fn transpose<T, E>(r: Result<Option<T>, E>) -> Option<Result<T, E>> {
+ match r {
+ Ok(Some(x)) => Some(Ok(x)),
+ Ok(None) => None,
+ Err(e) => Some(Err(e)),
+ }
+}
+
+fn extract_binary_paths(
+ msgs: CommandMessages,
+ kind: &'static str,
+) -> impl Iterator<Item = Result<path::PathBuf, CargoError>> {
+ msgs.filter_map(move |m| {
+ let m = m.and_then(|m| {
+ let m = m.decode()?;
+ format::log_message(&m);
+ let p = extract_bin(&m, kind).map(|p| p.to_path_buf());
+ Ok(p)
+ });
+ transpose(m)
+ })
+}
+
+fn extract_binary_path(
+ msgs: CommandMessages,
+ kind: &'static str,
+) -> Result<path::PathBuf, CargoError> {
+ let bins: Result<Vec<_>, CargoError> = extract_binary_paths(msgs, kind).collect();
+ let bins = bins?;
+ if bins.is_empty() {
+ return Err(CargoError::new(ErrorKind::CommandFailed).set_context("No binaries in crate"));
+ } else if bins.len() != 1 {
+ return Err(
+ CargoError::new(ErrorKind::CommandFailed).set_context(std::format!(
+ "Ambiguous which binary is intended: {:?}",
+ bins
+ )),
+ );
+ }
+ Ok(bins.into_iter().next().expect("already validated"))
+}
diff --git a/vendor/escargot/src/test.rs b/vendor/escargot/src/test.rs
new file mode 100644
index 000000000..5aebacfec
--- /dev/null
+++ b/vendor/escargot/src/test.rs
@@ -0,0 +1,201 @@
+use std::path;
+use std::process;
+
+use crate::error::*;
+use crate::format;
+use crate::msg::*;
+
+/// The `test` subcommand (emulated).
+///
+/// Created via [`CargoBuild::run_tests`].
+///
+/// Benefits over spawning `cargo test`:
+/// - Able to cache binary path, avoiding cargo overhead.
+/// - Independent of CWD.
+/// - stdout/stderr are clean of `cargo test` output.
+///
+/// Required feature: `test_unstable` since the format parsed is unstable.
+///
+/// Relevant features
+/// - `print` for logged output to be printed instead, generally for test writing.
+///
+/// # Example
+///
+/// ```rust
+/// extern crate escargot;
+/// extern crate assert_fs;
+///
+/// let temp = assert_fs::TempDir::new().unwrap();
+/// let run = escargot::CargoBuild::new()
+/// .test("test")
+/// .manifest_path("tests/fixtures/test/Cargo.toml")
+/// .target_dir(temp.path())
+/// .run_tests().unwrap()
+/// .next().unwrap().unwrap();
+/// println!("artifact={}", run.path().display());
+/// ```
+///
+/// [`CargoBuild::run_tests`]: crate::CargoBuild::run_tests()
+pub struct CargoTest {
+ bin_path: path::PathBuf,
+ kind: String,
+ name: String,
+}
+
+impl CargoTest {
+ pub(crate) fn with_messages(
+ msgs: CommandMessages,
+ ) -> impl Iterator<Item = Result<Self, CargoError>> {
+ extract_binary_paths(msgs)
+ }
+
+ /// The `name` of test
+ ///
+ /// Used to offer filtering or displays.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// let run: Result<Vec<_>, _> = escargot::CargoBuild::new()
+ /// .tests()
+ /// .current_release()
+ /// .current_target()
+ /// .manifest_path("tests/fixtures/test/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .run_tests()
+ /// .unwrap()
+ /// .collect();
+ /// let run = run.unwrap();
+ /// let mut names: Vec<_> = run.iter().map(|r| r.name()).collect();
+ /// names.sort_unstable();
+ /// assert_eq!(names, ["test", "test_fixture", "test_fixture"]);
+ /// ```
+ pub fn name(&self) -> &str {
+ self.name.as_str()
+ }
+
+ /// The `kind` of test
+ ///
+ /// Used to distinguish between integration tests (`test`) and unit tests (`bin`, `lib`).
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// let run: Result<Vec<_>, _> = escargot::CargoBuild::new()
+ /// .tests()
+ /// .current_release()
+ /// .current_target()
+ /// .manifest_path("tests/fixtures/test/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .run_tests()
+ /// .unwrap()
+ /// .collect();
+ /// let run = run.unwrap();
+ /// let mut kinds: Vec<_> = run.iter().map(|r| r.kind()).collect();
+ /// kinds.sort_unstable();
+ /// assert_eq!(kinds, ["bin", "lib", "test"]);
+ /// ```
+ pub fn kind(&self) -> &str {
+ self.kind.as_str()
+ }
+
+ /// Path to the specified binary.
+ ///
+ /// This is to support alternative ways of launching the binary besides [`Command`].
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// extern crate escargot;
+ /// extern crate assert_fs;
+ ///
+ /// let temp = assert_fs::TempDir::new().unwrap();
+ /// let run: Vec<_> = escargot::CargoBuild::new()
+ /// .tests()
+ /// .current_release()
+ /// .current_target()
+ /// .manifest_path("tests/fixtures/test/Cargo.toml")
+ /// .target_dir(temp.path())
+ /// .run_tests()
+ /// .unwrap()
+ /// .collect();
+ /// assert_eq!(run.len(), 3);
+ /// ```
+ ///
+ /// [`Command`]: std::process::Command
+ pub fn path(&self) -> &path::Path {
+ &self.bin_path
+ }
+
+ /// Run the build artifact.
+ pub fn command(&self) -> process::Command {
+ let mut cmd = process::Command::new(self.path());
+ cmd.arg("-Z").arg("unstable-options").arg("--format=json");
+ cmd
+ }
+
+ /// Run the configured test, returning test events.
+ pub fn exec(&self) -> CargoResult<CommandMessages> {
+ CommandMessages::with_command(self.command())
+ }
+}
+
+fn extract_bin(msg: &format::Message<'_>) -> Option<CargoTest> {
+ match msg {
+ format::Message::CompilerArtifact(art) => {
+ if art.profile.test {
+ let bin_path = art
+ .filenames
+ .get(0)
+ .expect("files must exist")
+ .to_path_buf();
+ let kind = art
+ .target
+ .kind
+ .get(0)
+ .expect("kind must exist")
+ .as_ref()
+ .to_owned();
+ let name = art.target.name.as_ref().to_owned();
+ Some(CargoTest {
+ bin_path,
+ kind,
+ name,
+ })
+ } else {
+ None
+ }
+ }
+ _ => None,
+ }
+}
+
+fn transpose<T, E>(r: Result<Option<T>, E>) -> Option<Result<T, E>> {
+ match r {
+ Ok(Some(x)) => Some(Ok(x)),
+ Ok(None) => None,
+ Err(e) => Some(Err(e)),
+ }
+}
+
+fn extract_binary_paths(
+ msgs: CommandMessages,
+) -> impl Iterator<Item = Result<CargoTest, CargoError>> {
+ msgs.filter_map(move |m| {
+ let m = m.and_then(|m| {
+ let m = m.decode()?;
+ format::log_message(&m);
+ let p = extract_bin(&m);
+ Ok(p)
+ });
+ transpose(m)
+ })
+}