diff --git a/src/bin/cargo/commands/package.rs b/src/bin/cargo/commands/package.rs index a1ef4793cea..1964e138cd9 100644 --- a/src/bin/cargo/commands/package.rs +++ b/src/bin/cargo/commands/package.rs @@ -26,6 +26,7 @@ pub fn cli() -> App { )) .arg_target_triple("Build for the target triple") .arg_target_dir() + .arg_features() .arg_manifest_path() .arg_jobs() } @@ -42,6 +43,9 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { allow_dirty: args.is_present("allow-dirty"), target: args.target(), jobs: args.jobs()?, + features: args._values_of("features"), + all_features: args.is_present("all-features"), + no_default_features: args.is_present("no-default-features"), }, )?; Ok(()) diff --git a/src/bin/cargo/commands/publish.rs b/src/bin/cargo/commands/publish.rs index 69845d033da..67b4ed2d2a8 100644 --- a/src/bin/cargo/commands/publish.rs +++ b/src/bin/cargo/commands/publish.rs @@ -18,6 +18,7 @@ pub fn cli() -> App { .arg_target_triple("Build for the target triple") .arg_target_dir() .arg_manifest_path() + .arg_features() .arg_jobs() .arg_dry_run("Perform all checks without uploading") .arg(opt("registry", "Registry to publish to").value_name("REGISTRY")) @@ -40,6 +41,9 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { jobs: args.jobs()?, dry_run: args.is_present("dry-run"), registry, + features: args._values_of("features"), + all_features: args.is_present("all-features"), + no_default_features: args.is_present("no-default-features"), }, )?; Ok(()) diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index c0200197a89..a8f92ad2fe3 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -26,6 +26,9 @@ pub struct PackageOpts<'cfg> { pub verify: bool, pub jobs: Option, pub target: Option, + pub features: Vec, + pub all_features: bool, + pub no_default_features: bool, } static VCS_INFO_FILE: &'static str = ".cargo_vcs_info.json"; @@ -447,9 +450,9 @@ fn run_verify(ws: &Workspace<'_>, tar: &FileLock, opts: &PackageOpts<'_>) -> Car &ops::CompileOptions { config, build_config: BuildConfig::new(config, opts.jobs, &opts.target, CompileMode::Build)?, - features: Vec::new(), - no_default_features: false, - all_features: false, + features: opts.features.clone(), + no_default_features: opts.no_default_features, + all_features: opts.all_features, spec: ops::Packages::Packages(Vec::new()), filter: ops::CompileFilter::Default { required_features_filterable: true, diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index 33699872469..04cf2886918 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -39,6 +39,9 @@ pub struct PublishOpts<'cfg> { pub target: Option, pub dry_run: bool, pub registry: Option, + pub features: Vec, + pub all_features: bool, + pub no_default_features: bool, } pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> { @@ -82,6 +85,9 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> { allow_dirty: opts.allow_dirty, target: opts.target.clone(), jobs: opts.jobs, + features: opts.features.clone(), + all_features: opts.all_features, + no_default_features: opts.no_default_features, }, )? .unwrap(); diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index f14eff20b6d..fd4fab5a462 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -1236,3 +1236,94 @@ To proceed despite this, pass the `--no-verify` flag.", p.cargo("package --no-verify").run(); } + +#[test] +fn package_with_select_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + + [features] + required = [] + optional = [] + "#, + ).file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ).build(); + + p.cargo("package --features required") + .masquerade_as_nightly_cargo() + .with_status(0) + .run(); +} + +#[test] +fn package_with_all_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + + [features] + required = [] + optional = [] + "#, + ).file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ).build(); + + p.cargo("package --all-features") + .masquerade_as_nightly_cargo() + .with_status(0) + .run(); +} + +#[test] +fn package_no_default_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + + [features] + default = ["required"] + required = [] + "#, + ).file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ).build(); + + p.cargo("package --no-default-features") + .masquerade_as_nightly_cargo() + .with_stderr_contains("error: This crate requires `required` feature!") + .with_status(101) + .run(); +} diff --git a/tests/testsuite/publish.rs b/tests/testsuite/publish.rs index ee6a6db73d5..2663b2657fb 100644 --- a/tests/testsuite/publish.rs +++ b/tests/testsuite/publish.rs @@ -787,3 +787,106 @@ fn block_publish_no_registry() { ) .run(); } + +#[test] +fn publish_with_select_features() { + publish::setup(); + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + + [features] + required = [] + optional = [] + "#, + ) + .file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ) + .build(); + + p.cargo("publish --features required --index") + .arg(publish::registry().to_string()) + .with_stderr_contains("[UPLOADING] foo v0.0.1 ([CWD])") + .run(); +} + +#[test] +fn publish_with_all_features() { + publish::setup(); + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + + [features] + required = [] + optional = [] + "#, + ) + .file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ) + .build(); + + p.cargo("publish --all-features --index") + .arg(publish::registry().to_string()) + .with_stderr_contains("[UPLOADING] foo v0.0.1 ([CWD])") + .run(); +} + +#[test] +fn publish_with_no_default_features() { + publish::setup(); + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + + [features] + default = ["required"] + required = [] + "#, + ) + .file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ) + .build(); + + p.cargo("publish --no-default-features --index") + .arg(publish::registry().to_string()) + .with_stderr_contains("error: This crate requires `required` feature!") + .with_status(101) + .run(); +}