From 1cd643d7288ac3557663370a210d13b82a876ee6 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 17 Oct 2020 09:16:34 +0900 Subject: [PATCH] Add --exclude-features as an alias of --skip * Add `--exclude-features` option. This is an alias of `--skip` option. * Rename `--skip-no-default-features` flag to `--exclude-no-default-features`. The old name can be used as an alias, but is deprecated. * Rename `--skip-all-features` flag to `--exclude-all-features`. --- CHANGELOG.md | 7 +++- README.md | 10 +---- src/cli.rs | 93 ++++++++++++++++++++++++++++++-------------- src/package.rs | 26 +++++++------ tests/long-help.txt | 15 ++++--- tests/short-help.txt | 45 ++++++++++----------- tests/test.rs | 83 ++++++++++++++++++++++++++++++--------- 7 files changed, 181 insertions(+), 98 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 802b3932..ac8965b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,12 @@ This project adheres to [Semantic Versioning](https://semver.org). * Treat `--all-features` flag as one of feature combinations. See [#42][42] for details. -* Add `--skip-all-features` flag. See [#42][42] for details. +* Add `--exclude-all-features` flag. See [#42][42] for details. + +* Add `--exclude-features` option. This is an alias of `--skip` option. + +* Rename `--skip-no-default-features` flag to `--exclude-no-default-features`. + The old name can be used as an alias, but is deprecated. * Fix an issue where using `--features` with `--each-feature` or `--feature-powerset` together would result in the same feature combination being performed multiple times. diff --git a/README.md b/README.md index b7f6e845..70faf1ea 100644 --- a/README.md +++ b/README.md @@ -96,15 +96,9 @@ The following flags can be used with `--each-feature` and `--feature-powerset`. Use optional dependencies as features. -* **`--skip`** +* **`--exclude-features`**, **`--skip`** - Space-separated list of features to skip. - - To skip run of default feature, using value `--skip default`. - -* **`--skip-no-default-features`** - - Skip run of just `--no-default-features` flag. + Space-separated list of features to exclude. * **`--depth`** diff --git a/src/cli.rs b/src/cli.rs index 9e92e708..8983f043 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -5,7 +5,7 @@ use termcolor::ColorChoice; use crate::{ProcessBuilder, Result}; fn print_version() { - println!("{0} {1}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"),) + println!("{0} {1}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")) } // (short flag, long flag, short descriptions, additional descriptions) @@ -28,14 +28,15 @@ const HELP: &[(&str, &str, &str, &[&str])] = &[ "If DEPS are not specified, all optional dependencies are considered as features.", "This flag can only be used together with either --each-feature flag or --feature-powerset flag.", ]), - ("", "--skip ...", "Space-separated list of features to skip", &[ - "To skip run of default feature, using value `--skip default`.", + ("", "--skip ...", "Alias for --exclude-features", &[]), + ("", "--exclude-features ...", "Space-separated list of features to exclude", &[ + "To exclude run of default feature, using value `--exclude-features default`.", "This flag can only be used together with either --each-feature flag or --feature-powerset flag.", ]), - ("", "--skip-no-default-features", "Skip run of just --no-default-features flag", &[ + ("", "--exclude-no-default-features", "Exclude run of just --no-default-features flag", &[ "This flag can only be used together with either --each-feature flag or --feature-powerset flag.", ]), - ("", "--skip-all-features", "Skip run of just --all-features flag", &[ + ("", "--exclude-all-features", "Exclude run of just --all-features flag", &[ "This flag can only be used together with either --each-feature flag or --feature-powerset flag.", ]), ( @@ -143,8 +144,8 @@ OPTIONS:", writeln!(f, "\n")?; } } else { - write!(f, "{:26} ", long)?; - write(f, 35, false, self.term_size, desc)?; + write!(f, "{:32} ", long)?; + write(f, 41, false, self.term_size, desc)?; writeln!(f)?; } } @@ -204,12 +205,12 @@ pub(crate) struct Args { // Note: These values are not always exactly the same as the input. // Error messages should not assume that these options have been specified. - /// --skip ... - pub(crate) skip: Vec, - /// --skip-no-default-features - pub(crate) skip_no_default_features: bool, - /// --skip-all-features - pub(crate) skip_all_features: bool, + /// --exclude-features ..., --skip ... + pub(crate) exclude_features: Vec, + /// --exclude-no-default-features, (--skip-no-default-features) + pub(crate) exclude_no_default_features: bool, + /// --exclude-all-features + pub(crate) exclude_all_features: bool, // flags that will be propagated to cargo /// --features ... @@ -276,7 +277,6 @@ pub(crate) fn args(coloring: &mut Option) -> Result> { let mut package = Vec::new(); let mut exclude = Vec::new(); let mut features = Vec::new(); - let mut skip = Vec::new(); let mut optional_deps = None; let mut workspace = None; @@ -286,11 +286,14 @@ pub(crate) fn args(coloring: &mut Option) -> Result> { let mut feature_powerset = false; let mut ignore_private = false; let mut ignore_unknown_features = false; - let mut skip_no_default_features = false; - let mut skip_all_features = false; let mut clean_per_run = false; let mut depth = None; + let mut exclude_features = Vec::new(); + let mut exclude_no_default_features = false; + let mut exclude_all_features = false; + let mut skip_no_default_features = false; + let mut verbose = false; let mut no_default_features = false; let mut all_features = false; @@ -397,7 +400,14 @@ pub(crate) fn args(coloring: &mut Option) -> Result> { parse_multi_opt!(package, false, true, "-p", "--package ..."); parse_multi_opt!(exclude, false, true, "--exclude", "--exclude ..."); parse_multi_opt!(features, true, true, "--features", "--features ..."); - parse_multi_opt!(skip, true, true, "--skip", "--skip ..."); + parse_multi_opt!(exclude_features, true, true, "--skip", "--skip ..."); + parse_multi_opt!( + exclude_features, + true, + true, + "--exclude-features", + "--exclude-features ..." + ); if arg.starts_with("--optional-deps") { if optional_deps.is_some() { @@ -425,8 +435,24 @@ pub(crate) fn args(coloring: &mut Option) -> Result> { "--each-feature" => parse_flag!(each_feature), "--feature-powerset" => parse_flag!(feature_powerset), "--ignore-private" => parse_flag!(ignore_private), - "--skip-no-default-features" => parse_flag!(skip_no_default_features), - "--skip-all-features" => parse_flag!(skip_all_features), + "--exclude-no-default-features" => { + if exclude_no_default_features || skip_no_default_features { + return Err(multi_arg(&arg, subcommand.as_ref())); + } + exclude_no_default_features = true; + continue; + } + "--skip-no-default-features" => { + if exclude_no_default_features || skip_no_default_features { + return Err(multi_arg( + "--exclude-no-default-features", + subcommand.as_ref(), + )); + } + skip_no_default_features = true; + continue; + } + "--exclude-all-features" => parse_flag!(exclude_all_features), "--clean-per-run" => parse_flag!(clean_per_run), "--ignore-unknown-features" => parse_flag!(ignore_unknown_features), "--ignore-non-exist-features" => bail!( @@ -481,17 +507,17 @@ pub(crate) fn args(coloring: &mut Option) -> Result> { bail!( "--optional-deps can only be used together with either --each-feature or --feature-powerset" ); - } else if !skip.is_empty() { + } else if !exclude_features.is_empty() { bail!( - "--skip can only be used together with either --each-feature or --feature-powerset" + "--exclude-features (--skip) can only be used together with either --each-feature or --feature-powerset" ); - } else if skip_no_default_features { + } else if exclude_no_default_features || skip_no_default_features { bail!( - "--skip-no-default-features can only be used together with either --each-feature or --feature-powerset" + "--exclude-no-default-features can only be used together with either --each-feature or --feature-powerset" ); - } else if skip_all_features { + } else if exclude_all_features { bail!( - "--skip-all-features can only be used together with either --each-feature or --feature-powerset" + "--exclude-all-features can only be used together with either --each-feature or --feature-powerset" ); } } @@ -555,6 +581,13 @@ For more information try --help } } + if skip_no_default_features { + warn!( + color, + "--skip-no-default-features is deprecated, use --exclude-no-default-features flag instead" + ); + exclude_no_default_features = true; + } if no_dev_deps { info!( color, @@ -562,8 +595,8 @@ For more information try --help ) } - skip_no_default_features |= no_default_features; - skip.extend_from_slice(&features); + exclude_no_default_features |= no_default_features; + exclude_features.extend_from_slice(&features); Ok(Some(Args { leading_args: leading, @@ -588,9 +621,9 @@ For more information try --help no_default_features, verbose, - skip, - skip_no_default_features, - skip_all_features, + exclude_features, + exclude_no_default_features, + exclude_all_features, features, color, diff --git a/src/package.rs b/src/package.rs index c74a6a0d..f2f6bf8a 100644 --- a/src/package.rs +++ b/src/package.rs @@ -62,11 +62,13 @@ impl<'a> Kind<'a> { return Kind::Nomal { show_progress: false }; } - let features = - package.features.keys().filter(|f| *f != "default" && !args.skip.contains(f)); + let features = package + .features + .keys() + .filter(|f| *f != "default" && !args.exclude_features.contains(f)); let opt_deps = args.optional_deps.as_ref().map(|opt_deps| { package.dependencies.iter().filter_map(Dependency::as_feature).filter(move |f| { - !args.skip.contains(f) && (opt_deps.is_empty() || opt_deps.contains(f)) + !args.exclude_features.contains(f) && (opt_deps.is_empty() || opt_deps.contains(f)) }) }); @@ -82,9 +84,9 @@ impl<'a> Kind<'a> { Kind::Nomal { show_progress: true } } else { *total += features.len() - + (!args.skip.iter().any(|x| x == "default")) as usize - + (!args.skip_no_default_features) as usize - + (!args.skip_all_features) as usize; + + (!args.exclude_features.iter().any(|x| x == "default")) as usize + + (!args.exclude_no_default_features) as usize + + (!args.exclude_all_features) as usize; Kind::Each { features } } } else if args.feature_powerset { @@ -100,9 +102,9 @@ impl<'a> Kind<'a> { } else { // -1: the first element of a powerset is `[]` *total += features.len() - 1 - + (!args.skip.iter().any(|x| x == "default")) as usize - + (!args.skip_no_default_features) as usize - + (!args.skip_all_features) as usize; + + (!args.exclude_features.iter().any(|x| x == "default")) as usize + + (!args.exclude_no_default_features) as usize + + (!args.exclude_all_features) as usize; Kind::Powerset { features } } } else { @@ -129,7 +131,7 @@ pub(crate) fn exec( let mut line = line.clone(); - if !args.skip.iter().any(|x| x == "default") { + if !args.exclude_features.iter().any(|x| x == "default") { // run with default features exec_cargo(args, package, &mut line, info, true)?; } @@ -138,7 +140,7 @@ pub(crate) fn exec( line.arg("--no-default-features"); } - if !args.skip_no_default_features { + if !args.exclude_no_default_features { // run with no default features if the package has other features // // `default` is not skipped because `cfg(feature = "default")` is work @@ -162,7 +164,7 @@ pub(crate) fn exec( _ => unreachable!(), } - if !args.skip_all_features { + if !args.exclude_all_features { // run with all features line.arg("--all-features"); exec_cargo(args, package, &mut line, info, true)?; diff --git a/tests/long-help.txt b/tests/long-help.txt index a284e4c1..d02bcb33 100644 --- a/tests/long-help.txt +++ b/tests/long-help.txt @@ -45,19 +45,22 @@ OPTIONS: This flag can only be used together with either --each-feature flag or --feature-powerset flag. --skip ... - Space-separated list of features to skip. + Alias for --exclude-features. - To skip run of default feature, using value `--skip default`. + --exclude-features ... + Space-separated list of features to exclude. + + To exclude run of default feature, using value `--exclude-features default`. This flag can only be used together with either --each-feature flag or --feature-powerset flag. - --skip-no-default-features - Skip run of just --no-default-features flag. + --exclude-no-default-features + Exclude run of just --no-default-features flag. This flag can only be used together with either --each-feature flag or --feature-powerset flag. - --skip-all-features - Skip run of just --all-features flag. + --exclude-all-features + Exclude run of just --all-features flag. This flag can only be used together with either --each-feature flag or --feature-powerset flag. diff --git a/tests/short-help.txt b/tests/short-help.txt index 13eae892..b2e180f9 100644 --- a/tests/short-help.txt +++ b/tests/short-help.txt @@ -7,28 +7,29 @@ USAGE: Use -h for short descriptions and --help for more details. OPTIONS: - -p, --package ... Package(s) to check - --all Alias for --workspace - --workspace Perform command for all packages in the workspace - --exclude ... Exclude packages from the check - --manifest-path Path to Cargo.toml - --features ... Space-separated list of features to activate - --each-feature Perform for each feature of the package - --feature-powerset Perform for the feature powerset of the package - --optional-deps [DEPS]... Use optional dependencies as features - --skip ... Space-separated list of features to skip - --skip-no-default-features Skip run of just --no-default-features flag - --skip-all-features Skip run of just --all-features flag - --depth Specify a max number of simultaneous feature flags of --feature-powerset - --no-dev-deps Perform without dev-dependencies - --remove-dev-deps Equivalent to --no-dev-deps flag except for does not restore the original `Cargo.toml` after performed - --ignore-private Skip to perform on `publish = false` packages - --ignore-unknown-features Skip passing --features flag to `cargo` if that feature does not exist in the package - --clean-per-run Remove artifacts for that package before running the command - -v, --verbose Use verbose output - --color Coloring: auto, always, never - -h, --help Prints help information - -V, --version Prints version information + -p, --package ... Package(s) to check + --all Alias for --workspace + --workspace Perform command for all packages in the workspace + --exclude ... Exclude packages from the check + --manifest-path Path to Cargo.toml + --features ... Space-separated list of features to activate + --each-feature Perform for each feature of the package + --feature-powerset Perform for the feature powerset of the package + --optional-deps [DEPS]... Use optional dependencies as features + --skip ... Alias for --exclude-features + --exclude-features ... Space-separated list of features to exclude + --exclude-no-default-features Exclude run of just --no-default-features flag + --exclude-all-features Exclude run of just --all-features flag + --depth Specify a max number of simultaneous feature flags of --feature-powerset + --no-dev-deps Perform without dev-dependencies + --remove-dev-deps Equivalent to --no-dev-deps flag except for does not restore the original `Cargo.toml` after performed + --ignore-private Skip to perform on `publish = false` packages + --ignore-unknown-features Skip passing --features flag to `cargo` if that feature does not exist in the package + --clean-per-run Remove artifacts for that package before running the command + -v, --verbose Use verbose output + --color Coloring: auto, always, never + -h, --help Prints help information + -V, --version Prints version information Some common cargo commands are (see all commands with --list): build Compile the current package diff --git a/tests/test.rs b/tests/test.rs index bf492e15..98c7c4c4 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -112,7 +112,7 @@ impl Output { #[test] fn multi_arg() { - // --package, -p, --exclude, --features, --skip, and --verbose are allowed. + // --package, -p, --exclude, --features, --exclude-features, and --verbose are allowed. for flag in &[ "--examples", @@ -655,22 +655,22 @@ fn depth_failure() { } #[test] -fn skip_failure() { +fn exclude_features_failure() { cargo_hack() - .args(&["check", "--skip", "a"]) + .args(&["check", "--exclude-features", "a"]) .current_dir(test_dir("tests/fixtures/real")) .output() .unwrap() .assert_failure() .assert_stderr_contains( - "--skip can only be used together with either --each-feature or --feature-powerset", + "--exclude-features (--skip) can only be used together with either --each-feature or --feature-powerset", ); } #[test] fn each_feature_skip_success() { cargo_hack() - .args(&["check", "--each-feature", "--skip", "a"]) + .args(&["check", "--each-feature", "--exclude-features", "a"]) .current_dir(test_dir("tests/fixtures/real")) .output() .unwrap() @@ -687,12 +687,46 @@ fn each_feature_skip_success() { "running `cargo check --no-default-features --all-features` on real (5/5)", ) .assert_stderr_not_contains("--features a"); + + cargo_hack() + .args(&["check", "--each-feature", "--exclude-features", "a b"]) + .current_dir(test_dir("tests/fixtures/real")) + .output() + .unwrap() + .assert_success() + .assert_stderr_contains("running `cargo check` on real (1/4)") + .assert_stderr_contains("running `cargo check --no-default-features` on real (2/4)") + .assert_stderr_contains( + "running `cargo check --no-default-features --features c` on real (3/4)", + ) + .assert_stderr_contains( + "running `cargo check --no-default-features --all-features` on real (4/4)", + ) + .assert_stderr_not_contains("--features a") + .assert_stderr_not_contains("--features b"); + + cargo_hack() + .args(&["check", "--each-feature", "--exclude-features", "a", "--exclude-features", "b"]) + .current_dir(test_dir("tests/fixtures/real")) + .output() + .unwrap() + .assert_success() + .assert_stderr_contains("running `cargo check` on real (1/4)") + .assert_stderr_contains("running `cargo check --no-default-features` on real (2/4)") + .assert_stderr_contains( + "running `cargo check --no-default-features --features c` on real (3/4)", + ) + .assert_stderr_contains( + "running `cargo check --no-default-features --all-features` on real (4/4)", + ) + .assert_stderr_not_contains("--features a") + .assert_stderr_not_contains("--features b"); } #[test] fn powerset_skip_success() { cargo_hack() - .args(&["check", "--feature-powerset", "--skip", "a"]) + .args(&["check", "--feature-powerset", "--exclude-features", "a"]) .current_dir(test_dir("tests/fixtures/real")) .output() .unwrap() @@ -718,9 +752,9 @@ fn powerset_skip_success() { } #[test] -fn skip_default() { +fn exclude_features_default() { cargo_hack() - .args(&["check", "--each-feature", "--skip", "default"]) + .args(&["check", "--each-feature", "--exclude-features", "default"]) .current_dir(test_dir("tests/fixtures/real")) .output() .unwrap() @@ -742,9 +776,9 @@ fn skip_default() { } #[test] -fn skip_no_default_features() { +fn exclude_no_default_features() { cargo_hack() - .args(&["check", "--each-feature", "--skip-no-default-features"]) + .args(&["check", "--each-feature", "--exclude-no-default-features"]) .current_dir(test_dir("tests/fixtures/real")) .output() .unwrap() @@ -763,25 +797,36 @@ fn skip_no_default_features() { .assert_stderr_contains( "running `cargo check --no-default-features --all-features` on real (5/5)", ); + + // --skip-no-default-features is a deprecated alias of --exclude-no-default-features + cargo_hack() + .args(&["check", "--each-feature", "--skip-no-default-features"]) + .current_dir(test_dir("tests/fixtures/virtual")) + .output() + .unwrap() + .assert_success() + .assert_stderr_contains( + "--skip-no-default-features is deprecated, use --exclude-no-default-features flag instead", + ); } #[test] -fn skip_no_default_features_failure() { +fn exclude_no_default_features_failure() { cargo_hack() - .args(&["check", "--skip-no-default-features"]) + .args(&["check", "--exclude-no-default-features"]) .current_dir(test_dir("tests/fixtures/real")) .output() .unwrap() .assert_failure() .assert_stderr_contains( - "--skip-no-default-features can only be used together with either --each-feature or --feature-powerset", + "--exclude-no-default-features can only be used together with either --each-feature or --feature-powerset", ); } #[test] -fn skip_all_features() { +fn exclude_all_features() { cargo_hack() - .args(&["check", "--each-feature", "--skip-all-features"]) + .args(&["check", "--each-feature", "--exclude-all-features"]) .current_dir(test_dir("tests/fixtures/real")) .output() .unwrap() @@ -803,15 +848,15 @@ fn skip_all_features() { } #[test] -fn skip_all_features_failure() { +fn exclude_all_features_failure() { cargo_hack() - .args(&["check", "--skip-all-features"]) + .args(&["check", "--exclude-all-features"]) .current_dir(test_dir("tests/fixtures/real")) .output() .unwrap() .assert_failure() .assert_stderr_contains( - "--skip-all-features can only be used together with either --each-feature or --feature-powerset", + "--exclude-all-features can only be used together with either --each-feature or --feature-powerset", ); } @@ -1056,7 +1101,7 @@ fn optional_deps_failure() { #[test] fn skip_optional_deps() { cargo_hack() - .args(&["check", "--each-feature", "--optional-deps", "--skip", "real"]) + .args(&["check", "--each-feature", "--optional-deps", "--exclude-features", "real"]) .current_dir(test_dir("tests/fixtures/optional_deps")) .output() .unwrap()