summaryrefslogtreecommitdiff
path: root/cli/npm/resolution.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/npm/resolution.rs')
-rw-r--r--cli/npm/resolution.rs118
1 files changed, 118 insertions, 0 deletions
diff --git a/cli/npm/resolution.rs b/cli/npm/resolution.rs
index 8656d8a3c..7cd4df124 100644
--- a/cli/npm/resolution.rs
+++ b/cli/npm/resolution.rs
@@ -11,9 +11,13 @@ use deno_core::anyhow::Context;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
use deno_core::futures;
+use deno_core::parking_lot::Mutex;
use deno_core::parking_lot::RwLock;
use serde::Deserialize;
use serde::Serialize;
+use std::sync::Arc;
+
+use crate::lockfile::Lockfile;
use super::cache::should_sync_download;
use super::registry::NpmPackageInfo;
@@ -172,6 +176,24 @@ impl NpmPackageId {
None
}
}
+
+ pub fn serialize_for_lock_file(&self) -> String {
+ format!("{}@{}", self.name, self.version)
+ }
+
+ pub fn deserialize_from_lock_file(id: &str) -> Result<Self, AnyError> {
+ let reference = NpmPackageReference::from_str(&format!("npm:{}", id))
+ .with_context(|| {
+ format!("Unable to deserialize npm package reference: {}", id)
+ })?;
+ let version =
+ NpmVersion::parse(&reference.req.version_req.unwrap().to_string())
+ .unwrap();
+ Ok(Self {
+ name: reference.req.name,
+ version,
+ })
+ }
}
impl std::fmt::Display for NpmPackageId {
@@ -345,6 +367,88 @@ impl NpmResolutionSnapshot {
}
maybe_best_version.cloned()
}
+
+ pub async fn from_lockfile(
+ lockfile: Arc<Mutex<Lockfile>>,
+ api: &NpmRegistryApi,
+ ) -> Result<Self, AnyError> {
+ let mut package_reqs = HashMap::new();
+ let mut packages_by_name: HashMap<String, Vec<NpmVersion>> = HashMap::new();
+ let mut packages = HashMap::new();
+
+ {
+ let lockfile = lockfile.lock();
+
+ for (key, value) in &lockfile.content.npm.specifiers {
+ let reference = NpmPackageReference::from_str(&format!("npm:{}", key))
+ .with_context(|| format!("Unable to parse npm specifier: {}", key))?;
+ let package_id = NpmPackageId::deserialize_from_lock_file(value)?;
+ package_reqs.insert(reference.req, package_id.version.clone());
+ }
+
+ for (key, value) in &lockfile.content.npm.packages {
+ let package_id = NpmPackageId::deserialize_from_lock_file(key)?;
+ let mut dependencies = HashMap::default();
+
+ for (name, specifier) in &value.dependencies {
+ dependencies.insert(
+ name.to_string(),
+ NpmPackageId::deserialize_from_lock_file(specifier)?,
+ );
+ }
+
+ for (name, id) in &dependencies {
+ packages_by_name
+ .entry(name.to_string())
+ .or_default()
+ .push(id.version.clone());
+ }
+
+ let package = NpmResolutionPackage {
+ id: package_id.clone(),
+ // temporary dummy value
+ dist: NpmPackageVersionDistInfo {
+ tarball: "foobar".to_string(),
+ shasum: "foobar".to_string(),
+ integrity: Some("foobar".to_string()),
+ },
+ dependencies,
+ };
+
+ packages.insert(package_id.clone(), package);
+ }
+ }
+
+ let mut unresolved_tasks = Vec::with_capacity(packages_by_name.len());
+
+ for package_id in packages.keys() {
+ let package_id = package_id.clone();
+ let api = api.clone();
+ unresolved_tasks.push(tokio::task::spawn(async move {
+ let info = api.package_info(&package_id.name).await?;
+ Result::<_, AnyError>::Ok((package_id, info))
+ }));
+ }
+ for result in futures::future::join_all(unresolved_tasks).await {
+ let (package_id, info) = result??;
+
+ let version_and_info = get_resolved_package_version_and_info(
+ &package_id.name,
+ &NpmVersionReq::parse(&package_id.version.to_string()).unwrap(),
+ info,
+ None,
+ )?;
+
+ let package = packages.get_mut(&package_id).unwrap();
+ package.dist = version_and_info.info.dist;
+ }
+
+ Ok(Self {
+ package_reqs,
+ packages_by_name,
+ packages,
+ })
+ }
}
pub struct NpmResolution {
@@ -628,6 +732,20 @@ impl NpmResolution {
pub fn snapshot(&self) -> NpmResolutionSnapshot {
self.snapshot.read().clone()
}
+
+ pub fn lock(
+ &self,
+ lockfile: &mut Lockfile,
+ snapshot: &NpmResolutionSnapshot,
+ ) -> Result<(), AnyError> {
+ for (package_req, version) in snapshot.package_reqs.iter() {
+ lockfile.insert_npm_specifier(package_req, version.to_string());
+ }
+ for package in self.all_packages() {
+ lockfile.check_or_insert_npm_package(&package)?;
+ }
+ Ok(())
+ }
}
#[derive(Clone)]