diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index 10e40e14ffe..fc3ce5e9b9d 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -391,9 +391,9 @@ pub fn prepare_target(cx: &mut Context<'_, '_>, unit: &Unit, force: bool) -> Car let compare = compare_old_fingerprint(&loc, &*fingerprint, mtime_on_use); log_compare(unit, &compare); - // If our comparison failed (e.g., we're going to trigger a rebuild of this - // crate), then we also ensure the source of the crate passes all - // verification checks before we build it. + // If our comparison failed or reported dirty (e.g., we're going to trigger + // a rebuild of this crate), then we also ensure the source of the crate + // passes all verification checks before we build it. // // The `Source::verify` method is intended to allow sources to execute // pre-build checks to ensure that the relevant source code is all @@ -401,7 +401,11 @@ pub fn prepare_target(cx: &mut Context<'_, '_>, unit: &Unit, force: bool) -> Car // directory sources which will use this hook to perform an integrity check // on all files in the source to ensure they haven't changed. If they have // changed then an error is issued. - if compare.is_err() { + if compare + .as_ref() + .map(|dirty| dirty.is_some()) + .unwrap_or(true) + { let source_id = unit.pkg.package_id().source_id(); let sources = bcx.packages.sources(); let source = sources diff --git a/tests/testsuite/freshness.rs b/tests/testsuite/freshness.rs index 6853af13eed..86b186af847 100644 --- a/tests/testsuite/freshness.rs +++ b/tests/testsuite/freshness.rs @@ -2744,3 +2744,73 @@ fn changing_linker() { ) .run(); } + +#[cargo_test] +fn verify_source_before_recompile() { + Package::new("bar", "0.1.0") + .file("src/lib.rs", "") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("vendor --respect-source-config").run(); + p.change_file( + ".cargo/config.toml", + r#" + [source.crates-io] + replace-with = 'vendor' + + [source.vendor] + directory = 'vendor' + "#, + ); + // Sanity check: vendoring works correctly. + p.cargo("check --verbose") + .with_stderr_contains("[RUNNING] `rustc --crate-name bar [CWD]/vendor/bar/src/lib.rs[..]") + .run(); + // Now modify vendored crate. + p.change_file( + "vendor/bar/src/lib.rs", + r#"compile_error!("You shall not pass!");"#, + ); + // Should ignore modifed sources without any recompile. + p.cargo("check --verbose") + .with_stderr( + "\ +[FRESH] bar v0.1.0 +[FRESH] foo v0.1.0 ([CWD]) +[FINISHED] dev [..] +", + ) + .run(); + + // Add a `RUSTFLAGS` to trigger a recompile. + // + // Cargo should refuse to build because of checksum verfication failure. + // Cargo shouldn't recompile dependency `bar`. + p.cargo("check --verbose") + .env("RUSTFLAGS", "-W warnings") + .with_status(101) + .with_stderr( + "\ +error: the listed checksum of `[CWD]/vendor/bar/src/lib.rs` has changed: +expected: [..] +actual: [..] + +directory sources are not [..] +", + ) + .run(); +}