diff options
author | Nathan Whitaker <17734409+nathanwhit@users.noreply.github.com> | 2024-09-24 12:23:57 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-24 19:23:57 +0000 |
commit | 36ebc03f177cc7db5deb93f4d403cafbed756eb5 (patch) | |
tree | c36af6c9b7093d3191de3cd6e60c4ce9dca4151a /cli/npm/managed/resolvers/global.rs | |
parent | ba5b8d0213cde2585236098b00beb8a512889626 (diff) |
fix(cli): Warn on not-run lifecycle scripts with global cache (#25786)
Refactors the lifecycle scripts code to extract out the common
functionality and then uses that to provide a warning in the global
resolver.
While ideally we would still support them with the global cache, for now
a warning is at least better than the status quo (where people are
unaware why their packages aren't working).
Diffstat (limited to 'cli/npm/managed/resolvers/global.rs')
-rw-r--r-- | cli/npm/managed/resolvers/global.rs | 100 |
1 files changed, 98 insertions, 2 deletions
diff --git a/cli/npm/managed/resolvers/global.rs b/cli/npm/managed/resolvers/global.rs index 7f8f285f3..187e6b277 100644 --- a/cli/npm/managed/resolvers/global.rs +++ b/cli/npm/managed/resolvers/global.rs @@ -2,16 +2,19 @@ //! Code for global npm cache resolution. +use std::borrow::Cow; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; +use crate::colors; use async_trait::async_trait; use deno_ast::ModuleSpecifier; use deno_core::error::AnyError; use deno_core::url::Url; use deno_npm::NpmPackageCacheFolderId; use deno_npm::NpmPackageId; +use deno_npm::NpmResolutionPackage; use deno_npm::NpmSystemInfo; use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_node::NodePermissions; @@ -19,10 +22,14 @@ use node_resolver::errors::PackageFolderResolveError; use node_resolver::errors::PackageNotFoundError; use node_resolver::errors::ReferrerNotFoundError; +use crate::args::LifecycleScriptsConfig; +use crate::cache::FastInsecureHasher; + use super::super::cache::NpmCache; use super::super::cache::TarballCache; use super::super::resolution::NpmResolution; use super::common::cache_packages; +use super::common::lifecycle_scripts::LifecycleScriptsStrategy; use super::common::NpmPackageFsResolver; use super::common::RegistryReadPermissionChecker; @@ -34,6 +41,7 @@ pub struct GlobalNpmPackageResolver { resolution: Arc<NpmResolution>, system_info: NpmSystemInfo, registry_read_permission_checker: RegistryReadPermissionChecker, + lifecycle_scripts: LifecycleScriptsConfig, } impl GlobalNpmPackageResolver { @@ -43,6 +51,7 @@ impl GlobalNpmPackageResolver { tarball_cache: Arc<TarballCache>, resolution: Arc<NpmResolution>, system_info: NpmSystemInfo, + lifecycle_scripts: LifecycleScriptsConfig, ) -> Self { Self { registry_read_permission_checker: RegistryReadPermissionChecker::new( @@ -53,6 +62,7 @@ impl GlobalNpmPackageResolver { tarball_cache, resolution, system_info, + lifecycle_scripts, } } } @@ -149,8 +159,7 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { let package_partitions = self .resolution .all_system_packages_partitioned(&self.system_info); - - cache_packages(package_partitions.packages, &self.tarball_cache).await?; + cache_packages(&package_partitions.packages, &self.tarball_cache).await?; // create the copy package folders for copy in package_partitions.copy_packages { @@ -159,6 +168,18 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { .ensure_copy_package(©.get_package_cache_folder_id())?; } + let mut lifecycle_scripts = + super::common::lifecycle_scripts::LifecycleScripts::new( + &self.lifecycle_scripts, + GlobalLifecycleScripts::new(self, &self.lifecycle_scripts.root_dir), + ); + for package in &package_partitions.packages { + let package_folder = self.cache.package_folder_for_nv(&package.id.nv); + lifecycle_scripts.add(package, Cow::Borrowed(&package_folder)); + } + + lifecycle_scripts.warn_not_run_scripts()?; + Ok(()) } @@ -172,3 +193,78 @@ impl NpmPackageFsResolver for GlobalNpmPackageResolver { .ensure_registry_read_permission(permissions, path) } } + +struct GlobalLifecycleScripts<'a> { + resolver: &'a GlobalNpmPackageResolver, + path_hash: u64, +} + +impl<'a> GlobalLifecycleScripts<'a> { + fn new(resolver: &'a GlobalNpmPackageResolver, root_dir: &Path) -> Self { + let mut hasher = FastInsecureHasher::new_without_deno_version(); + hasher.write(root_dir.to_string_lossy().as_bytes()); + let path_hash = hasher.finish(); + Self { + resolver, + path_hash, + } + } + + fn warned_scripts_file(&self, package: &NpmResolutionPackage) -> PathBuf { + self + .package_path(package) + .join(format!(".scripts-warned-{}", self.path_hash)) + } +} + +impl<'a> super::common::lifecycle_scripts::LifecycleScriptsStrategy + for GlobalLifecycleScripts<'a> +{ + fn can_run_scripts(&self) -> bool { + false + } + fn package_path(&self, package: &NpmResolutionPackage) -> PathBuf { + self.resolver.cache.package_folder_for_nv(&package.id.nv) + } + + fn warn_on_scripts_not_run( + &self, + packages: &[(&NpmResolutionPackage, PathBuf)], + ) -> std::result::Result<(), deno_core::anyhow::Error> { + log::warn!("{} The following packages contained npm lifecycle scripts ({}) that were not executed:", colors::yellow("Warning"), colors::gray("preinstall/install/postinstall")); + for (package, _) in packages { + log::warn!("┠─ {}", colors::gray(format!("npm:{}", package.id.nv))); + } + log::warn!("┃"); + log::warn!( + "┠─ {}", + colors::italic("This may cause the packages to not work correctly.") + ); + log::warn!("┠─ {}", colors::italic("Lifecycle scripts are only supported when using a `node_modules` directory.")); + log::warn!( + "┠─ {}", + colors::italic("Enable it in your deno config file:") + ); + log::warn!("┖─ {}", colors::bold("\"nodeModulesDir\": \"auto\"")); + + for (package, _) in packages { + std::fs::write(self.warned_scripts_file(package), "")?; + } + Ok(()) + } + + fn did_run_scripts( + &self, + _package: &NpmResolutionPackage, + ) -> std::result::Result<(), deno_core::anyhow::Error> { + Ok(()) + } + + fn has_warned(&self, package: &NpmResolutionPackage) -> bool { + self.warned_scripts_file(package).exists() + } + + fn has_run(&self, _package: &NpmResolutionPackage) -> bool { + false + } +} |