diff --git a/crates/cargo-test-support/src/registry.rs b/crates/cargo-test-support/src/registry.rs index 17a90e8f6be..7092a1f9e21 100644 --- a/crates/cargo-test-support/src/registry.rs +++ b/crates/cargo-test-support/src/registry.rs @@ -385,6 +385,7 @@ pub struct Package { alternative: bool, invalid_json: bool, proc_macro: bool, + generate_checksum: bool, links: Option, rust_version: Option, cargo_features: Vec, @@ -860,6 +861,7 @@ impl Package { alternative: false, invalid_json: false, proc_macro: false, + generate_checksum: true, links: None, rust_version: None, cargo_features: Vec::new(), @@ -877,6 +879,12 @@ impl Package { self } + /// Call with `true` to prevent a checksum being generated for the package. + pub fn skip_checksum(&mut self, local: bool) -> &mut Package { + self.generate_checksum = !local; + self + } + /// Call with `true` to publish in an "alternative registry". /// /// The name of the alternative registry is called "alternative". @@ -1075,9 +1083,11 @@ impl Package { }) }) .collect::>(); - let cksum = { + let cksum = if self.generate_checksum { let c = t!(fs::read(&self.archive_dst())); cksum(&c) + } else { + String::new() }; let name = if self.invalid_json { serde_json::json!(1) diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index 000ded24652..fdb950270f7 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -147,7 +147,10 @@ pub fn resolve( let mut cksums = HashMap::new(); for (summary, _) in cx.activations.values() { - let cksum = summary.checksum().map(|s| s.to_string()); + let cksum = summary + .checksum() + .map(|s| s.to_string()) + .filter(|s| !s.is_empty()); cksums.insert(summary.package_id(), cksum); } let graph = cx.graph(); diff --git a/src/cargo/sources/registry/local.rs b/src/cargo/sources/registry/local.rs index a4b57a91e7a..fc4153b3e41 100644 --- a/src/cargo/sources/registry/local.rs +++ b/src/cargo/sources/registry/local.rs @@ -129,7 +129,11 @@ impl<'cfg> RegistryData for LocalRegistry<'cfg> { // We don't actually need to download anything per-se, we just need to // verify the checksum matches the .crate file itself. let actual = Sha256::new().update_file(&crate_file)?.finish_hex(); - if actual != checksum { + + // If a checksum of a package from local registry is empty, + // we assume it comes from a git dependency and can be skipped. + // (Probably be generated by tool `cargo-local-registry`) + if actual != checksum && !checksum.is_empty() { anyhow::bail!("failed to verify the checksum of `{}`", pkg) } diff --git a/tests/testsuite/directory.rs b/tests/testsuite/directory.rs index aef2969e8dd..b718ec99a8d 100644 --- a/tests/testsuite/directory.rs +++ b/tests/testsuite/directory.rs @@ -410,10 +410,11 @@ fn crates_io_then_bad_checksum() { p.cargo("build").run(); setup(); - VendorPackage::new("bar") - .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) - .file("src/lib.rs", "") - .build(); + let mut v = VendorPackage::new("bar"); + v.file("Cargo.toml", &basic_manifest("bar", "0.1.0")); + v.file("src/lib.rs", ""); + v.cksum.package = Some("abcdef".into()); + v.build(); p.cargo("build") .with_status(101) diff --git a/tests/testsuite/local_registry.rs b/tests/testsuite/local_registry.rs index 1e242454601..4d1b0830245 100644 --- a/tests/testsuite/local_registry.rs +++ b/tests/testsuite/local_registry.rs @@ -2,7 +2,7 @@ use cargo_test_support::paths::{self, CargoPathExt}; use cargo_test_support::registry::{registry_path, Package}; -use cargo_test_support::{basic_manifest, project, t}; +use cargo_test_support::{basic_manifest, git, path2url, project, t}; use std::fs; fn setup() { @@ -526,3 +526,79 @@ fn crates_io_registry_url_is_optional() { p.cargo("build").with_stderr("[FINISHED] [..]").run(); p.cargo("test").run(); } + +#[cargo_test] +fn git_dependencies_do_not_require_a_checksum() { + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("src/lib.rs", "pub fn bar() {}") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies.bar] + git = '{}' + "#, + git_project.url() + ), + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("generate-lockfile").run(); + + let root = paths::root(); + t!(fs::create_dir(&root.join(".cargo"))); + + Package::new("bar", "0.0.1") + .local(true) + // Omit the checksum from the local registry by setting it to an empty string + // since git dependencies do not have checksums. Make sure that cargo doesn't + // treat this empty checksum as invalid. + // See https://github.com/rust-lang/cargo/pull/11188 for more info. + .skip_checksum(true) + .file("src/lib.rs", "pub fn bar() {}") + .publish(); + + t!(fs::write( + root.join(".cargo/config"), + format!( + r#" + [source.my-awesome-git-registry] + git = '{}' + replace-with = 'my-awesome-local-registry' + + [source.my-awesome-local-registry] + local-registry = 'registry' + "#, + git_project.url() + ) + )); + p.cargo("clean").run(); + p.cargo("build") + .with_stderr(&format!( + "[UNPACKING] bar v0.0.1 ([..])\n\ + [COMPILING] bar v0.0.1 ({}#[..])\n\ + [COMPILING] foo v0.0.1 ([CWD])\n\ + [FINISHED] [..]\n", + path2url(&git_project.root()) + )) + .run(); + p.cargo("build").with_stderr("[FINISHED] [..]").run(); + p.cargo("test").run(); + let lockfile = t!(fs::read_to_string(p.root().join("Cargo.lock"))); + // We only have one dependency, and it should not contain a checksum in the lockfile + assert!(!lockfile.contains("checksum")); +}