fix: don't overwrite node_modules inside inject dependencies (#4299)

This commit is contained in:
Zoltan Kochan
2022-02-05 00:52:05 +02:00
committed by GitHub
parent 1a3126e0bc
commit 7ae349cd3f
3 changed files with 49 additions and 9 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/lifecycle": patch
"pnpm": patch
---
`node_modules` directories inside injected dependencies should not be overwritten.

View File

@@ -357,8 +357,6 @@ test('inject local packages when node-linker is hoisted', async () => {
version: '1.0.0',
dependencies: {
'is-negative': '1.0.0',
},
devDependencies: {
'dep-of-pkg-with-1-dep': '100.0.0',
},
peerDependencies: {
@@ -370,6 +368,7 @@ test('inject local packages when node-linker is hoisted', async () => {
version: '1.0.0',
dependencies: {
'project-1': 'workspace:1.0.0',
'dep-of-pkg-with-1-dep': '101.0.0',
},
devDependencies: {
'is-positive': '1.0.0',
@@ -461,6 +460,7 @@ test('inject local packages when node-linker is hoisted', async () => {
await rootModules.has('is-positive')
await projects['project-2'].has('project-1')
await projects['project-2'].has('project-1/node_modules/dep-of-pkg-with-1-dep')
await projects['project-3'].has('project-1')
await projects['project-3'].has('project-2')
@@ -485,6 +485,7 @@ test('inject local packages when node-linker is hoisted', async () => {
'is-positive': '>=1.0.0',
},
dependencies: {
'dep-of-pkg-with-1-dep': '100.0.0',
'is-negative': '1.0.0',
'is-positive': '1.0.0',
},
@@ -499,6 +500,7 @@ test('inject local packages when node-linker is hoisted', async () => {
name: 'project-2',
version: '1.0.0',
dependencies: {
'dep-of-pkg-with-1-dep': '101.0.0',
'project-1': 'file:project-1_is-positive@2.0.0',
},
transitivePeerDependencies: ['is-positive'],

View File

@@ -1,3 +1,5 @@
import fs from 'fs'
import path from 'path'
import { fetchFromDir } from '@pnpm/directory-fetcher'
import { StoreController } from '@pnpm/store-controller-types'
import { ProjectManifest } from '@pnpm/types'
@@ -53,16 +55,46 @@ export default async function runLifecycleHooksConcurrently (
if (targetDirs == null || targetDirs.length === 0) return
const filesResponse = await fetchFromDir(rootDir, {})
await Promise.all(
targetDirs.map((targetDir) => opts.storeController.importPackage(targetDir, {
filesResponse: {
fromStore: false,
...filesResponse,
},
force: false,
}))
targetDirs.map(async (targetDir) => {
const targetModulesDir = path.join(targetDir, 'node_modules')
const nodeModulesIndex = {}
if (fs.existsSync(targetModulesDir)) {
// If the target directory contains a node_modules directory
// (it may happen when the hoisted node linker is used)
// then we need to preserve this node_modules.
// So we scan this node_modules directory and pass it as part of the new package.
await scanDir('node_modules', targetModulesDir, targetModulesDir, nodeModulesIndex)
}
return opts.storeController.importPackage(targetDir, {
filesResponse: {
fromStore: false,
...filesResponse,
filesIndex: {
...filesResponse.filesIndex,
...nodeModulesIndex,
},
},
force: false,
})
})
)
}
)
})
await runGroups(childConcurrency, groups)
}
async function scanDir (prefix: string, rootDir: string, currentDir: string, index: Record<string, string>) {
const files = await fs.promises.readdir(currentDir)
await Promise.all(files.map(async (file) => {
const fullPath = path.join(currentDir, file)
const stat = await fs.promises.stat(fullPath)
if (stat.isDirectory()) {
return scanDir(prefix, rootDir, fullPath, index)
}
if (stat.isFile()) {
const relativePath = path.relative(rootDir, fullPath)
index[path.join(prefix, relativePath)] = fullPath
}
}))
}