diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2023-04-06 18:46:44 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-06 18:46:44 -0400 |
commit | d07aa4a0723b04583b7cb1e09152457d866d13d3 (patch) | |
tree | f329a30becca95583fb71b4158c939c68228ce06 /cli/npm/resolution/common.rs | |
parent | 1586c52b5b5ad511ec0bf896e94de8585f743cf8 (diff) |
refactor(npm): use deno_npm and deno_semver (#18602)
Diffstat (limited to 'cli/npm/resolution/common.rs')
-rw-r--r-- | cli/npm/resolution/common.rs | 243 |
1 files changed, 0 insertions, 243 deletions
diff --git a/cli/npm/resolution/common.rs b/cli/npm/resolution/common.rs deleted file mode 100644 index eb3e51f7d..000000000 --- a/cli/npm/resolution/common.rs +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -use deno_core::anyhow::bail; -use deno_core::error::AnyError; -use deno_graph::semver::Version; -use deno_graph::semver::VersionReq; -use once_cell::sync::Lazy; - -use super::NpmPackageId; -use crate::npm::registry::NpmPackageInfo; -use crate::npm::registry::NpmPackageVersionInfo; - -pub static LATEST_VERSION_REQ: Lazy<VersionReq> = - Lazy::new(|| VersionReq::parse_from_specifier("latest").unwrap()); - -pub fn resolve_best_package_version_and_info<'info, 'version>( - version_req: &VersionReq, - package_info: &'info NpmPackageInfo, - existing_versions: impl Iterator<Item = &'version Version>, -) -> Result<VersionAndInfo<'info>, AnyError> { - if let Some(version) = resolve_best_from_existing_versions( - version_req, - package_info, - existing_versions, - )? { - match package_info.versions.get(&version.to_string()) { - Some(version_info) => Ok(VersionAndInfo { - version, - info: version_info, - }), - None => { - bail!( - "could not find version '{}' for '{}'", - version, - &package_info.name - ) - } - } - } else { - // get the information - get_resolved_package_version_and_info(version_req, package_info, None) - } -} - -#[derive(Clone)] -pub struct VersionAndInfo<'a> { - pub version: Version, - pub info: &'a NpmPackageVersionInfo, -} - -fn get_resolved_package_version_and_info<'a>( - version_req: &VersionReq, - info: &'a NpmPackageInfo, - parent: Option<&NpmPackageId>, -) -> Result<VersionAndInfo<'a>, AnyError> { - if let Some(tag) = version_req.tag() { - tag_to_version_info(info, tag, parent) - } else { - let mut maybe_best_version: Option<VersionAndInfo> = None; - for version_info in info.versions.values() { - let version = Version::parse_from_npm(&version_info.version)?; - if version_req.matches(&version) { - let is_best_version = maybe_best_version - .as_ref() - .map(|best_version| best_version.version.cmp(&version).is_lt()) - .unwrap_or(true); - if is_best_version { - maybe_best_version = Some(VersionAndInfo { - version, - info: version_info, - }); - } - } - } - - match maybe_best_version { - Some(v) => Ok(v), - // If the package isn't found, it likely means that the user needs to use - // `--reload` to get the latest npm package information. Although it seems - // like we could make this smart by fetching the latest information for - // this package here, we really need a full restart. There could be very - // interesting bugs that occur if this package's version was resolved by - // something previous using the old information, then now being smart here - // causes a new fetch of the package information, meaning this time the - // previous resolution of this package's version resolved to an older - // version, but next time to a different version because it has new information. - None => bail!( - concat!( - "Could not find npm package '{}' matching {}{}. ", - "Try retrieving the latest npm package information by running with --reload", - ), - info.name, - version_req.version_text(), - match parent { - Some(resolved_id) => format!(" as specified in {}", resolved_id.nv), - None => String::new(), - } - ), - } - } -} - -pub fn version_req_satisfies( - version_req: &VersionReq, - version: &Version, - package_info: &NpmPackageInfo, - parent: Option<&NpmPackageId>, -) -> Result<bool, AnyError> { - match version_req.tag() { - Some(tag) => { - let tag_version = tag_to_version_info(package_info, tag, parent)?.version; - Ok(tag_version == *version) - } - None => Ok(version_req.matches(version)), - } -} - -fn resolve_best_from_existing_versions<'a>( - version_req: &VersionReq, - package_info: &NpmPackageInfo, - existing_versions: impl Iterator<Item = &'a Version>, -) -> Result<Option<Version>, AnyError> { - let mut maybe_best_version: Option<&Version> = None; - for version in existing_versions { - if version_req_satisfies(version_req, version, package_info, None)? { - let is_best_version = maybe_best_version - .as_ref() - .map(|best_version| (*best_version).cmp(version).is_lt()) - .unwrap_or(true); - if is_best_version { - maybe_best_version = Some(version); - } - } - } - Ok(maybe_best_version.cloned()) -} - -fn tag_to_version_info<'a>( - info: &'a NpmPackageInfo, - tag: &str, - parent: Option<&NpmPackageId>, -) -> Result<VersionAndInfo<'a>, AnyError> { - // For when someone just specifies @types/node, we want to pull in a - // "known good" version of @types/node that works well with Deno and - // not necessarily the latest version. For example, we might only be - // compatible with Node vX, but then Node vY is published so we wouldn't - // want to pull that in. - // Note: If the user doesn't want this behavior, then they can specify an - // explicit version. - if tag == "latest" && info.name == "@types/node" { - return get_resolved_package_version_and_info( - // WARNING: When bumping this version, check if anything needs to be - // updated in the `setNodeOnlyGlobalNames` call in 99_main_compiler.js - &VersionReq::parse_from_npm("18.0.0 - 18.11.18").unwrap(), - info, - parent, - ); - } - - if let Some(version) = info.dist_tags.get(tag) { - match info.versions.get(version) { - Some(info) => Ok(VersionAndInfo { - version: Version::parse_from_npm(version)?, - info, - }), - None => { - bail!( - "Could not find version '{}' referenced in dist-tag '{}'.", - version, - tag, - ) - } - } - } else { - bail!("Could not find dist-tag '{}'.", tag) - } -} - -#[cfg(test)] -mod test { - use std::collections::HashMap; - - use deno_graph::npm::NpmPackageReqReference; - - use super::*; - - #[test] - fn test_get_resolved_package_version_and_info() { - // dist tag where version doesn't exist - let package_ref = NpmPackageReqReference::from_str("npm:test").unwrap(); - let package_info = NpmPackageInfo { - name: "test".to_string(), - versions: HashMap::new(), - dist_tags: HashMap::from([( - "latest".to_string(), - "1.0.0-alpha".to_string(), - )]), - }; - let result = get_resolved_package_version_and_info( - package_ref - .req - .version_req - .as_ref() - .unwrap_or(&*LATEST_VERSION_REQ), - &package_info, - None, - ); - assert_eq!( - result.err().unwrap().to_string(), - "Could not find version '1.0.0-alpha' referenced in dist-tag 'latest'." - ); - - // dist tag where version is a pre-release - let package_ref = NpmPackageReqReference::from_str("npm:test").unwrap(); - let package_info = NpmPackageInfo { - name: "test".to_string(), - versions: HashMap::from([ - ("0.1.0".to_string(), NpmPackageVersionInfo::default()), - ( - "1.0.0-alpha".to_string(), - NpmPackageVersionInfo { - version: "0.1.0-alpha".to_string(), - ..Default::default() - }, - ), - ]), - dist_tags: HashMap::from([( - "latest".to_string(), - "1.0.0-alpha".to_string(), - )]), - }; - let result = get_resolved_package_version_and_info( - package_ref - .req - .version_req - .as_ref() - .unwrap_or(&*LATEST_VERSION_REQ), - &package_info, - None, - ); - assert_eq!(result.unwrap().version.to_string(), "1.0.0-alpha"); - } -} |