diff options
Diffstat (limited to 'cli/args/lockfile.rs')
-rw-r--r-- | cli/args/lockfile.rs | 100 |
1 files changed, 78 insertions, 22 deletions
diff --git a/cli/args/lockfile.rs b/cli/args/lockfile.rs index 1a3233c5a..31519aee3 100644 --- a/cli/args/lockfile.rs +++ b/cli/args/lockfile.rs @@ -1,18 +1,30 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; + +use std::collections::HashMap; use std::path::PathBuf; +use std::sync::Arc; + +use deno_core::anyhow::bail; +use deno_core::anyhow::Context; +use deno_core::error::AnyError; +use deno_core::futures::stream::FuturesOrdered; +use deno_core::futures::StreamExt; +use deno_core::parking_lot::Mutex; +use deno_npm::registry::NpmRegistryApi; +use deno_npm::resolution::NpmResolutionSnapshot; +use deno_npm::resolution::NpmResolutionSnapshotCreateOptions; +use deno_npm::resolution::NpmResolutionSnapshotCreateOptionsPackage; +use deno_npm::NpmPackageId; +use deno_semver::npm::NpmPackageReq; use crate::args::config_file::LockConfig; use crate::args::ConfigFile; -use crate::npm::NpmResolutionPackage; use crate::Flags; use super::DenoSubcommand; pub use deno_lockfile::Lockfile; pub use deno_lockfile::LockfileError; -use deno_lockfile::NpmPackageDependencyLockfileInfo; -use deno_lockfile::NpmPackageLockfileInfo; pub fn discover( flags: &Flags, @@ -61,24 +73,68 @@ pub fn discover( Ok(Some(lockfile)) } -// NOTE(bartlomieju): we don't want a reverse mapping to be possible. -#[allow(clippy::from_over_into)] -impl Into<NpmPackageLockfileInfo> for NpmResolutionPackage { - fn into(self) -> NpmPackageLockfileInfo { - let dependencies = self - .dependencies - .into_iter() - .map(|(name, id)| NpmPackageDependencyLockfileInfo { - name, - id: id.as_serialized(), - }) - .collect(); - - NpmPackageLockfileInfo { - display_id: self.pkg_id.nv.to_string(), - serialized_id: self.pkg_id.as_serialized(), - integrity: self.dist.integrity().to_string(), - dependencies, +pub async fn snapshot_from_lockfile( + lockfile: Arc<Mutex<Lockfile>>, + api: &dyn NpmRegistryApi, +) -> Result<NpmResolutionSnapshot, AnyError> { + let (root_packages, mut packages) = { + let lockfile = lockfile.lock(); + + let mut root_packages = + HashMap::<NpmPackageReq, NpmPackageId>::with_capacity( + lockfile.content.npm.specifiers.len(), + ); + // collect the specifiers to version mappings + for (key, value) in &lockfile.content.npm.specifiers { + let package_req = NpmPackageReq::from_str(key) + .with_context(|| format!("Unable to parse npm specifier: {key}"))?; + let package_id = NpmPackageId::from_serialized(value)?; + root_packages.insert(package_req, package_id.clone()); + } + + // now fill the packages except for the dist information + let mut packages = Vec::with_capacity(lockfile.content.npm.packages.len()); + for (key, package) in &lockfile.content.npm.packages { + let pkg_id = NpmPackageId::from_serialized(key)?; + + // collect the dependencies + let mut dependencies = HashMap::with_capacity(package.dependencies.len()); + for (name, specifier) in &package.dependencies { + let dep_id = NpmPackageId::from_serialized(specifier)?; + dependencies.insert(name.clone(), dep_id); + } + + packages.push(NpmResolutionSnapshotCreateOptionsPackage { + pkg_id, + dist: Default::default(), // temporarily empty + dependencies, + }); } + (root_packages, packages) + }; + + // now that the lockfile is dropped, fetch the package version information + let mut version_infos = + FuturesOrdered::from_iter(packages.iter().map(|p| p.pkg_id.nv.clone()).map( + |nv| async move { + match api.package_version_info(&nv).await? { + Some(version_info) => Ok(version_info), + None => { + bail!("could not find '{}' specified in the lockfile. Maybe try again with --reload", nv); + } + } + }, + )); + + let mut i = 0; + while let Some(version_info) = version_infos.next().await { + packages[i].dist = version_info?.dist; + i += 1; } + + NpmResolutionSnapshot::from_packages(NpmResolutionSnapshotCreateOptions { + packages, + root_packages, + }) + .context("The lockfile is corrupt. You can recreate it with --lock-write") } |