diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index 091192cd766..a5f2c1d1c8b 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -379,9 +379,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 @@ -389,7 +389,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/src/cargo/sources/registry/http_remote.rs b/src/cargo/sources/registry/http_remote.rs index a890b78a03e..7fbcaa7aa25 100644 --- a/src/cargo/sources/registry/http_remote.rs +++ b/src/cargo/sources/registry/http_remote.rs @@ -334,13 +334,6 @@ impl<'cfg> HttpRegistry<'cfg> { } } - fn check_registry_auth_unstable(&self) -> CargoResult<()> { - if self.auth_required && !self.config.cli_unstable().registry_auth { - anyhow::bail!("authenticated registries require `-Z registry-auth`"); - } - Ok(()) - } - /// Get the cached registry configuration, if it exists. fn config_cached(&mut self) -> CargoResult> { if self.registry_config.is_some() { @@ -486,7 +479,9 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> { return Poll::Ready(Ok(LoadResponse::NotFound)); } StatusCode::Unauthorized - if !self.auth_required && path == Path::new("config.json") => + if !self.auth_required + && path == Path::new("config.json") + && self.config.cli_unstable().registry_auth => { debug!("re-attempting request for config.json with authorization included."); self.fresh.remove(path); @@ -542,6 +537,10 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> { } } + if !self.config.cli_unstable().registry_auth { + self.auth_required = false; + } + // Looks like we're going to have to do a network request. self.start_fetch()?; @@ -587,7 +586,6 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> { } } if self.auth_required { - self.check_registry_auth_unstable()?; let authorization = auth::auth_token(self.config, &self.source_id, self.login_url.as_ref(), None)?; headers.append(&format!("Authorization: {}", authorization))?; @@ -660,8 +658,10 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> { } fn config(&mut self) -> Poll>> { - let cfg = ready!(self.config()?).clone(); - self.check_registry_auth_unstable()?; + let mut cfg = ready!(self.config()?).clone(); + if !self.config.cli_unstable().registry_auth { + cfg.auth_required = false; + } Poll::Ready(Ok(Some(cfg))) } diff --git a/src/cargo/sources/registry/remote.rs b/src/cargo/sources/registry/remote.rs index 70aa8efd3f1..aa0ec90233e 100644 --- a/src/cargo/sources/registry/remote.rs +++ b/src/cargo/sources/registry/remote.rs @@ -245,11 +245,9 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> { match ready!(self.load(Path::new(""), Path::new("config.json"), None)?) { LoadResponse::Data { raw_data, .. } => { trace!("config loaded"); - let cfg: RegistryConfig = serde_json::from_slice(&raw_data)?; - if cfg.auth_required && !self.config.cli_unstable().registry_auth { - return Poll::Ready(Err(anyhow::anyhow!( - "authenticated registries require `-Z registry-auth`" - ))); + let mut cfg: RegistryConfig = serde_json::from_slice(&raw_data)?; + if !self.config.cli_unstable().registry_auth { + cfg.auth_required = false; } Poll::Ready(Ok(Some(cfg))) } diff --git a/tests/testsuite/freshness.rs b/tests/testsuite/freshness.rs index 793ebb94c60..112b05e983e 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(); +} diff --git a/tests/testsuite/registry_auth.rs b/tests/testsuite/registry_auth.rs index 419dc61983d..03665e6ee65 100644 --- a/tests/testsuite/registry_auth.rs +++ b/tests/testsuite/registry_auth.rs @@ -42,12 +42,26 @@ static SUCCESS_OUTPUT: &'static str = "\ #[cargo_test] fn requires_nightly() { - let _registry = RegistryBuilder::new().alternative().auth_required().build(); + let _registry = RegistryBuilder::new() + .alternative() + .auth_required() + .http_api() + .build(); let p = make_project(); p.cargo("build") .with_status(101) - .with_stderr_contains(" authenticated registries require `-Z registry-auth`") + .with_stderr( + r#"[UPDATING] `alternative` index +[DOWNLOADING] crates ... +error: failed to download from `[..]/dl/bar/0.0.1/download` + +Caused by: + failed to get successful HTTP response from `[..]`, got 401 + body: + Unauthorized message from server. +"#, + ) .run(); }