From 88679e07f2abecd36faa82b6c233e3df47017a86 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 4 May 2021 00:24:08 -0400 Subject: [PATCH] Implement `[future-incompat-report]` config section Currently, I've just implemented the `always` and `never` frequencies from the RFC, which don't require tracking any additional state. --- src/cargo/core/compiler/job_queue.rs | 28 +++++++++++++---- src/cargo/util/config/mod.rs | 38 +++++++++++++++++++++++ src/doc/src/reference/unstable.md | 12 +++++++ tests/testsuite/config.rs | 2 +- tests/testsuite/future_incompat_report.rs | 37 ++++++++++++++++++++-- 5 files changed, 108 insertions(+), 9 deletions(-) diff --git a/src/cargo/core/compiler/job_queue.rs b/src/cargo/core/compiler/job_queue.rs index 8ddef0b3578..0c2d943b692 100644 --- a/src/cargo/core/compiler/job_queue.rs +++ b/src/cargo/core/compiler/job_queue.rs @@ -885,7 +885,21 @@ impl<'cfg> DrainState<'cfg> { if !bcx.config.cli_unstable().future_incompat_report { return; } + let should_display_message = match bcx.config.future_incompat_config() { + Ok(config) => config.should_display_message(), + Err(e) => { + crate::display_warning_with_error( + "failed to read future-incompat config from disk", + &e, + &mut bcx.config.shell(), + ); + true + } + }; + if self.per_package_future_incompat_reports.is_empty() { + // Explicitly passing a command-line flag overrides + // `should_display_message` from the config file if bcx.build_config.future_incompat_report { drop( bcx.config @@ -907,11 +921,13 @@ impl<'cfg> DrainState<'cfg> { .map(|pid| pid.to_string()) .collect(); - drop(bcx.config.shell().warn(&format!( - "the following packages contain code that will be rejected by a future \ - version of Rust: {}", - package_vers.join(", ") - ))); + if should_display_message || bcx.build_config.future_incompat_report { + drop(bcx.config.shell().warn(&format!( + "the following packages contain code that will be rejected by a future \ + version of Rust: {}", + package_vers.join(", ") + ))); + } let on_disk_reports = OnDiskReports::save_report(bcx.ws, &self.per_package_future_incompat_reports); @@ -925,7 +941,7 @@ impl<'cfg> DrainState<'cfg> { future-incompatibilities -Z future-incompat-report --id {}`", report_id ))); - } else { + } else if should_display_message { drop(bcx.config.shell().note(&format!( "to see what the problems were, use the option \ `--future-incompat-report`, or run `cargo report \ diff --git a/src/cargo/util/config/mod.rs b/src/cargo/util/config/mod.rs index e42b01fa11b..e65d45ba6e4 100644 --- a/src/cargo/util/config/mod.rs +++ b/src/cargo/util/config/mod.rs @@ -178,6 +178,7 @@ pub struct Config { package_cache_lock: RefCell, usize)>>, /// Cached configuration parsed by Cargo http_config: LazyCell, + future_incompat_config: LazyCell, net_config: LazyCell, build_config: LazyCell, target_cfgs: LazyCell>, @@ -275,6 +276,7 @@ impl Config { updated_sources: LazyCell::new(), package_cache_lock: RefCell::new(None), http_config: LazyCell::new(), + future_incompat_config: LazyCell::new(), net_config: LazyCell::new(), build_config: LazyCell::new(), target_cfgs: LazyCell::new(), @@ -1436,6 +1438,11 @@ impl Config { .try_borrow_with(|| self.get::("http")) } + pub fn future_incompat_config(&self) -> CargoResult<&CargoFutureIncompatConfig> { + self.future_incompat_config + .try_borrow_with(|| self.get::("future-incompat-report")) + } + pub fn net_config(&self) -> CargoResult<&CargoNetConfig> { self.net_config .try_borrow_with(|| self.get::("net")) @@ -2034,6 +2041,37 @@ pub struct CargoHttpConfig { pub ssl_version: Option, } +#[derive(Debug, Default, Deserialize, PartialEq)] +#[serde(rename_all = "kebab-case")] +pub struct CargoFutureIncompatConfig { + frequency: Option, +} + +#[derive(Debug, Deserialize, PartialEq)] +#[serde(rename_all = "kebab-case")] +pub enum CargoFutureIncompatFrequencyConfig { + Always, + Never, +} + +impl CargoFutureIncompatConfig { + pub fn should_display_message(&self) -> bool { + use CargoFutureIncompatFrequencyConfig::*; + + let frequency = self.frequency.as_ref().unwrap_or(&Always); + match frequency { + Always => true, + Never => false, + } + } +} + +impl Default for CargoFutureIncompatFrequencyConfig { + fn default() -> Self { + Self::Always + } +} + /// Configuration for `ssl-version` in `http` section /// There are two ways to configure: /// diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 189c0b131a9..35c877b7e2c 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -1215,6 +1215,18 @@ the `--future-incompat-report` flag. The developer should then update their dependencies to a version where the issue is fixed, or work with the developers of the dependencies to help resolve the issue. +This feature can be configured through a `[future-incompat-report]` +section in `.cargo/config`. Currently, the supported options are: + +``` +[future-incompat-report] +frequency = FREQUENCY +``` + +The supported values for `FREQUENCY` are 'always` and 'never', which control +whether or not a message is printed out at the end of `cargo build` / `cargo check`. + + ### patch-in-config * Original Pull Request: [#9204](https://github.com/rust-lang/cargo/pull/9204) * Tracking Issue: [#9269](https://github.com/rust-lang/cargo/issues/9269) diff --git a/tests/testsuite/config.rs b/tests/testsuite/config.rs index 176fdd88321..1468cdef39a 100644 --- a/tests/testsuite/config.rs +++ b/tests/testsuite/config.rs @@ -148,7 +148,7 @@ pub fn write_config_at(path: impl AsRef, contents: &str) { fs::write(path, contents).unwrap(); } -fn write_config_toml(config: &str) { +pub fn write_config_toml(config: &str) { write_config_at(paths::root().join(".cargo/config.toml"), config); } diff --git a/tests/testsuite/future_incompat_report.rs b/tests/testsuite/future_incompat_report.rs index eb197da9956..7edd89b5c0a 100644 --- a/tests/testsuite/future_incompat_report.rs +++ b/tests/testsuite/future_incompat_report.rs @@ -7,6 +7,7 @@ //! So we pick some random lint that will likely always be the same //! over time. +use super::config::write_config_toml; use cargo_test_support::registry::Package; use cargo_test_support::{basic_manifest, is_nightly, project, Project}; @@ -115,14 +116,46 @@ fn test_single_crate() { let p = simple_project(); for command in &["build", "check", "rustc", "test"] { - p.cargo(command).arg("-Zfuture-incompat-report") + let check_has_future_compat = || { + p.cargo(command).arg("-Zfuture-incompat-report") + .masquerade_as_nightly_cargo() + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .with_stderr_contains(FUTURE_OUTPUT) + .with_stderr_contains("warning: the following packages contain code that will be rejected by a future version of Rust: foo v0.0.0 [..]") + .with_stderr_does_not_contain("[..]incompatibility[..]") + .run(); + }; + + // Check that we show a message with no [future-incompat-report] config section + write_config_toml(""); + check_has_future_compat(); + + // Check that we show a message with `frequence = "always"` + write_config_toml( + "\ +[future-incompat-report] +frequency = 'always' +", + ); + check_has_future_compat(); + + // Check that we do not show a message with `frequency = "never"` + write_config_toml( + "\ +[future-incompat-report] +frequency = 'never' +", + ); + p.cargo(command) + .arg("-Zfuture-incompat-report") .masquerade_as_nightly_cargo() .env("RUSTFLAGS", "-Zfuture-incompat-test") .with_stderr_contains(FUTURE_OUTPUT) - .with_stderr_contains("warning: the following packages contain code that will be rejected by a future version of Rust: foo v0.0.0 [..]") + .with_stderr_does_not_contain("[..]rejected[..]") .with_stderr_does_not_contain("[..]incompatibility[..]") .run(); + // Check that passing `--future-incompat-report` overrides `frequency = 'never'` p.cargo(command).arg("-Zfuture-incompat-report").arg("-Zunstable-options").arg("--future-incompat-report") .masquerade_as_nightly_cargo() .env("RUSTFLAGS", "-Zfuture-incompat-test")