From 360dbe199fd15b74cebea94014d8bd6aa6296356 Mon Sep 17 00:00:00 2001 From: Sebastian Schuberth Date: Mon, 22 Jan 2024 18:09:15 +0100 Subject: [PATCH] fix(node): Do not follow cyclic directory links This implements a proper solution for the `maxDepth`-related work-around introduced for PNPM in 18d8903 to fix a similar issue for Yarn if the `node_modules` directory hierarchy contains cyclic links. This is done by maintaining a temporary set of visited "real" directories. The issue was interesting to debug as the infinite loop caused by circular links was only triggered when actually evaluating the lazy sequence created by `File.walk()`. Fixes #6531. Signed-off-by: Sebastian Schuberth --- plugins/package-managers/node/src/main/kotlin/Npm.kt | 12 +++++------- .../package-managers/node/src/main/kotlin/Pnpm.kt | 7 ------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/plugins/package-managers/node/src/main/kotlin/Npm.kt b/plugins/package-managers/node/src/main/kotlin/Npm.kt index 6c6aedce9ace1..36b14f53219c1 100644 --- a/plugins/package-managers/node/src/main/kotlin/Npm.kt +++ b/plugins/package-managers/node/src/main/kotlin/Npm.kt @@ -129,12 +129,6 @@ open class Npm( private val npmViewCache = ConcurrentHashMap>() - /** - * Search depth in the `node_modules` directory for `package.json` files used for collecting all packages of the - * projects. - */ - protected open val modulesSearchDepth = Int.MAX_VALUE - protected open fun hasLockFile(projectDir: File) = NodePackageManager.NPM.hasLockFile(projectDir) /** @@ -246,7 +240,11 @@ open class Npm( logger.info { "Searching for 'package.json' files in '$nodeModulesDir'..." } - val nodeModulesFiles = nodeModulesDir.walk().maxDepth(modulesSearchDepth).filter { + val visitedDirs = mutableSetOf() + + val nodeModulesFiles = nodeModulesDir.walk().onEnter { dir -> + !dir.isSymbolicLink() || visitedDirs.add(dir.realFile()) + }.filter { it.isFile && it.name == "package.json" && isValidNodeModulesDirectory(nodeModulesDir, nodeModulesDirForPackageJson(it)) } diff --git a/plugins/package-managers/node/src/main/kotlin/Pnpm.kt b/plugins/package-managers/node/src/main/kotlin/Pnpm.kt index d96eac586ff1a..9f77bae6611db 100644 --- a/plugins/package-managers/node/src/main/kotlin/Pnpm.kt +++ b/plugins/package-managers/node/src/main/kotlin/Pnpm.kt @@ -51,13 +51,6 @@ class Pnpm( ) = Pnpm(type, analysisRoot, analyzerConfig, repoConfig) } - /** - * PNPM symlinks workspace modules in the `node_modules` directory, which will result in cyclic symlinks of - * `node_module` directories. Limit the search depth to '2' in this case as all packages are in a direct - * subdirectory of the `node_modules` directory, thanks to the `--shamefully-hoist` install option. - */ - override val modulesSearchDepth = 2 - override fun hasLockFile(projectDir: File) = NodePackageManager.PNPM.hasLockFile(projectDir) override fun File.isWorkspaceDir() = realFile() in findWorkspaceSubmodules(analysisRoot)