diff --git a/src/lib.rs b/src/lib.rs index 9cd072b51..89fb65583 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,7 @@ mod develop; mod metadata; mod module_writer; mod new_project; +mod polyfill; mod project_layout; mod pyproject_toml; mod python_interpreter; diff --git a/src/polyfill.rs b/src/polyfill.rs new file mode 100644 index 000000000..ace8475d6 --- /dev/null +++ b/src/polyfill.rs @@ -0,0 +1,26 @@ +use cargo_metadata::{Metadata, MetadataCommand}; +use std::process::Stdio; + +pub trait MetadataCommandExt { + /// Runs configured `cargo metadata` and returns parsed `Metadata`. + /// Inherits stderr from parent process. + fn exec_inherit_stderr(&self) -> Result; +} + +impl MetadataCommandExt for MetadataCommand { + fn exec_inherit_stderr(&self) -> Result { + let mut command = self.cargo_command(); + command.stderr(Stdio::inherit()); + let output = command.output()?; + if !output.status.success() { + return Err(cargo_metadata::Error::CargoMetadata { + stderr: String::from_utf8(output.stderr)?, + }); + } + let stdout = std::str::from_utf8(&output.stdout)? + .lines() + .find(|line| line.starts_with('{')) + .ok_or(cargo_metadata::Error::NoJson)?; + Self::parse(stdout) + } +} diff --git a/src/project_layout.rs b/src/project_layout.rs index 1d64328fa..50f52d851 100644 --- a/src/project_layout.rs +++ b/src/project_layout.rs @@ -1,4 +1,5 @@ use crate::build_options::{extract_cargo_metadata_args, CargoOptions}; +use crate::polyfill::MetadataCommandExt; use crate::{CargoToml, Metadata21, PyProjectToml}; use anyhow::{bail, format_err, Context, Result}; use cargo_metadata::{Metadata, MetadataCommand}; @@ -277,7 +278,7 @@ impl ProjectResolver { let result = MetadataCommand::new() .manifest_path(manifest_path) .other_options(cargo_metadata_extra_args) - .exec(); + .exec_inherit_stderr(); let cargo_metadata = match result { Ok(cargo_metadata) => cargo_metadata, diff --git a/src/source_distribution.rs b/src/source_distribution.rs index 9ee797152..909d1d27e 100644 --- a/src/source_distribution.rs +++ b/src/source_distribution.rs @@ -1,4 +1,5 @@ use crate::module_writer::{add_data, ModuleWriter}; +use crate::polyfill::MetadataCommandExt; use crate::{BuildContext, PyProjectToml, SDistWriter}; use anyhow::{bail, Context, Result}; use cargo_metadata::{Metadata, MetadataCommand}; @@ -442,7 +443,7 @@ pub fn source_distribution( .manifest_path(path_dep) // We don't need to resolve the dependency graph .no_deps() - .exec() + .exec_inherit_stderr() .with_context(|| { format!( "Cargo metadata failed for {} at '{}'", diff --git a/tests/common/errors.rs b/tests/common/errors.rs index 97896c6fd..d1d095492 100644 --- a/tests/common/errors.rs +++ b/tests/common/errors.rs @@ -85,11 +85,7 @@ pub fn locked_doesnt_build_without_cargo_lock() -> Result<()> { .source() .ok_or_else(|| format_err!("{}", err))? .to_string(); - // Sometimes the first message is "waiting for file lock on package cache", - // so we can only check if the lock file is in the message somewhere - if !err_string.starts_with("`cargo metadata` exited with an error:") - || !err_string.contains("lock file") - { + if !err_string.starts_with("`cargo metadata` exited with an error:") { bail!("{:?}", err_string); } } else {