diff options
Diffstat (limited to 'cli/npm/resolvers')
-rw-r--r-- | cli/npm/resolvers/common.rs | 52 | ||||
-rw-r--r-- | cli/npm/resolvers/local.rs | 63 |
2 files changed, 70 insertions, 45 deletions
diff --git a/cli/npm/resolvers/common.rs b/cli/npm/resolvers/common.rs index cc590e2ad..508b783c9 100644 --- a/cli/npm/resolvers/common.rs +++ b/cli/npm/resolvers/common.rs @@ -5,7 +5,6 @@ use std::path::Path; use std::path::PathBuf; use deno_ast::ModuleSpecifier; -use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::futures; use deno_core::futures::future::BoxFuture; @@ -48,40 +47,41 @@ pub async fn cache_packages( cache: &NpmCache, registry_url: &Url, ) -> Result<(), AnyError> { - if std::env::var("DENO_UNSTABLE_NPM_SYNC_DOWNLOAD") == Ok("1".to_string()) { - // for some of the tests, we want downloading of packages - // to be deterministic so that the output is always the same + let sync_download = should_sync_download(); + if sync_download { + // we're running the tests not with --quiet + // and we want the output to be deterministic packages.sort_by(|a, b| a.id.cmp(&b.id)); - for package in packages { + } + let mut handles = Vec::with_capacity(packages.len()); + for package in packages { + let cache = cache.clone(); + let registry_url = registry_url.clone(); + let handle = tokio::task::spawn(async move { cache - .ensure_package(&package.id, &package.dist, registry_url) + .ensure_package(&package.id, &package.dist, ®istry_url) .await - .with_context(|| { - format!("Failed caching npm package '{}'.", package.id) - })?; - } - } else { - let handles = packages.into_iter().map(|package| { - let cache = cache.clone(); - let registry_url = registry_url.clone(); - tokio::task::spawn(async move { - cache - .ensure_package(&package.id, &package.dist, ®istry_url) - .await - .with_context(|| { - format!("Failed caching npm package '{}'.", package.id) - }) - }) }); - let results = futures::future::join_all(handles).await; - for result in results { - // surface the first error - result??; + if sync_download { + handle.await??; + } else { + handles.push(handle); } } + let results = futures::future::join_all(handles).await; + for result in results { + // surface the first error + result??; + } Ok(()) } +/// For some of the tests, we want downloading of packages +/// to be deterministic so that the output is always the same +pub fn should_sync_download() -> bool { + std::env::var("DENO_UNSTABLE_NPM_SYNC_DOWNLOAD") == Ok("1".to_string()) +} + pub fn ensure_registry_read_permission( registry_path: &Path, path: &Path, diff --git a/cli/npm/resolvers/local.rs b/cli/npm/resolvers/local.rs index d92ffb84d..35223f1aa 100644 --- a/cli/npm/resolvers/local.rs +++ b/cli/npm/resolvers/local.rs @@ -16,16 +16,18 @@ use deno_core::error::AnyError; use deno_core::futures::future::BoxFuture; use deno_core::futures::FutureExt; use deno_core::url::Url; +use deno_runtime::deno_core::futures; +use tokio::task::JoinHandle; use crate::fs_util; use crate::npm::resolution::NpmResolution; use crate::npm::resolution::NpmResolutionSnapshot; +use crate::npm::resolvers::common::should_sync_download; use crate::npm::NpmCache; use crate::npm::NpmPackageId; use crate::npm::NpmPackageReq; use crate::npm::NpmRegistryApi; -use super::common::cache_packages; use super::common::ensure_registry_read_permission; use super::common::InnerNpmPackageResolver; @@ -161,19 +163,14 @@ impl InnerNpmPackageResolver for LocalNpmPackageResolver { let resolver = self.clone(); async move { resolver.resolution.add_package_reqs(packages).await?; - cache_packages( - resolver.resolution.all_packages(), - &resolver.cache, - &resolver.registry_url, - ) - .await?; sync_resolution_with_fs( &resolver.resolution.snapshot(), &resolver.cache, &resolver.registry_url, &resolver.root_node_modules_path, - )?; + ) + .await?; Ok(()) } @@ -186,7 +183,7 @@ impl InnerNpmPackageResolver for LocalNpmPackageResolver { } /// Creates a pnpm style folder structure. -fn sync_resolution_with_fs( +async fn sync_resolution_with_fs( snapshot: &NpmResolutionSnapshot, cache: &NpmCache, registry_url: &Url, @@ -205,24 +202,52 @@ fn sync_resolution_with_fs( // // Copy (hardlink in future) <global_registry_cache>/<package_id>/ to // node_modules/.deno/<package_id>/node_modules/<package_name> - let all_packages = snapshot.all_packages(); + let sync_download = should_sync_download(); + let mut all_packages = snapshot.all_packages(); + if sync_download { + // we're running the tests not with --quiet + // and we want the output to be deterministic + all_packages.sort_by(|a, b| a.id.cmp(&b.id)); + } + let mut handles: Vec<JoinHandle<Result<(), AnyError>>> = + Vec::with_capacity(all_packages.len()); for package in &all_packages { let folder_name = get_package_folder_name(&package.id); let folder_path = deno_local_registry_dir.join(&folder_name); let initialized_file = folder_path.join("deno_initialized"); if !initialized_file.exists() { - let sub_node_modules = folder_path.join("node_modules"); - let package_path = join_package_name(&sub_node_modules, &package.id.name); - fs::create_dir_all(&package_path) - .with_context(|| format!("Creating '{}'", folder_path.display()))?; - let cache_folder = cache.package_folder(&package.id, registry_url); - // for now copy, but in the future consider hard linking - fs_util::copy_dir_recursive(&cache_folder, &package_path)?; - // write out a file that indicates this folder has been initialized - fs::write(initialized_file, "")?; + let cache = cache.clone(); + let registry_url = registry_url.clone(); + let package = package.clone(); + let handle = tokio::task::spawn(async move { + cache + .ensure_package(&package.id, &package.dist, ®istry_url) + .await?; + let sub_node_modules = folder_path.join("node_modules"); + let package_path = + join_package_name(&sub_node_modules, &package.id.name); + fs::create_dir_all(&package_path) + .with_context(|| format!("Creating '{}'", folder_path.display()))?; + let cache_folder = cache.package_folder(&package.id, ®istry_url); + // for now copy, but in the future consider hard linking + fs_util::copy_dir_recursive(&cache_folder, &package_path)?; + // write out a file that indicates this folder has been initialized + fs::write(initialized_file, "")?; + Ok(()) + }); + if sync_download { + handle.await??; + } else { + handles.push(handle); + } } } + let results = futures::future::join_all(handles).await; + for result in results { + result??; // surface the first error + } + // 2. Symlink all the dependencies into the .deno directory. // // Symlink node_modules/.deno/<package_id>/node_modules/<dep_name> to |