From ef24de24a82fe681581cc130f342363c47c0969a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 7 Jun 2024 07:48:48 +0200 Subject: Merging upstream version 1.75.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/clap-cargo/src/features.rs | 168 +++++++++++++++ vendor/clap-cargo/src/lib.rs | 52 +++++ vendor/clap-cargo/src/manifest.rs | 67 ++++++ vendor/clap-cargo/src/style.rs | 23 +++ vendor/clap-cargo/src/workspace.rs | 404 +++++++++++++++++++++++++++++++++++++ 5 files changed, 714 insertions(+) create mode 100644 vendor/clap-cargo/src/features.rs create mode 100644 vendor/clap-cargo/src/lib.rs create mode 100644 vendor/clap-cargo/src/manifest.rs create mode 100644 vendor/clap-cargo/src/style.rs create mode 100644 vendor/clap-cargo/src/workspace.rs (limited to 'vendor/clap-cargo/src') diff --git a/vendor/clap-cargo/src/features.rs b/vendor/clap-cargo/src/features.rs new file mode 100644 index 000000000..21a7513d2 --- /dev/null +++ b/vendor/clap-cargo/src/features.rs @@ -0,0 +1,168 @@ +//! Cargo Feature Flags. + +#[derive(Default, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "clap", derive(clap::Args))] +#[non_exhaustive] +pub struct Features { + #[cfg_attr(feature = "clap", arg(long))] + /// Activate all available features + pub all_features: bool, + #[cfg_attr(feature = "clap", arg(long))] + /// Do not activate the `default` feature + pub no_default_features: bool, + #[cfg_attr(feature = "clap", arg(short = 'F', long, value_delimiter = ' '))] + /// Space-separated list of features to activate + pub features: Vec, +} + +#[cfg(feature = "cargo_metadata")] +impl Features { + /// Forward these flags to the `cargo_metadata` crate. + /// + /// Note: Requires the features `cargo_metadata`. + pub fn forward_metadata<'m>( + &self, + meta: &'m mut cargo_metadata::MetadataCommand, + ) -> &'m mut cargo_metadata::MetadataCommand { + if self.all_features { + meta.features(cargo_metadata::CargoOpt::AllFeatures); + } + if self.no_default_features { + meta.features(cargo_metadata::CargoOpt::NoDefaultFeatures); + } + if !self.features.is_empty() { + meta.features(cargo_metadata::CargoOpt::SomeFeatures( + self.features.clone(), + )); + } + meta + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + #[cfg(feature = "clap")] + fn verify_app() { + #[derive(Debug, clap::Parser)] + struct Cli { + #[command(flatten)] + features: Features, + } + + use clap::CommandFactory; + Cli::command().debug_assert() + } + + #[test] + #[cfg(feature = "clap")] + fn parse_multiple_occurrences() { + use clap::Parser; + + #[derive(PartialEq, Eq, Debug, Parser)] + struct Args { + positional: Option, + #[command(flatten)] + features: Features, + } + + assert_eq!( + Args { + positional: None, + features: Features { + all_features: false, + no_default_features: false, + features: vec![] + } + }, + Args::parse_from(["test"]) + ); + assert_eq!( + Args { + positional: Some("foo".to_owned()), + features: Features { + all_features: false, + no_default_features: false, + features: vec![] + } + }, + Args::parse_from(["test", "foo"]) + ); + assert_eq!( + Args { + positional: None, + features: Features { + all_features: false, + no_default_features: false, + features: vec!["foo".to_owned()] + } + }, + Args::parse_from(["test", "--features", "foo"]) + ); + assert_eq!( + Args { + positional: None, + features: Features { + all_features: false, + no_default_features: false, + features: vec!["foo".to_owned(), "bar".to_owned()] + } + }, + Args::parse_from(["test", "--features", "foo bar"]) + ); + assert_eq!( + Args { + positional: Some("baz".to_owned()), + features: Features { + all_features: false, + no_default_features: false, + features: vec!["foo".to_owned(), "bar".to_owned()] + } + }, + Args::parse_from(["test", "--features", "foo bar", "baz"]) + ); + assert_eq!( + Args { + positional: Some("baz".to_owned()), + features: Features { + all_features: false, + no_default_features: false, + features: vec!["foo".to_owned(), "bar".to_owned()] + } + }, + Args::parse_from(["test", "--features", "foo", "--features", "bar", "baz"]) + ); + } + + #[cfg(feature = "cargo_metadata")] + #[test] + fn features_all() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/simple/Cargo.toml"); + + let features = Features { + all_features: true, + ..Default::default() + }; + features.forward_metadata(&mut metadata); + metadata.exec().unwrap(); + // TODO verify we forwarded correctly. + } + + #[cfg(feature = "cargo_metadata")] + #[test] + fn features_none() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/simple/Cargo.toml"); + + let features = Features { + no_default_features: true, + ..Default::default() + }; + features.forward_metadata(&mut metadata); + metadata.exec().unwrap(); + // TODO verify we forwarded correctly. + } +} diff --git a/vendor/clap-cargo/src/lib.rs b/vendor/clap-cargo/src/lib.rs new file mode 100644 index 000000000..e7acd5774 --- /dev/null +++ b/vendor/clap-cargo/src/lib.rs @@ -0,0 +1,52 @@ +//! **clap-cargo**: Re-usable CLI flags for `cargo` plugins +//! +//! ## Install +//! +//! Add to your `Cargo.toml`: +//! +//! ```toml +//! [dependencies] +//! clap-cargo = "0.1" +//! ``` +//! +//! ## Examples +//! +//! ```rust +//! # #[cfg(feature = "clap")] { +//! // ... +//! #[derive(Debug, clap::Parser)] +//! struct Cli { +//! #[command(flatten)] +//! manifest: clap_cargo::Manifest, +//! #[command(flatten)] +//! workspace: clap_cargo::Workspace, +//! #[command(flatten)] +//! features: clap_cargo::Features, +//! } +//! # } +//! ``` +//! +//! ## Relevant crates +//! +//! Other crates that might be useful for cargo plugins: +//! * [escargot][escargot] for wrapping `cargo-build`, `carg-run`, `cargo-test`, etc. +//! * [cargo_metadata][cargo_metadata] for getting crate information. +//! * [clap-verbosity][clap-verbosity] for adding logging to your CLI. +//! +//! [escargot]: https://crates.io/crates/escargot +//! [cargo_metadata]: https://crates.io/crates/cargo_metadata +//! [clap-verbosity]: https://crates.io/crates/clap-verbosity-flag + +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![warn(missing_debug_implementations)] +#![warn(unused_extern_crates)] + +mod features; +mod manifest; +mod workspace; + +pub mod style; + +pub use features::*; +pub use manifest::*; +pub use workspace::*; diff --git a/vendor/clap-cargo/src/manifest.rs b/vendor/clap-cargo/src/manifest.rs new file mode 100644 index 000000000..c7d4764ff --- /dev/null +++ b/vendor/clap-cargo/src/manifest.rs @@ -0,0 +1,67 @@ +//! Cargo flag for selecting the relevant crate. + +use std::path; + +#[derive(Default, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "clap", derive(clap::Args))] +#[non_exhaustive] +pub struct Manifest { + #[cfg_attr(feature = "clap", arg(long, name = "PATH"))] + /// Path to Cargo.toml + pub manifest_path: Option, +} + +#[cfg(feature = "cargo_metadata")] +impl Manifest { + /// Create a `cargo_metadata::MetadataCommand` + /// + /// Note: Requires the features `cargo_metadata`. + pub fn metadata(&self) -> cargo_metadata::MetadataCommand { + let mut c = cargo_metadata::MetadataCommand::new(); + if let Some(ref manifest_path) = self.manifest_path { + c.manifest_path(manifest_path); + } + c + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + #[cfg(feature = "clap")] + fn verify_app() { + #[derive(Debug, clap::Parser)] + struct Cli { + #[command(flatten)] + manifest: Manifest, + } + + use clap::CommandFactory; + Cli::command().debug_assert() + } + + #[cfg(feature = "cargo_metadata")] + #[test] + fn metadata_with_path() { + let manifest = Manifest { + manifest_path: Some(path::PathBuf::from("tests/fixtures/simple/Cargo.toml")), + }; + let metadata = manifest.metadata(); + metadata.exec().unwrap(); + // TODO verify we forwarded correctly. + } + + #[cfg(feature = "cargo_metadata")] + #[test] + fn metadata_without_path() { + let cwd = path::PathBuf::from("tests/fixtures/simple"); + let manifest = Manifest { + manifest_path: None, + }; + let mut metadata = manifest.metadata(); + metadata.current_dir(cwd).exec().unwrap(); + // TODO verify we forwarded correctly. + } +} diff --git a/vendor/clap-cargo/src/style.rs b/vendor/clap-cargo/src/style.rs new file mode 100644 index 000000000..4ff33d43d --- /dev/null +++ b/vendor/clap-cargo/src/style.rs @@ -0,0 +1,23 @@ +use anstyle::*; + +pub const NOP: Style = Style::new(); +pub const HEADER: Style = AnsiColor::Green.on_default().effects(Effects::BOLD); +pub const USAGE: Style = AnsiColor::Green.on_default().effects(Effects::BOLD); +pub const LITERAL: Style = AnsiColor::Cyan.on_default().effects(Effects::BOLD); +pub const PLACEHOLDER: Style = AnsiColor::Cyan.on_default(); +pub const ERROR: Style = AnsiColor::Red.on_default().effects(Effects::BOLD); +pub const WARN: Style = AnsiColor::Yellow.on_default().effects(Effects::BOLD); +pub const NOTE: Style = AnsiColor::Cyan.on_default().effects(Effects::BOLD); +pub const GOOD: Style = AnsiColor::Green.on_default().effects(Effects::BOLD); +pub const VALID: Style = AnsiColor::Cyan.on_default().effects(Effects::BOLD); +pub const INVALID: Style = AnsiColor::Yellow.on_default().effects(Effects::BOLD); + +#[cfg(feature = "clap")] +pub const CLAP_STYLING: clap::builder::styling::Styles = clap::builder::styling::Styles::styled() + .header(HEADER) + .usage(USAGE) + .literal(LITERAL) + .placeholder(PLACEHOLDER) + .error(ERROR) + .valid(VALID) + .invalid(INVALID); diff --git a/vendor/clap-cargo/src/workspace.rs b/vendor/clap-cargo/src/workspace.rs new file mode 100644 index 000000000..09e6e93a9 --- /dev/null +++ b/vendor/clap-cargo/src/workspace.rs @@ -0,0 +1,404 @@ +//! Cargo flags for selecting crates in a workspace. + +#[derive(Default, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "clap", derive(clap::Args))] +#[non_exhaustive] +pub struct Workspace { + #[cfg_attr(feature = "clap", arg(short, long, value_name = "SPEC"))] + /// Package to process (see `cargo help pkgid`) + pub package: Vec, + #[cfg_attr(feature = "clap", arg(long))] + /// Process all packages in the workspace + pub workspace: bool, + #[cfg_attr( + feature = "clap", + arg(long, hide_short_help(true), hide_long_help(true)) + )] + /// Process all packages in the workspace + pub all: bool, + #[cfg_attr(feature = "clap", arg(long, value_name = "SPEC"))] + /// Exclude packages from being processed + pub exclude: Vec, +} + +#[cfg(feature = "cargo_metadata")] +impl Workspace { + /// Partition workspace members into those selected and those excluded. + /// + /// Notes: + /// - Requires the features `cargo_metadata`. + /// - Requires not calling `MetadataCommand::no_deps` + pub fn partition_packages<'m>( + &self, + meta: &'m cargo_metadata::Metadata, + ) -> ( + Vec<&'m cargo_metadata::Package>, + Vec<&'m cargo_metadata::Package>, + ) { + let selection = + Packages::from_flags(self.workspace || self.all, &self.exclude, &self.package); + let workspace_members: std::collections::HashSet<_> = + meta.workspace_members.iter().collect(); + let base_ids: std::collections::HashSet<_> = match selection { + Packages::Default => { + // Deviating from cargo because Metadata doesn't have default members + let resolve = meta.resolve.as_ref().expect("no-deps is unsupported"); + match &resolve.root { + Some(root) => { + let mut base_ids = std::collections::HashSet::new(); + base_ids.insert(root); + base_ids + } + None => workspace_members, + } + } + Packages::All => workspace_members, + Packages::OptOut(_) => workspace_members, // Deviating from cargo by only checking workspace members + Packages::Packages(patterns) => { + meta.packages + .iter() + // Deviating from cargo by not supporting patterns + // Deviating from cargo by only checking workspace members + .filter(|p| workspace_members.contains(&p.id) && patterns.contains(&p.name)) + .map(|p| &p.id) + .collect() + } + }; + + meta.packages + .iter() + // Deviating from cargo by not supporting patterns + .partition(|p| base_ids.contains(&p.id) && !self.exclude.contains(&p.name)) + } +} + +// See cargo's src/cargo/ops/cargo_compile.rs +#[derive(Clone, PartialEq, Eq, Debug)] +#[cfg(feature = "cargo_metadata")] +#[allow(clippy::enum_variant_names)] +enum Packages<'p> { + Default, + All, + OptOut(&'p [String]), + Packages(&'p [String]), +} + +#[cfg(feature = "cargo_metadata")] +impl<'p> Packages<'p> { + pub fn from_flags(all: bool, exclude: &'p [String], package: &'p [String]) -> Self { + match (all, exclude.len(), package.len()) { + (false, 0, 0) => Packages::Default, + (false, 0, _) => Packages::Packages(package), + (false, _, 0) => Packages::OptOut(exclude), // Deviating from cargo because we don't do error handling + (false, _, _) => Packages::Packages(package), // Deviating from cargo because we don't do error handling + (true, 0, _) => Packages::All, + (true, _, _) => Packages::OptOut(exclude), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + #[cfg(feature = "clap")] + fn verify_app() { + #[derive(Debug, clap::Parser)] + struct Cli { + #[command(flatten)] + workspace: Workspace, + } + + use clap::CommandFactory; + Cli::command().debug_assert() + } + + #[test] + #[cfg(feature = "clap")] + fn parse_multiple_occurrences() { + use clap::Parser; + + #[derive(PartialEq, Eq, Debug, Parser)] + struct Args { + positional: Option, + #[command(flatten)] + workspace: Workspace, + } + + assert_eq!( + Args { + positional: None, + workspace: Workspace { + package: vec![], + workspace: false, + all: false, + exclude: vec![], + } + }, + Args::parse_from(["test"]) + ); + assert_eq!( + Args { + positional: Some("baz".to_owned()), + workspace: Workspace { + package: vec!["foo".to_owned(), "bar".to_owned()], + workspace: false, + all: false, + exclude: vec![], + } + }, + Args::parse_from(["test", "--package", "foo", "--package", "bar", "baz"]) + ); + assert_eq!( + Args { + positional: Some("baz".to_owned()), + workspace: Workspace { + package: vec![], + workspace: false, + all: false, + exclude: vec!["foo".to_owned(), "bar".to_owned()], + } + }, + Args::parse_from(["test", "--exclude", "foo", "--exclude", "bar", "baz"]) + ); + } + + #[cfg(feature = "cargo_metadata")] + #[cfg(test)] + mod partition_default { + use super::*; + + #[test] + fn single_crate() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/simple/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn mixed_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + + #[test] + fn mixed_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + + #[test] + fn pure_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 3); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn pure_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + } + + #[cfg(feature = "cargo_metadata")] + #[cfg(test)] + mod partition_all { + use super::*; + + #[test] + fn single_crate() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/simple/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + all: true, + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn mixed_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + all: true, + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 3); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn mixed_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + all: true, + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 3); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn pure_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + all: true, + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 3); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn pure_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + all: true, + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 3); + assert_eq!(excluded.len(), 0); + } + } + + #[cfg(feature = "cargo_metadata")] + #[cfg(test)] + mod partition_package { + use super::*; + + #[test] + fn single_crate() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/simple/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + package: vec!["simple".to_owned()], + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 0); + } + + #[test] + fn mixed_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + package: vec!["a".to_owned()], + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + + #[test] + fn mixed_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/mixed_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + package: vec!["a".to_owned()], + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + + #[test] + fn pure_ws_root() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + package: vec!["a".to_owned()], + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + + #[test] + fn pure_ws_leaf() { + let mut metadata = cargo_metadata::MetadataCommand::new(); + metadata.manifest_path("tests/fixtures/pure_ws/c/Cargo.toml"); + let metadata = metadata.exec().unwrap(); + + let workspace = Workspace { + package: vec!["a".to_owned()], + ..Default::default() + }; + let (included, excluded) = workspace.partition_packages(&metadata); + assert_eq!(included.len(), 1); + assert_eq!(excluded.len(), 2); + } + } +} -- cgit v1.2.3