mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-10 18:18:56 -04:00
fix: don't remove hoisted dependencies from .pnpm on repeat install (#5971)
This commit is contained in:
7
.changeset/rare-dragons-crash.md
Normal file
7
.changeset/rare-dragons-crash.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@pnpm/modules-cleaner": patch
|
||||
"@pnpm/core": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Packages hoisted to the virtual store are not removed on repeat install, when the non-headless algorithm runs the installation.
|
||||
@@ -245,7 +245,9 @@ export async function linkPackages (
|
||||
}
|
||||
|
||||
let newHoistedDependencies!: HoistedDependencies
|
||||
if ((opts.hoistPattern != null || opts.publicHoistPattern != null) && (newDepPaths.length > 0 || removedDepPaths.size > 0)) {
|
||||
if (opts.hoistPattern == null && opts.publicHoistPattern == null) {
|
||||
newHoistedDependencies = {}
|
||||
} else if (newDepPaths.length > 0 || removedDepPaths.size > 0) {
|
||||
// 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 match.
|
||||
// But for hoisting, we need a version of the lockfile w/o the skipped packages, so we're making a copy.
|
||||
@@ -264,7 +266,7 @@ export async function linkPackages (
|
||||
virtualStoreDir: opts.virtualStoreDir,
|
||||
})
|
||||
} else {
|
||||
newHoistedDependencies = {}
|
||||
newHoistedDependencies = opts.hoistedDependencies
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -20,7 +20,7 @@ import { testDefaults } from '../utils'
|
||||
test('should hoist dependencies', async () => {
|
||||
const project = prepareEmpty()
|
||||
|
||||
await addDependenciesToPackage({}, ['express', '@foo/has-dep-from-same-scope'], await testDefaults({ fastUnpack: false, hoistPattern: '*' }))
|
||||
const manifest = await addDependenciesToPackage({}, ['express', '@foo/has-dep-from-same-scope'], await testDefaults({ fastUnpack: false, hoistPattern: '*' }))
|
||||
|
||||
await project.has('express')
|
||||
await project.has('.pnpm/node_modules/debug')
|
||||
@@ -31,6 +31,19 @@ test('should hoist dependencies', async () => {
|
||||
|
||||
// should also hoist bins
|
||||
await project.isExecutable('.pnpm/node_modules/.bin/mime')
|
||||
|
||||
const modules = await project.readModulesManifest()
|
||||
expect(Object.keys(modules!.hoistedDependencies).length > 0).toBeTruthy()
|
||||
|
||||
// On repeat install the hoisted packages are preserved (non-headless install)
|
||||
await install(manifest, await testDefaults({ fastUnpack: false, hoistPattern: '*', preferFrozenLockfile: false, modulesCacheMaxAge: 0 }))
|
||||
await project.has('.pnpm/node_modules/debug')
|
||||
expect((await project.readModulesManifest())!.hoistedDependencies).toStrictEqual(modules!.hoistedDependencies)
|
||||
|
||||
// On repeat install the hoisted packages are preserved (headless install)
|
||||
await install(manifest, await testDefaults({ fastUnpack: false, hoistPattern: '*', frozenLockfile: true, modulesCacheMaxAge: 0 }))
|
||||
await project.has('.pnpm/node_modules/debug')
|
||||
expect((await project.readModulesManifest())!.hoistedDependencies).toStrictEqual(modules!.hoistedDependencies)
|
||||
})
|
||||
|
||||
test('should hoist dependencies to the root of node_modules when publicHoistPattern is used', async () => {
|
||||
|
||||
@@ -156,7 +156,7 @@ export async function prune (
|
||||
.map((orphanDepPath) => depPathToFilename(orphanDepPath))
|
||||
.map(async (orphanDepPath) => _tryRemovePkg(orphanDepPath))
|
||||
)
|
||||
const neededPkgs: Set<string> = new Set()
|
||||
const neededPkgs: Set<string> = new Set(['node_modules'])
|
||||
for (const depPath of Object.keys(opts.wantedLockfile.packages ?? {})) {
|
||||
if (opts.skipped.has(depPath)) continue
|
||||
neededPkgs.add(depPathToFilename(depPath))
|
||||
|
||||
Reference in New Issue
Block a user