Mix package renames into fingerprints
authorAleksey Kladov <aleksey.kladov@gmail.com>
Sat, 28 Apr 2018 10:35:49 +0000 (13:35 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Sat, 28 Apr 2018 10:38:16 +0000 (13:38 +0300)
src/cargo/core/compiler/context/mod.rs
src/cargo/core/compiler/fingerprint.rs
src/cargo/core/compiler/mod.rs
tests/testsuite/rename_deps.rs

index 8326e16d4a4640a302bed74f0f293a75c920abd2..f3d1e6d18ed94b3f225e49df1dd0ba1cd2024221 100644 (file)
@@ -429,6 +429,32 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         self.unit_dependencies[unit].clone()
     }
 
+    pub fn extern_crate_name(&self, unit: &Unit<'a>, dep: &Unit<'a>) -> CargoResult<String> {
+        let deps = {
+            let a = unit.pkg.package_id();
+            let b = dep.pkg.package_id();
+            if a == b {
+                &[]
+            } else {
+                self.resolve.dependencies_listed(a, b)
+            }
+        };
+
+        let crate_name = dep.target.crate_name();
+        let mut names = deps.iter()
+            .map(|d| d.rename().unwrap_or(&crate_name));
+        let name = names.next().unwrap_or(&crate_name);
+        for n in names {
+            if n == name {
+                continue
+            }
+            bail!("multiple dependencies listed for the same crate must \
+                   all have the same name, but the dependency on `{}` \
+                   is listed as having different names", dep.pkg.package_id());
+        }
+        Ok(name.to_string())
+    }
+
     /// Whether a dependency should be compiled for the host or target platform,
     /// specified by `Kind`.
     fn dep_platform_activated(&self, dep: &Dependency, kind: Kind) -> bool {
index 9020c5cf2a8639e2fa2307d515b6e47574a5c585..73bd44bf3eb27e034904a0a9a70443b50a877367 100644 (file)
@@ -150,7 +150,7 @@ pub struct Fingerprint {
     profile: u64,
     path: u64,
     #[serde(serialize_with = "serialize_deps", deserialize_with = "deserialize_deps")]
-    deps: Vec<(String, Arc<Fingerprint>)>,
+    deps: Vec<(String, String, Arc<Fingerprint>)>,
     local: Vec<LocalFingerprint>,
     #[serde(skip_serializing, skip_deserializing)]
     memoized_hash: Mutex<Option<u64>>,
@@ -158,25 +158,26 @@ pub struct Fingerprint {
     edition: Edition,
 }
 
-fn serialize_deps<S>(deps: &[(String, Arc<Fingerprint>)], ser: S) -> Result<S::Ok, S::Error>
+fn serialize_deps<S>(deps: &[(String, String, Arc<Fingerprint>)], ser: S) -> Result<S::Ok, S::Error>
 where
     S: ser::Serializer,
 {
     deps.iter()
-        .map(|&(ref a, ref b)| (a, b.hash()))
+        .map(|&(ref a, ref b, ref c)| (a, b, c.hash()))
         .collect::<Vec<_>>()
         .serialize(ser)
 }
 
-fn deserialize_deps<'de, D>(d: D) -> Result<Vec<(String, Arc<Fingerprint>)>, D::Error>
+fn deserialize_deps<'de, D>(d: D) -> Result<Vec<(String, String, Arc<Fingerprint>)>, D::Error>
 where
     D: de::Deserializer<'de>,
 {
-    let decoded = <Vec<(String, u64)>>::deserialize(d)?;
+    let decoded = <Vec<(String, String, u64)>>::deserialize(d)?;
     Ok(decoded
         .into_iter()
-        .map(|(name, hash)| {
+        .map(|(pkg_id, name, hash)| {
             (
+                pkg_id,
                 name,
                 Arc::new(Fingerprint {
                     rustc: 0,
@@ -330,7 +331,7 @@ impl Fingerprint {
             bail!("number of dependencies has changed")
         }
         for (a, b) in self.deps.iter().zip(old.deps.iter()) {
-            if a.1.hash() != b.1.hash() {
+            if a.1 != b.1 || a.2.hash() != b.2.hash() {
                 bail!("new ({}) != old ({})", a.0, b.0)
             }
         }
@@ -357,7 +358,8 @@ impl hash::Hash for Fingerprint {
         ).hash(h);
 
         h.write_usize(deps.len());
-        for &(ref name, ref fingerprint) in deps {
+        for &(ref pkg_id, ref name, ref fingerprint) in deps {
+            pkg_id.hash(h);
             name.hash(h);
             // use memoized dep hashes to avoid exponential blowup
             h.write_u64(Fingerprint::hash(fingerprint));
@@ -426,8 +428,11 @@ fn calculate<'a, 'cfg>(
     let deps = cx.dep_targets(unit);
     let deps = deps.iter()
         .filter(|u| !u.target.is_custom_build() && !u.target.is_bin())
-        .map(|unit| {
-            calculate(cx, unit).map(|fingerprint| (unit.pkg.package_id().to_string(), fingerprint))
+        .map(|dep| {
+            calculate(cx, dep).and_then(|fingerprint| {
+                let name = cx.extern_crate_name(unit, dep)?;
+                Ok((dep.pkg.package_id().to_string(), name, fingerprint))
+            })
         })
         .collect::<CargoResult<Vec<_>>>()?;
 
@@ -441,7 +446,7 @@ fn calculate<'a, 'cfg>(
         LocalFingerprint::Precalculated(fingerprint)
     };
     let mut deps = deps;
-    deps.sort_by(|&(ref a, _), &(ref b, _)| a.cmp(b));
+    deps.sort_by(|&(ref a, _, _), &(ref b, _, _)| a.cmp(b));
     let extra_flags = if unit.mode.is_doc() {
         cx.rustdocflags_args(unit)?
     } else {
index c0a948cc9114cb6bfde9649c254f9024b28d0cf1..28718a67f78da15db530b5ed239ab46a5623612b 100644 (file)
@@ -1097,30 +1097,7 @@ fn build_deps_args<'a, 'cfg>(
                 continue;
             }
             let mut v = OsString::new();
-
-            let deps = {
-                let a = current.pkg.package_id();
-                let b = dep.pkg.package_id();
-                if a == b {
-                    &[]
-                } else {
-                    cx.resolve.dependencies_listed(a, b)
-                }
-            };
-
-            let crate_name = dep.target.crate_name();
-            let mut names = deps.iter()
-                .map(|d| d.rename().unwrap_or(&crate_name));
-            let name = names.next().unwrap_or(&crate_name);
-            for n in names {
-                if n == name {
-                    continue
-                }
-                bail!("multiple dependencies listed for the same crate must \
-                       all have the same name, but the dependency on `{}` \
-                       is listed as having different names", dep.pkg.package_id());
-            }
-
+            let name = cx.extern_crate_name(current, dep)?;
             v.push(name);
             v.push("=");
             v.push(cx.files().out_dir(dep));
index 7d70833d3cbbe26021296da343cbcc66c67db325..afb80008e872906b2deb1aadbeb2f366acf48340 100644 (file)
@@ -315,3 +315,51 @@ name, but the dependency on `foo v0.1.0` is listed as having different names
 ")
     );
 }
+
+#[test]
+fn rename_affects_fingerprint() {
+    Package::new("foo", "0.1.0").publish();
+
+    let p = project("foo")
+        .file(
+            "Cargo.toml",
+            r#"
+                cargo-features = ["rename-dependency"]
+
+                [package]
+                name = "test"
+                version = "0.1.0"
+                authors = []
+
+                [dependencies]
+                foo = { version = "0.1", package = "foo" }
+            "#,
+        )
+        .file("src/lib.rs", "extern crate foo;")
+        .build();
+
+    assert_that(
+        p.cargo("build -v").masquerade_as_nightly_cargo(),
+        execs().with_status(0),
+    );
+
+    p.change_file(
+        "Cargo.toml",
+        r#"
+                cargo-features = ["rename-dependency"]
+
+                [package]
+                name = "test"
+                version = "0.1.0"
+                authors = []
+
+                [dependencies]
+                bar = { version = "0.1", package = "foo" }
+        "#,
+    );
+
+    assert_that(
+        p.cargo("build -v").masquerade_as_nightly_cargo(),
+        execs().with_status(101),
+    );
+}