diff options
Diffstat (limited to 'vendor/cargo_metadata/src/lib.rs')
-rw-r--r-- | vendor/cargo_metadata/src/lib.rs | 154 |
1 files changed, 141 insertions, 13 deletions
diff --git a/vendor/cargo_metadata/src/lib.rs b/vendor/cargo_metadata/src/lib.rs index a250aa176..27c72da0d 100644 --- a/vendor/cargo_metadata/src/lib.rs +++ b/vendor/cargo_metadata/src/lib.rs @@ -83,9 +83,11 @@ use camino::Utf8PathBuf; use derive_builder::Builder; use std::collections::HashMap; use std::env; +use std::ffi::OsString; use std::fmt; +use std::hash::Hash; use std::path::PathBuf; -use std::process::Command; +use std::process::{Command, Stdio}; use std::str::from_utf8; pub use camino; @@ -154,10 +156,22 @@ pub struct Metadata { } impl Metadata { - /// Get the root package of this metadata instance. + /// Get the workspace's root package of this metadata instance. pub fn root_package(&self) -> Option<&Package> { - let root = self.resolve.as_ref()?.root.as_ref()?; - self.packages.iter().find(|pkg| &pkg.id == root) + match &self.resolve { + Some(resolve) => { + // if dependencies are resolved, use Cargo's answer + let root = resolve.root.as_ref()?; + self.packages.iter().find(|pkg| &pkg.id == root) + } + None => { + // if dependencies aren't resolved, check for a root package manually + let root_manifest_path = self.workspace_root.join("Cargo.toml"); + self.packages + .iter() + .find(|pkg| pkg.manifest_path == root_manifest_path) + } + } } /// Get the workspace packages. @@ -374,9 +388,12 @@ impl Package { /// Full path to the readme file if one is present in the manifest pub fn readme(&self) -> Option<Utf8PathBuf> { - self.readme - .as_ref() - .map(|file| self.manifest_path.join(file)) + self.readme.as_ref().map(|file| { + self.manifest_path + .parent() + .unwrap_or(&self.manifest_path) + .join(file) + }) } } @@ -409,7 +426,7 @@ impl std::fmt::Display for Source { pub struct Target { /// Name as given in the `Cargo.toml` or generated from the file name pub name: String, - /// Kind of target ("bin", "example", "test", "bench", "lib") + /// Kind of target ("bin", "example", "test", "bench", "lib", "custom-build") pub kind: Vec<String>, /// 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` @@ -450,9 +467,47 @@ pub struct Target { pub doc: bool, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +impl Target { + fn is_kind(&self, name: &str) -> bool { + self.kind.iter().any(|kind| kind == name) + } + + /// Return true if this target is of kind "lib". + pub fn is_lib(&self) -> bool { + self.is_kind("lib") + } + + /// Return true if this target is of kind "bin". + pub fn is_bin(&self) -> bool { + self.is_kind("bin") + } + + /// Return true if this target is of kind "example". + pub fn is_example(&self) -> bool { + self.is_kind("example") + } + + /// Return true if this target is of kind "test". + pub fn is_test(&self) -> bool { + self.is_kind("test") + } + + /// Return true if this target is of kind "bench". + pub fn is_bench(&self) -> bool { + self.is_kind("bench") + } + + /// Return true if this target is of kind "custom-build". + pub fn is_custom_build(&self) -> bool { + self.is_kind("custom-build") + } +} + +/// The Rust edition +/// +/// As of writing this comment rust editions 2024, 2027 and 2030 are not actually a thing yet but are parsed nonetheless for future proofing. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] #[non_exhaustive] -/// The rust edition pub enum Edition { /// Edition 2015 #[serde(rename = "2015")] @@ -463,6 +518,36 @@ pub enum Edition { /// Edition 2021 #[serde(rename = "2021")] E2021, + #[doc(hidden)] + #[serde(rename = "2024")] + _E2024, + #[doc(hidden)] + #[serde(rename = "2027")] + _E2027, + #[doc(hidden)] + #[serde(rename = "2030")] + _E2030, +} + +impl Edition { + /// Return the string representation of the edition + pub fn as_str(&self) -> &'static str { + use Edition::*; + match self { + E2015 => "2015", + E2018 => "2018", + E2021 => "2021", + _E2024 => "2024", + _E2027 => "2027", + _E2030 => "2030", + } + } +} + +impl fmt::Display for Edition { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } } impl Default for Edition { @@ -497,7 +582,7 @@ pub struct MetadataCommand { manifest_path: Option<PathBuf>, /// Current directory of the `cargo metadata` process. current_dir: Option<PathBuf>, - /// Output information only about the root package and don't fetch dependencies. + /// Output information only about workspace members and don't fetch dependencies. no_deps: bool, /// Collections of `CargoOpt::SomeFeatures(..)` features: Vec<String>, @@ -508,6 +593,11 @@ pub struct MetadataCommand { /// Arbitrary command line flags to pass to `cargo`. These will be added /// to the end of the command line invocation. other_options: Vec<String>, + /// Arbitrary environment variables to set when running `cargo`. These will be merged into + /// the calling environment, overriding any which clash. + env: HashMap<OsString, OsString>, + /// Show stderr + verbose: bool, } impl MetadataCommand { @@ -533,7 +623,7 @@ impl MetadataCommand { self.current_dir = Some(path.into()); self } - /// Output information only about the root package and don't fetch dependencies. + /// Output information only about workspace members and don't fetch dependencies. pub fn no_deps(&mut self) -> &mut MetadataCommand { self.no_deps = true; self @@ -603,6 +693,38 @@ impl MetadataCommand { self } + /// Arbitrary environment variables to set when running `cargo`. These will be merged into + /// the calling environment, overriding any which clash. + /// + /// Some examples of when you may want to use this: + /// 1. Setting cargo config values without needing a .cargo/config.toml file, e.g. to set + /// `CARGO_NET_GIT_FETCH_WITH_CLI=true` + /// 2. To specify a custom path to RUSTC if your rust toolchain components aren't laid out in + /// the way cargo expects by default. + /// + /// ```no_run + /// # use cargo_metadata::{CargoOpt, MetadataCommand}; + /// MetadataCommand::new() + /// .env("CARGO_NET_GIT_FETCH_WITH_CLI", "true") + /// .env("RUSTC", "/path/to/rustc") + /// // ... + /// # ; + /// ``` + pub fn env<K: Into<OsString>, V: Into<OsString>>( + &mut self, + key: K, + val: V, + ) -> &mut MetadataCommand { + self.env.insert(key.into(), val.into()); + self + } + + /// Set whether to show stderr + pub fn verbose(&mut self, verbose: bool) -> &mut MetadataCommand { + self.verbose = verbose; + self + } + /// Builds a command for `cargo metadata`. This is the first /// part of the work of `exec`. pub fn cargo_command(&self) -> Command { @@ -637,6 +759,8 @@ impl MetadataCommand { } cmd.args(&self.other_options); + cmd.envs(&self.env); + cmd } @@ -649,7 +773,11 @@ impl MetadataCommand { /// Runs configured `cargo metadata` and returns parsed `Metadata`. pub fn exec(&self) -> Result<Metadata> { - let output = self.cargo_command().output()?; + let mut command = self.cargo_command(); + if self.verbose { + command.stderr(Stdio::inherit()); + } + let output = command.output()?; if !output.status.success() { return Err(Error::CargoMetadata { stderr: String::from_utf8(output.stderr)?, |