diff options
Diffstat (limited to 'cli/npm/resolvers')
-rw-r--r-- | cli/npm/resolvers/common.rs | 6 | ||||
-rw-r--r-- | cli/npm/resolvers/global.rs | 11 | ||||
-rw-r--r-- | cli/npm/resolvers/local.rs | 79 | ||||
-rw-r--r-- | cli/npm/resolvers/mod.rs | 15 |
4 files changed, 109 insertions, 2 deletions
diff --git a/cli/npm/resolvers/common.rs b/cli/npm/resolvers/common.rs index e0705f12b..e8acc5c3a 100644 --- a/cli/npm/resolvers/common.rs +++ b/cli/npm/resolvers/common.rs @@ -13,6 +13,7 @@ use deno_core::error::AnyError; use deno_core::futures; use deno_core::task::spawn; use deno_core::url::Url; +use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; use deno_npm::NpmResolutionPackage; use deno_runtime::deno_fs::FileSystem; @@ -47,6 +48,11 @@ pub trait NpmPackageFsResolver: Send + Sync { specifier: &ModuleSpecifier, ) -> Result<PathBuf, AnyError>; + fn resolve_package_cache_folder_id_from_specifier( + &self, + specifier: &ModuleSpecifier, + ) -> Result<NpmPackageCacheFolderId, AnyError>; + async fn cache_packages(&self) -> Result<(), AnyError>; fn ensure_read_permission( diff --git a/cli/npm/resolvers/global.rs b/cli/npm/resolvers/global.rs index ca84d7e8b..d1962ff04 100644 --- a/cli/npm/resolvers/global.rs +++ b/cli/npm/resolvers/global.rs @@ -82,7 +82,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { fn package_folder(&self, id: &NpmPackageId) -> Result<PathBuf, AnyError> { let folder_id = self .resolution - .resolve_package_cache_folder_id_from_id(id) + .resolve_pkg_cache_folder_id_from_pkg_id(id) .unwrap(); Ok( self @@ -131,6 +131,15 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { ) } + fn resolve_package_cache_folder_id_from_specifier( + &self, + specifier: &ModuleSpecifier, + ) -> Result<NpmPackageCacheFolderId, AnyError> { + self + .cache + .resolve_package_folder_id_from_specifier(specifier, &self.registry_url) + } + async fn cache_packages(&self) -> Result<(), AnyError> { let package_partitions = self .resolution diff --git a/cli/npm/resolvers/local.rs b/cli/npm/resolvers/local.rs index 976038404..670f41480 100644 --- a/cli/npm/resolvers/local.rs +++ b/cli/npm/resolvers/local.rs @@ -11,6 +11,7 @@ use std::path::Path; use std::path::PathBuf; use std::sync::Arc; +use crate::npm::cache::mixed_case_package_name_decode; use crate::util::fs::symlink_dir; use crate::util::fs::LaxSingleProcessFsFlag; use crate::util::progress_bar::ProgressBar; @@ -33,6 +34,7 @@ use deno_runtime::deno_fs; use deno_runtime::deno_node::NodePermissions; use deno_runtime::deno_node::NodeResolutionMode; use deno_runtime::deno_node::PackageJson; +use deno_semver::npm::NpmPackageNv; use crate::npm::cache::mixed_case_package_name_encode; use crate::npm::cache::should_sync_download; @@ -137,7 +139,7 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver { } fn package_folder(&self, id: &NpmPackageId) -> Result<PathBuf, AnyError> { - match self.resolution.resolve_package_cache_folder_id_from_id(id) { + match self.resolution.resolve_pkg_cache_folder_id_from_pkg_id(id) { // package is stored at: // node_modules/.deno/<package_cache_folder_id_folder_name>/node_modules/<package_name> Some(cache_folder_id) => Ok( @@ -215,6 +217,18 @@ impl NpmPackageFsResolver for LocalNpmPackageResolver { Ok(package_root_path) } + fn resolve_package_cache_folder_id_from_specifier( + &self, + specifier: &ModuleSpecifier, + ) -> Result<NpmPackageCacheFolderId, AnyError> { + let folder_path = self.resolve_package_folder_from_specifier(specifier)?; + let folder_name = folder_path.parent().unwrap().to_string_lossy(); + match get_package_folder_id_from_folder_name(&folder_name) { + Some(package_folder_id) => Ok(package_folder_id), + None => bail!("could not resolve package from specifier '{}'", specifier), + } + } + async fn cache_packages(&self) -> Result<(), AnyError> { sync_resolution_with_fs( &self.resolution.snapshot(), @@ -471,6 +485,30 @@ fn get_package_folder_id_folder_name( format!("{}@{}{}", name, nv.version, copy_str).replace('/', "+") } +fn get_package_folder_id_from_folder_name( + folder_name: &str, +) -> Option<NpmPackageCacheFolderId> { + let folder_name = folder_name.replace('+', "/"); + let (name, ending) = folder_name.rsplit_once('@')?; + let name = if let Some(encoded_name) = name.strip_prefix('_') { + mixed_case_package_name_decode(encoded_name)? + } else { + name.to_string() + }; + let (raw_version, copy_index) = match ending.split_once('_') { + Some((raw_version, copy_index)) => { + let copy_index = copy_index.parse::<u8>().ok()?; + (raw_version, copy_index) + } + None => (ending, 0), + }; + let version = deno_semver::Version::parse_from_npm(raw_version).ok()?; + Some(NpmPackageCacheFolderId { + nv: NpmPackageNv { name, version }, + copy_index, + }) +} + fn symlink_package_dir( old_path: &Path, new_path: &Path, @@ -531,3 +569,42 @@ fn join_package_name(path: &Path, package_name: &str) -> PathBuf { } path } + +#[cfg(test)] +mod test { + use deno_npm::NpmPackageCacheFolderId; + use deno_semver::npm::NpmPackageNv; + + use super::*; + + #[test] + fn test_get_package_folder_id_folder_name() { + let cases = vec![ + ( + NpmPackageCacheFolderId { + nv: NpmPackageNv { + name: "@types/foo".to_string(), + version: deno_semver::Version::parse_standard("1.2.3").unwrap(), + }, + copy_index: 1, + }, + "@types+foo@1.2.3_1".to_string(), + ), + ( + NpmPackageCacheFolderId { + nv: NpmPackageNv { + name: "JSON".to_string(), + version: deno_semver::Version::parse_standard("3.2.1").unwrap(), + }, + copy_index: 0, + }, + "_jjju6tq@3.2.1".to_string(), + ), + ]; + for (input, output) in cases { + assert_eq!(get_package_folder_id_folder_name(&input), output); + let folder_id = get_package_folder_id_from_folder_name(&output).unwrap(); + assert_eq!(folder_id, input); + } + } +} diff --git a/cli/npm/resolvers/mod.rs b/cli/npm/resolvers/mod.rs index abfe668c3..39fcba3fc 100644 --- a/cli/npm/resolvers/mod.rs +++ b/cli/npm/resolvers/mod.rs @@ -143,6 +143,21 @@ impl CliNpmResolver { Ok(path) } + /// Resolves the package nv from the provided specifier. + pub fn resolve_package_id_from_specifier( + &self, + specifier: &ModuleSpecifier, + ) -> Result<NpmPackageId, AnyError> { + let cache_folder_id = self + .fs_resolver + .resolve_package_cache_folder_id_from_specifier(specifier)?; + Ok( + self + .resolution + .resolve_pkg_id_from_pkg_cache_folder_id(&cache_folder_id)?, + ) + } + /// Attempts to get the package size in bytes. pub fn package_size( &self, |