diff --git a/Cargo.lock b/Cargo.lock index 311cd98..8087633 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "adler" @@ -250,9 +250,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -308,12 +308,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.2", "serde", ] @@ -469,6 +469,7 @@ dependencies = [ "byteorder", "concurrent_lru", "fancy-regex", + "indexmap 2.7.1", "lazy_static", "miniz_oxide", "mmap-rs", @@ -599,7 +600,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.6", + "indexmap 2.7.1", "serde", "serde_derive", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 6c4ecdf..f88a1a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ arca = "^0.7" byteorder = "1" concurrent_lru = "^0.2" fancy-regex = "^0.13.0" +indexmap = { version = "2.7.1", features = ["serde"] } lazy_static = "1" miniz_oxide = "^0.7" mmap-rs = { version = "^0.6", optional = true } @@ -19,7 +20,7 @@ pathdiff = "^0.2" regex = "1" serde = { version = "1", features = ["derive"] } serde_json = "1" -serde_with = "3" +serde_with = { version = "3", features = ["indexmap_2"] } thiserror = "1" [features] diff --git a/data/edge_case_manifest_state.json b/data/edge_case_manifest_state.json new file mode 100644 index 0000000..6b37bda --- /dev/null +++ b/data/edge_case_manifest_state.json @@ -0,0 +1,117 @@ +{ + "__info": [ + "This file is automatically generated. Do not touch it, or risk", + "your modifications being lost." + ], + "dependencyTreeRoots": [ + { + "name": "rspack-link", + "reference": "workspace:." + } + ], + "enableTopLevelFallback": true, + "ignorePatternData": "(^(?:\\.yarn\\/sdks(?:\\/(?!\\.{1,2}(?:\\/|$))(?:(?:(?!(?:^|\\/)\\.{1,2}(?:\\/|$)).)*?)|$))$)", + "fallbackExclusionList": [ + [ + "rspack-link", + [ + "workspace:." + ] + ] + ], + "fallbackPool": [], + "packageRegistryData": [ + [ + null, + [ + [ + null, + { + "packageLocation": "./", + "packageDependencies": [ + ], + "linkType": "SOFT" + } + ] + ] + ], + + [ + "@carbon/icon-helpers", + [ + [ + "npm:10.54.0", + { + "packageLocation": "./.yarn/unplugged/@carbon-icon-helpers-npm-10.54.0-a58f8b7b6c/node_modules/@carbon/icon-helpers/", + "packageDependencies": [ + [ + "@carbon/icon-helpers", + "npm:10.54.0" + ], + [ + "@ibm/telemetry-js", + "npm:1.9.1" + ] + ], + "linkType": "HARD" + } + ] + ] + ], + [ + "@carbon/icons-react", + [ + [ + "npm:11.54.0", + { + "packageLocation": "./.yarn/unplugged/@carbon-icons-react-virtual-379302d360/node_modules/@carbon/icons-react/", + "packageDependencies": [ + [ + "@carbon/icons-react", + "npm:11.54.0" + ] + ], + "linkType": "SOFT" + } + ], + [ + "virtual:ed977161de61e6995bdb8c18ad719dac99ebc9dc1b7317c42e54ab394643509c7ea342abb2b214efc589efcb79dc9deae3ca4092870cbe691d6377887658443c#npm:11.54.0", + { + "packageLocation": "./.yarn/unplugged/@carbon-icons-react-virtual-379302d360/node_modules/@carbon/icons-react/", + "packageDependencies": [ + [ + "@carbon/icons-react", + "virtual:ed977161de61e6995bdb8c18ad719dac99ebc9dc1b7317c42e54ab394643509c7ea342abb2b214efc589efcb79dc9deae3ca4092870cbe691d6377887658443c#npm:11.54.0" + ], + [ + "@carbon/icon-helpers", + "npm:10.54.0" + ], + [ + "@ibm/telemetry-js", + "npm:1.9.1" + ], + [ + "@types/react", + null + ], + [ + "prop-types", + "npm:15.8.1" + ], + [ + "react", + "npm:19.0.0" + ] + ], + "packagePeers": [ + "@types/react", + "react" + ], + "linkType": "HARD" + } + ] + ] + ] + ] +} diff --git a/src/lib.rs b/src/lib.rs index 0751287..7571799 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ mod util; mod zip; use fancy_regex::Regex; +use indexmap::IndexMap; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DefaultOnNull}; @@ -164,7 +165,7 @@ pub struct Manifest { // }] // ] #[serde_as(as = "Vec<(DefaultOnNull<_>, Vec<(DefaultOnNull<_>, _)>)>")] - package_registry_data: HashMap>, + package_registry_data: HashMap>, } pub fn parse_bare_identifier(specifier: &str) -> Result<(String, Option), Error> { @@ -184,7 +185,7 @@ pub fn parse_bare_identifier(specifier: &str) -> Result<(String, Option) if let Some(ident) = ident_option { Ok((ident, segments.next().map(|v| v.to_string()))) } else { - Err(Error::BadSpecifier{ + Err(Error::BadSpecifier { message: String::from("Invalid specifier"), specifier: specifier.to_string(), }) diff --git a/src/lib_tests.rs b/src/lib_tests.rs index bed50e3..7aa4701 100644 --- a/src/lib_tests.rs +++ b/src/lib_tests.rs @@ -1,6 +1,6 @@ use serde::Deserialize; -use crate::{ResolutionConfig, Resolution, Manifest}; +use crate::{Manifest, Resolution, ResolutionConfig}; #[derive(Deserialize)] struct Test { @@ -20,8 +20,11 @@ struct TestSuite { mod tests { use std::{fs, path::PathBuf}; - use crate::{init_pnp_manifest, load_pnp_manifest, resolve_to_unqualified, ResolutionHost}; use super::*; + use crate::{ + init_pnp_manifest, load_pnp_manifest, resolve_to_unqualified, + resolve_to_unqualified_via_manifest, ResolutionHost, + }; #[test] fn example() { @@ -119,4 +122,31 @@ mod tests { } } } + + #[test] + fn test_edge_case_one_pkg_cached_and_unplugged() { + let manifest = { + let manifest_json_path = std::env::current_dir().unwrap().join("./data/edge_case_manifest_state.json"); + let manifest_content = fs::read_to_string(&manifest_json_path).unwrap(); + let mut manifest = serde_json::from_str::(&manifest_content).unwrap(); + init_pnp_manifest(&mut manifest, manifest_json_path); + manifest + }; + + let issuer = std::env::current_dir().unwrap(). + join("data/.yarn/unplugged/@carbon-icons-react-virtual-379302d360/node_modules/@carbon/icons-react/es/"); + + let resolution = + resolve_to_unqualified_via_manifest(&manifest, "@carbon/icon-helpers", &issuer) + .unwrap(); + + match resolution { + Resolution::Resolved(resolved, _) => { + assert!(resolved.ends_with(".yarn/unplugged/@carbon-icon-helpers-npm-10.54.0-a58f8b7b6c/node_modules/@carbon/icon-helpers")) + } + _ => { + panic!("Unexpected resolve failed"); + } + } + } }