From 92c629887af79da0cdc92b3a3749b5ddb1ae1d1e Mon Sep 17 00:00:00 2001 From: Steven Petryk Date: Mon, 19 Aug 2024 12:58:10 -0700 Subject: [PATCH] fix: avoid recreating existing, valid symlinks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a somewhat lazy approach to fixing an issue where pnpm regenerates symlinks, even if the existing symlink is perfectly fine. This behavior (of clobbering valid symlinks) can have adverse downstream effects, like triggering watchers and invalidating caches (the mtime changes). This is not the ideal solution, because it incurs the cost of a failed `readlink` if the symlink does _not_ currently exist (which is always the case in a fresh pnpm install, and _sometimes_ the case in a pnpm install that needs to move things around). But in the happy case—when the node_modules are already mostly correct, at Discord, we saw a 0.2-0.5s speedup in `pnpm install`. So I think it's worth doing this, and then considering this function more holistically if we find time. --- src/index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/index.ts b/src/index.ts index 728f892..1a43ed5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -42,6 +42,15 @@ async function forceSymlink ( renameTried?: boolean } ): Promise<{ reused: boolean, warn?: string }> { + // The happy path: the symlink already exists, and is correct (which is true + // in most already-initialized projects). + try { + const actualPath = await fs.readlink(path) + if (actualPath === target) { + return { reused: true } + } + } catch (e) { /* logic below handles all other cases */ } + try { await fs.symlink(target, path, symlinkType) return { reused: false }