From 74522305c6dd1baaed14978cb424ca7c0c983d6d Mon Sep 17 00:00:00 2001 From: Jesse Hallett Date: Thu, 23 Jan 2025 00:15:04 -0800 Subject: [PATCH 1/2] fix parsing checksums from v1 manifests with latest cargo Crate2nix identifies packages using package ID strings reported by the `cargo metadata` subcommand. Cargo describes these strings as internal identifiers subject to change. And in fact the string format did change sometime between cargo 1.76 and cargo 1.78. In cargo 1.76 package ID strings look like this: ``` aho-corasick 1.1.3 (registry+https://github.com/rust-lang/crates.io-index) ``` In later cargo versions the format changed to look like this: ``` registry+https://github.com/rust-lang/crates.io-index#aho-corasick@1.1.3 ``` The change is fine as long as package IDs are used as opaque identifiers in memory. Unfortunately one use of package IDs is to look up checksums in the legacy v1 `Cargo.lock` manifest format. That format stores checksums in a map at the end of the file that looks like this: ```toml [metadata] "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" ``` Being a legacy format the keys in these checksum maps will always use the old package ID format. The problem becomes quickly apparent because nix-test-runner - which is used in the crate2nix test suite - happens to use a v1 manifest. That leads to tests and the devShell breaking when attempting to update crate2nix flake inputs. Currently crate2nix assumes that package IDs read from `cargo metadata` output can be used as lookup keys in the v1 checksum map. But when a recent version of cargo is installed that assumption is broken. This PR fixes the problem by constructing checksum lookup keys explicitly. This should make checksum lookups work regardless of which cargo version is installed. --- crate2nix/src/lock.rs | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/crate2nix/src/lock.rs b/crate2nix/src/lock.rs index b0aab37d..719e7ee9 100644 --- a/crate2nix/src/lock.rs +++ b/crate2nix/src/lock.rs @@ -50,32 +50,31 @@ impl EncodableResolve { .. } in self.package.iter() { - let Some((source, checksum)) = Option::zip(source.as_ref(), checksum.as_ref()) else { + let Some(source) = source.as_ref() else { continue; }; - if checksum == "" { - continue; - } - if let Some(package_id) = + let Some(package_id) = package_id_by_source.get(&(name.as_str(), source.as_str(), version.clone())) - { - hashes.insert((*package_id).clone(), checksum.clone()); - } - } + else { + continue; + }; - // Retrieve legacy checksums. - const CHECKSUM_PREFIX: &str = "checksum "; - if let Some(metadata) = &self.metadata { - for (key, value) in metadata { - if key.starts_with(CHECKSUM_PREFIX) { - let package_id = PackageId { - repr: key.trim_start_matches(CHECKSUM_PREFIX).to_string(), - }; - if value != "" { - hashes.insert(package_id, value.clone()); - } + let checksum = match checksum.as_ref() { + Some(checksum) if checksum == "" => None, + Some(checksum) => Some(checksum), + None => { + // Retrieve legacy checksums. + self.metadata.as_ref().and_then(|metadata| { + const CHECKSUM_PREFIX: &str = "checksum"; + let checksum_key = format!("{CHECKSUM_PREFIX} {name} {version} ({source})"); + metadata.get(&checksum_key) + }) } + }; + + if let Some(checksum) = checksum { + hashes.insert((*package_id).clone(), checksum.to_owned()); } } From 12683ecc033f29481a35540c8c7acc66b6f35e6d Mon Sep 17 00:00:00 2001 From: Jesse Hallett Date: Thu, 23 Jan 2025 00:42:15 -0800 Subject: [PATCH 2/2] remove redundant const --- crate2nix/src/lock.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crate2nix/src/lock.rs b/crate2nix/src/lock.rs index 719e7ee9..e930fc29 100644 --- a/crate2nix/src/lock.rs +++ b/crate2nix/src/lock.rs @@ -66,8 +66,7 @@ impl EncodableResolve { None => { // Retrieve legacy checksums. self.metadata.as_ref().and_then(|metadata| { - const CHECKSUM_PREFIX: &str = "checksum"; - let checksum_key = format!("{CHECKSUM_PREFIX} {name} {version} ({source})"); + let checksum_key = format!("checksum {name} {version} ({source})"); metadata.get(&checksum_key) }) }