From fc72bcb4494361ebd0870d09b8352a75eed3323b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 28 Apr 2018 13:35:49 +0300 Subject: [PATCH] Mix package renames into fingerprints --- src/cargo/core/compiler/context/mod.rs | 26 ++++++++++++++ src/cargo/core/compiler/fingerprint.rs | 27 +++++++++------ src/cargo/core/compiler/mod.rs | 25 +------------- tests/testsuite/rename_deps.rs | 48 ++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 35 deletions(-) diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index 8326e16d4a4..f3d1e6d18ed 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -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 { + 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 { diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index 9020c5cf2a8..73bd44bf3eb 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -150,7 +150,7 @@ pub struct Fingerprint { profile: u64, path: u64, #[serde(serialize_with = "serialize_deps", deserialize_with = "deserialize_deps")] - deps: Vec<(String, Arc)>, + deps: Vec<(String, String, Arc)>, local: Vec, #[serde(skip_serializing, skip_deserializing)] memoized_hash: Mutex>, @@ -158,25 +158,26 @@ pub struct Fingerprint { edition: Edition, } -fn serialize_deps(deps: &[(String, Arc)], ser: S) -> Result +fn serialize_deps(deps: &[(String, String, Arc)], ser: S) -> Result 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::>() .serialize(ser) } -fn deserialize_deps<'de, D>(d: D) -> Result)>, D::Error> +fn deserialize_deps<'de, D>(d: D) -> Result)>, D::Error> where D: de::Deserializer<'de>, { - let decoded = >::deserialize(d)?; + let decoded = >::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::>>()?; @@ -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 { diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index c0a948cc911..28718a67f78 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -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)); diff --git a/tests/testsuite/rename_deps.rs b/tests/testsuite/rename_deps.rs index 7d70833d3cb..afb80008e87 100644 --- a/tests/testsuite/rename_deps.rs +++ b/tests/testsuite/rename_deps.rs @@ -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), + ); +}