From 64a468261aa05f2cd7a0d65dc1a6b4a576ed1938 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 17 Jul 2020 10:07:06 -0700 Subject: [PATCH] Fix freshness checks for build scripts on renamed dirs This commit fixes an issue in Cargo where when an entire project directory is renamed (preserving the target directory) then path dependencies with build scripts would have their build scripts rereun when building again. The problem with this was that when a build script doesn't print `rerun-if-changed` Cargo's conservative fingerprint listed an absolute path in it, which was intended to be a relative path. The fix here is to use a relative path in the fingerprint to ensure that it's not the reason a rebuild happens when directories are renamed. --- src/cargo/core/workspace.rs | 6 +----- src/cargo/sources/path.rs | 4 ++++ tests/testsuite/freshness.rs | 26 ++++++++++++++++++-------- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index ccde5b9ecce..cdee37b376a 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -873,11 +873,7 @@ impl<'cfg> Workspace<'cfg> { MaybePackage::Package(ref p) => p.clone(), MaybePackage::Virtual(_) => continue, }; - let mut src = PathSource::new( - pkg.manifest_path(), - pkg.package_id().source_id(), - self.config, - ); + let mut src = PathSource::new(pkg.root(), pkg.package_id().source_id(), self.config); src.preload_with(pkg); registry.add_preloaded(Box::new(src)); } diff --git a/src/cargo/sources/path.rs b/src/cargo/sources/path.rs index cf406e8ddb2..64b0f77ed5a 100644 --- a/src/cargo/sources/path.rs +++ b/src/cargo/sources/path.rs @@ -522,6 +522,10 @@ impl<'cfg> Source for PathSource<'cfg> { fn fingerprint(&self, pkg: &Package) -> CargoResult { let (max, max_path) = self.last_modified_file(pkg)?; + // Note that we try to strip the prefix of this package to get a + // relative path to ensure that the fingerprint remains consistent + // across entire project directory renames. + let max_path = max_path.strip_prefix(&self.path).unwrap_or(&max_path); Ok(format!("{} ({})", max, max_path.display())) } diff --git a/tests/testsuite/freshness.rs b/tests/testsuite/freshness.rs index 26d898484fc..1ff8b8374f2 100644 --- a/tests/testsuite/freshness.rs +++ b/tests/testsuite/freshness.rs @@ -857,20 +857,30 @@ fn no_rebuild_when_rename_dir() { .file( "Cargo.toml", r#" - [package] - name = "bar" - version = "0.0.1" - authors = [] + [package] + name = "bar" + version = "0.0.1" + authors = [] - [dependencies] - foo = { path = "foo" } - "#, + [workspace] + + [dependencies] + foo = { path = "foo" } + "#, ) - .file("src/lib.rs", "") + .file("src/_unused.rs", "") + .file("build.rs", "fn main() {}") .file("foo/Cargo.toml", &basic_manifest("foo", "0.0.1")) .file("foo/src/lib.rs", "") + .file("foo/build.rs", "fn main() {}") .build(); + // make sure the most recently modified file is `src/lib.rs`, not + // `Cargo.toml`, to expose a historical bug where we forgot to strip the + // `Cargo.toml` path from looking for the package root. + cargo_test_support::sleep_ms(100); + fs::write(p.root().join("src/lib.rs"), "").unwrap(); + p.cargo("build").run(); let mut new = p.root(); new.pop();