fix: re-add manually removed packages to node_modules when node-linker is set to hoisted (#5921)

This commit is contained in:
Zoltan Kochan
2023-01-13 17:07:34 +02:00
committed by GitHub
parent 2ae1c449d2
commit bc8df37871
3 changed files with 24 additions and 3 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/headless": patch
"pnpm": patch
---
If an external tool or a user have removed a package from node_modules, pnpm should add it back on install. This was only an issue with `node-linker=hoisted`.

View File

@@ -3,6 +3,7 @@ import path from 'path'
import { addDependenciesToPackage, install, mutateModules, mutateModulesInSingleProject } from '@pnpm/core'
import { prepareEmpty } from '@pnpm/prepare'
import { addDistTag } from '@pnpm/registry-mock'
import rimraf from '@zkochan/rimraf'
import { sync as loadJsonFile } from 'load-json-file'
import { sync as readYamlFile } from 'read-yaml-file'
import symlinkDir from 'symlink-dir'
@@ -11,13 +12,14 @@ import { testDefaults } from '../utils'
test('installing with hoisted node-linker', async () => {
prepareEmpty()
await install({
const manifest = {
dependencies: {
send: '0.17.2',
'has-flag': '1.0.0',
ms: '1.0.0',
},
}, await testDefaults({
}
await install(manifest, await testDefaults({
nodeLinker: 'hoisted',
}))
@@ -27,6 +29,13 @@ test('installing with hoisted node-linker', async () => {
expect(fs.existsSync('node_modules/send/node_modules/ms')).toBeTruthy()
expect(readYamlFile<{ nodeLinker: string }>('node_modules/.modules.yaml').nodeLinker).toBe('hoisted')
// If a package from node_modules is removed, it should be re-added.
await rimraf('node_modules/send')
await install(manifest, await testDefaults({
nodeLinker: 'hoisted',
}))
expect(fs.realpathSync('node_modules/send')).toEqual(path.resolve('node_modules/send'))
})
test('installing with hoisted node-linker and no lockfile', async () => {

View File

@@ -1,3 +1,4 @@
import pathExists from 'path-exists'
import path from 'path'
import {
Lockfile,
@@ -181,7 +182,12 @@ async function fetchDeps (
const depLocation = path.relative(opts.lockfileDir, dir)
const resolution = pkgSnapshotToResolution(depPath, pkgSnapshot, opts.registries)
let fetchResponse!: ReturnType<FetchPackageToStoreFunction>
const skipFetch = opts.currentHoistedLocations?.[depPath]?.includes(depLocation)
// We check for the existence of the package inside node_modules.
// It will only be missing if the user manually removed it.
// That shouldn't normally happen but Bit CLI does remove node_modules in component directories:
// https://github.com/teambit/bit/blob/5e1eed7cd122813ad5ea124df956ee89d661d770/scopes/dependencies/dependency-resolver/dependency-installer.ts#L169
const skipFetch = opts.currentHoistedLocations?.[depPath]?.includes(depLocation) &&
await pathExists(path.join(opts.lockfileDir, depLocation))
const pkgResolution = {
id: packageId,
resolution,