diff --git a/.changeset/moody-moose-fix.md b/.changeset/moody-moose-fix.md new file mode 100644 index 0000000000..17aa6ef2c8 --- /dev/null +++ b/.changeset/moody-moose-fix.md @@ -0,0 +1,5 @@ +--- +"@pnpm/headless": patch +--- + +Fixed a performance regression that was caused by [#3032](https://github.com/pnpm/pnpm/pull/3032). diff --git a/packages/headless/src/index.ts b/packages/headless/src/index.ts index 4f59a1ec09..7f6397101e 100644 --- a/packages/headless/src/index.ts +++ b/packages/headless/src/index.ts @@ -223,11 +223,6 @@ export default async (opts: HeadlessOptions) => { pnpmVersion: opts.currentEngine.pnpmVersion, } as LockfileToDepGraphOptions ) - if (filteredLockfile.packages) { - for (const skippedDepPath of Array.from(skipped)) { - delete filteredLockfile.packages[skippedDepPath] - } - } if (opts.enablePnp) { const importerNames = R.fromPairs( opts.projects.map(({ manifest, id }) => [id, manifest.name ?? id]) @@ -276,8 +271,15 @@ export default async (opts: HeadlessOptions) => { let newHoistedDependencies!: HoistedDependencies if (opts.hoistPattern != null || opts.publicHoistPattern != null) { + // It is important to keep the skipped packages in the lockfile which will be saved as the "current lockfile". + // pnpm is comparing the current lockfile to the wanted one and they should much. + // But for hoisting, we need a version of the lockfile w/o the skipped packages, so we're making a copy. + const hoistLockfile = { + ...filteredLockfile, + packages: R.omit(Array.from(skipped), filteredLockfile.packages), + } newHoistedDependencies = await hoist({ - lockfile: filteredLockfile, + lockfile: hoistLockfile, lockfileDir, privateHoistedModulesDir: hoistedModulesDir, privateHoistPattern: opts.hoistPattern ?? [], diff --git a/packages/supi/test/install/hoist.ts b/packages/supi/test/install/hoist.ts index 649e0b7cfe..90fdb89b00 100644 --- a/packages/supi/test/install/hoist.ts +++ b/packages/supi/test/install/hoist.ts @@ -502,7 +502,6 @@ test('should recreate node_modules with hoisting', async () => { test('hoisting should not create a broken symlink to a skipped optional dependency', async () => { const project = prepareEmpty() - console.log(process.cwd()) await install({ optionalDependencies: { @@ -522,4 +521,9 @@ test('hoisting should not create a broken symlink to a skipped optional dependen }, await testDefaults({ publicHoistPattern: '*' })) await project.hasNot('dep-of-optional-pkg') + + const rootModules = assertProject(process.cwd()) + const currentLockfile = await rootModules.readCurrentLockfile() + const wantedLockfile = await rootModules.readLockfile() + expect(currentLockfile).toStrictEqual(wantedLockfile) }) \ No newline at end of file