summaryrefslogtreecommitdiff
path: root/cli/npm/managed
diff options
context:
space:
mode:
authorNathan Whitaker <17734409+nathanwhit@users.noreply.github.com>2024-07-11 11:39:45 -0700
committerGitHub <noreply@github.com>2024-07-11 18:39:45 +0000
commit3d0e1b65b1e1a754f6440fff1df873da8b2144a1 (patch)
tree240dac83d5c5e58d70cfb8b414becc9029cce3b6 /cli/npm/managed
parentba63740e7f390a5778baf01ba156f0b02c55a089 (diff)
fix(node): Ignore broken default install scripts (#24534)
NPM inserts a default install script when a package has a `binding.gyp` file. It's possible, however, for the package to exclude the `binding.gyp` file when they publish, and in this case the install script will never succeed for a user of the package. This happens with `fsevents`, for instance. They don't include the `binding.gyp` file in their published tarball, but the default install script appears in the manifest served by `npm`. This causes us to warn that `fsevents` has an install script, but when you try to run it it fails due to `binding.gyp` not existing.
Diffstat (limited to 'cli/npm/managed')
-rw-r--r--cli/npm/managed/resolvers/local.rs32
1 files changed, 26 insertions, 6 deletions
diff --git a/cli/npm/managed/resolvers/local.rs b/cli/npm/managed/resolvers/local.rs
index 90b0ed7be..2c6d9ca42 100644
--- a/cli/npm/managed/resolvers/local.rs
+++ b/cli/npm/managed/resolvers/local.rs
@@ -384,9 +384,24 @@ fn can_run_scripts(
}
}
-fn has_lifecycle_scripts(package: &NpmResolutionPackage) -> bool {
+// npm defaults to running `node-gyp rebuild` if there is a `binding.gyp` file
+// but it always fails if the package excludes the `binding.gyp` file when they publish.
+// (for example, `fsevents` hits this)
+fn is_broken_default_install_script(script: &str, package_path: &Path) -> bool {
+ script == "node-gyp rebuild" && !package_path.join("binding.gyp").exists()
+}
+
+fn has_lifecycle_scripts(
+ package: &NpmResolutionPackage,
+ package_path: &Path,
+) -> bool {
+ if let Some(install) = package.scripts.get("install") {
+ // default script
+ if !is_broken_default_install_script(install, package_path) {
+ return true;
+ }
+ }
package.scripts.contains_key("preinstall")
- || package.scripts.contains_key("install")
|| package.scripts.contains_key("postinstall")
}
@@ -504,14 +519,14 @@ async fn sync_resolution_with_fs(
});
}
- if has_lifecycle_scripts(package) {
+ let sub_node_modules = folder_path.join("node_modules");
+ let package_path =
+ join_package_name(&sub_node_modules, &package.id.nv.name);
+ if has_lifecycle_scripts(package, &package_path) {
let scripts_run = folder_path.join(".scripts-run");
let has_warned = folder_path.join(".scripts-warned");
if can_run_scripts(&lifecycle_scripts.allowed, &package.id.nv) {
if !scripts_run.exists() {
- let sub_node_modules = folder_path.join("node_modules");
- let package_path =
- join_package_name(&sub_node_modules, &package.id.nv.name);
packages_with_scripts.push((
package.clone(),
package_path,
@@ -685,6 +700,11 @@ async fn sync_resolution_with_fs(
)?;
for script_name in ["preinstall", "install", "postinstall"] {
if let Some(script) = package.scripts.get(script_name) {
+ if script_name == "install"
+ && is_broken_default_install_script(script, &package_path)
+ {
+ continue;
+ }
let exit_code =
crate::task_runner::run_task(crate::task_runner::RunTaskOptions {
task_name: script_name,