Add warnings for unknown profile overrides.
authorEric Huss <eric@huss.org>
Sat, 21 Apr 2018 05:19:16 +0000 (22:19 -0700)
committerEric Huss <eric@huss.org>
Fri, 27 Apr 2018 20:42:30 +0000 (13:42 -0700)
src/cargo/core/profiles.rs
src/cargo/core/workspace.rs
src/cargo/ops/cargo_compile.rs
tests/testsuite/profiles.rs

index ac3651fe0bfcd3b53db051dc70678811fe74fe12..71ee27102fea27d780c16a59fe1817f736aca5f7 100644 (file)
@@ -1,7 +1,12 @@
 use std::{cmp, fmt, hash};
+use std::collections::HashSet;
+
+use core::Shell;
+use core::interning::InternedString;
 use ops::CompileMode;
+use util::CargoResult;
+use util::lev_distance::lev_distance;
 use util::toml::{StringOrBool, TomlProfile, U32OrBool};
-use core::interning::InternedString;
 
 /// Collection of all user profiles.
 #[derive(Clone, Debug)]
@@ -112,6 +117,20 @@ impl Profiles {
             self.dev.profile_for("", true, ProfileFor::Any)
         }
     }
+
+    /// Used to check for overrides for non-existing packages.
+    pub fn validate_packages(
+        &self,
+        shell: &mut Shell,
+        packages: &HashSet<&str>,
+    ) -> CargoResult<()> {
+        self.dev.validate_packages(shell, packages)?;
+        self.release.validate_packages(shell, packages)?;
+        self.test.validate_packages(shell, packages)?;
+        self.bench.validate_packages(shell, packages)?;
+        self.doc.validate_packages(shell, packages)?;
+        Ok(())
+    }
 }
 
 /// An object used for handling the profile override hierarchy.
@@ -152,6 +171,32 @@ impl ProfileMaker {
         }
         profile
     }
+
+    fn validate_packages(&self, shell: &mut Shell, packages: &HashSet<&str>) -> CargoResult<()> {
+        if let Some(ref toml) = self.toml {
+            if let Some(ref overrides) = toml.overrides {
+                for key in overrides.keys().filter(|k| k.as_str() != "*") {
+                    if !packages.contains(key.as_str()) {
+                        let suggestion = packages
+                            .iter()
+                            .map(|p| (lev_distance(key, p), p))
+                            .filter(|&(d, _)| d < 4)
+                            .min_by_key(|p| p.0)
+                            .map(|p| p.1);
+                        match suggestion {
+                            Some(p) => shell.warn(format!(
+                                "package `{}` for profile override not found\n\nDid you mean `{}`?",
+                                key, p
+                            ))?,
+                            None => shell
+                                .warn(format!("package `{}` for profile override not found", key))?,
+                        };
+                    }
+                }
+            }
+        }
+        Ok(())
+    }
 }
 
 fn merge_profile(profile: &mut Profile, toml: &TomlProfile) {
index 0de6ef40ab81c5e60c66366bd6d0ceda8622b523..8f339045407f09a0c7f676579a8e3589c31018d4 100644 (file)
@@ -310,8 +310,6 @@ impl<'cfg> Workspace<'cfg> {
 
     /// Returns true if the package is a member of the workspace.
     pub fn is_member(&self, pkg: &Package) -> bool {
-        // TODO: Implement this in a better way.
-        //       Maybe make it part of Package?
         self.members().any(|p| p == pkg)
     }
 
index 6ff4cc01a8de93d467d43368ea08a928e7447426..dec8cb196d5b693c7d6ef44aefe32c2c9dba277b 100644 (file)
@@ -382,6 +382,12 @@ pub fn compile_ws<'a>(
     }
 
     let profiles = ws.profiles();
+    let package_names = packages
+        .package_ids()
+        .map(|pid| pid.name().as_str())
+        .collect::<HashSet<_>>();
+    profiles.validate_packages(&mut config.shell(), &package_names)?;
+
     let mut extra_compiler_args = None;
 
     let units = generate_targets(
index 528806856bd3daa33676339aeecfcb4c83e54b30..4e526a9327454ad52fb52874e6822a3be1186f53 100644 (file)
@@ -1,7 +1,7 @@
 use std::env;
 
 use cargotest::is_nightly;
-use cargotest::support::{execs, project};
+use cargotest::support::{basic_lib_manifest, execs, project};
 use cargotest::ChannelChanger;
 use hamcrest::assert_that;
 
@@ -426,24 +426,16 @@ fn profile_override_basic() {
         "#,
         )
         .file("src/lib.rs", "")
-        .file(
-            "bar/Cargo.toml",
-            r#"
-            [package]
-            name = "bar"
-            version = "0.0.1"
-            authors = []
-        "#,
-        )
+        .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
         .file("bar/src/lib.rs", "")
         .build();
 
     assert_that(
         p.cargo("build -v").masquerade_as_nightly_cargo(),
         execs().with_status(0).with_stderr(
-"[COMPILING] bar v0.0.1 ([..])
+"[COMPILING] bar [..]
 [RUNNING] `rustc --crate-name bar [..] -C opt-level=3 [..]`
-[COMPILING] foo v0.0.1 ([..])
+[COMPILING] foo [..]
 [RUNNING] `rustc --crate-name foo [..]`
 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
         )
@@ -451,5 +443,42 @@ fn profile_override_basic() {
         // .with_stderr_does_not_contain("\
         //     `rustc --crate-name bar[..]-C opt-level=3"),
     );
+}
+
+#[test]
+fn profile_override_bad_name() {
+    let p = project("foo")
+        .file(
+            "Cargo.toml",
+            r#"
+            cargo-features = ["profile-overrides"]
+
+            [package]
+            name = "foo"
+            version = "0.0.1"
+
+            [dependencies]
+            bar = {path = "bar"}
+
+            [profile.dev.overrides.bart]
+            opt-level = 3
+
+            [profile.dev.overrides.no-suggestion]
+            opt-level = 3
+        "#,
+        )
+        .file("src/lib.rs", "")
+        .file("bar/Cargo.toml", &basic_lib_manifest("bar"))
+        .file("bar/src/lib.rs", "")
+        .build();
+
+    assert_that(
+        p.cargo("build").masquerade_as_nightly_cargo(),
+        execs().with_status(0).with_stderr_contains("\
+[WARNING] package `bart` for profile override not found
 
+Did you mean `bar`?
+[WARNING] package `no-suggestion` for profile override not found
+[COMPILING] [..]
+"));
 }