diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index 8ed33b2f6..2f7ea741a 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -333,7 +333,10 @@ impl Features { /// and then test for your flag or your value and act accordingly. /// /// If you have any trouble with this, please let us know! -#[derive(Default, Debug)] +#[derive(Default, Debug, Deserialize)] +#[serde(default)] +#[serde(deny_unknown_fields)] +#[serde(rename_all="kebab-case")] pub struct CliUnstable { pub print_im_a_teapot: bool, pub unstable_options: bool, diff --git a/src/cargo/util/config/mod.rs b/src/cargo/util/config/mod.rs index bb3149352..156a272b9 100644 --- a/src/cargo/util/config/mod.rs +++ b/src/cargo/util/config/mod.rs @@ -63,7 +63,7 @@ use std::str::FromStr; use std::sync::Once; use std::time::Instant; -use anyhow::{anyhow, bail, Context}; +use anyhow::{anyhow, bail}; use curl::easy::Easy; use lazycell::LazyCell; use serde::Deserialize; @@ -745,18 +745,13 @@ impl Config { // If nightly features are enabled, allow setting Z-flags from config // using the `unstable` table. Ignore that block otherwise. if nightly_features_allowed() { - if let Some(unstable_configs) = - self.get::>>("unstable")? - { - self.unstable_flags - .update_with_table(&unstable_configs) - .with_context(|| "Invalid [unstable] entry in Cargo config")?; - - // NB. It sucks to parse these twice, but doing it again here - // allows the CLI to override config files for both enabling - // and disabling. - self.unstable_flags.parse(unstable_flags)?; + if let Some(unstable_flags) = self.get::>("unstable")? { + self.unstable_flags = unstable_flags; } + // NB. It sucks to parse these twice, but doing it again here + // allows the CLI to override config files for both enabling + // and disabling. + self.unstable_flags.parse(unstable_flags)?; } Ok(()) diff --git a/tests/testsuite/config.rs b/tests/testsuite/config.rs index 7b3384aa6..acb46730b 100644 --- a/tests/testsuite/config.rs +++ b/tests/testsuite/config.rs @@ -1097,12 +1097,12 @@ Caused by: #[cargo_test] /// Assert that unstable options can be configured with the `unstable` table in /// cargo config files -fn config_unstable_table() { +fn unstable_table_notation() { cargo::core::enable_nightly_features(); write_config( "\ [unstable] -print-im-a-teapot = 'yes' +print-im-a-teapot = true ", ); let config = ConfigBuilder::new().build(); @@ -1111,11 +1111,11 @@ print-im-a-teapot = 'yes' #[cargo_test] /// Assert that dotted notation works for configuring unstable options -fn config_unstable_dotted() { +fn unstable_dotted_notation() { cargo::core::enable_nightly_features(); write_config( "\ -unstable.print-im-a-teapot = 'yes' +unstable.print-im-a-teapot = true ", ); let config = ConfigBuilder::new().build(); @@ -1124,11 +1124,11 @@ unstable.print-im-a-teapot = 'yes' #[cargo_test] /// Assert that Zflags on the CLI take precedence over those from config -fn config_unstable_cli_wins() { +fn unstable_cli_precedence() { cargo::core::enable_nightly_features(); write_config( "\ -unstable.print-im-a-teapot = 'yes' +unstable.print-im-a-teapot = true ", ); let config = ConfigBuilder::new().build(); @@ -1142,8 +1142,8 @@ unstable.print-im-a-teapot = 'yes' #[cargo_test] /// Assert that atempting to set an unstable flag that doesn't exist via config -/// errors out the same as it would on the command line -fn config_unstable_invalid_flag() { +/// errors out the same as it would on the command line (nightly only) +fn unstable_invalid_flag_errors_on_nightly() { cargo::core::enable_nightly_features(); write_config( "\ @@ -1160,6 +1160,32 @@ Caused by: ); } +#[cargo_test] +/// Assert that atempting to set an unstable flag that doesn't exist via config +/// is ignored on stable +fn unstable_invalid_flag_ignored_on_stable() { + write_config( + "\ +unstable.an-invalid-flag = 'yes' +", + ); + assert!(ConfigBuilder::new().build_err().is_ok()); +} + +#[cargo_test] +/// Assert that unstable options can be configured with the `unstable` table in +/// cargo config files +fn unstable_flags_ignored_on_stable() { + write_config( + "\ +[unstable] +print-im-a-teapot = true +", + ); + let config = ConfigBuilder::new().build(); + assert_eq!(config.cli_unstable().print_im_a_teapot, false); +} + #[cargo_test] fn table_merge_failure() { // Config::merge fails to merge entries in two tables.