mirror of
https://github.com/pnpm/pnpm.git
synced 2026-03-23 17:41:50 -04:00
fix: hoisting in a workspace
Direct dependencies of workspace projects should be hoisted. close #2315 PR #2322
This commit is contained in:
@@ -33,7 +33,7 @@ export default function filterByImporters (
|
||||
lockfile,
|
||||
importerIds,
|
||||
{ include: opts.include, skipped: opts.skipped },
|
||||
),
|
||||
).step,
|
||||
packages,
|
||||
{
|
||||
failOnMissingDependencies: opts.failOnMissingDependencies,
|
||||
|
||||
@@ -27,19 +27,33 @@ export default async function hoistByLockfile (
|
||||
) {
|
||||
if (!opts.lockfile.packages) return {}
|
||||
|
||||
const deps = await getDependencies(
|
||||
lockfileWalker(
|
||||
opts.lockfile,
|
||||
Object.keys(opts.lockfile.importers),
|
||||
),
|
||||
0,
|
||||
{
|
||||
getIndependentPackageLocation: opts.getIndependentPackageLocation,
|
||||
lockfileDir: opts.lockfileDir,
|
||||
registries: opts.registries,
|
||||
virtualStoreDir: opts.virtualStoreDir,
|
||||
},
|
||||
const { directDeps, step } = lockfileWalker(
|
||||
opts.lockfile,
|
||||
Object.keys(opts.lockfile.importers),
|
||||
)
|
||||
const deps = [
|
||||
{
|
||||
absolutePath: '',
|
||||
children: directDeps
|
||||
.reduce((acc, dep) => {
|
||||
if (acc[dep.alias]) return acc
|
||||
acc[dep.alias] = dp.resolve(opts.registries, dep.relDepPath)
|
||||
return acc
|
||||
}, {}),
|
||||
depth: -1,
|
||||
location: '',
|
||||
},
|
||||
...await getDependencies(
|
||||
step,
|
||||
0,
|
||||
{
|
||||
getIndependentPackageLocation: opts.getIndependentPackageLocation,
|
||||
lockfileDir: opts.lockfileDir,
|
||||
registries: opts.registries,
|
||||
virtualStoreDir: opts.virtualStoreDir,
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
const aliasesByDependencyPath = await hoistGraph(deps, opts.lockfile.importers['.'].specifiers, {
|
||||
dryRun: false,
|
||||
@@ -92,7 +106,6 @@ async function getDependencies (
|
||||
location: !independent
|
||||
? path.join(modules, pkgName)
|
||||
: await opts.getIndependentPackageLocation!(pkgSnapshot.id || absolutePath, pkgName),
|
||||
name: pkgName,
|
||||
})
|
||||
|
||||
nextSteps.push(next())
|
||||
@@ -112,7 +125,6 @@ async function getDependencies (
|
||||
}
|
||||
|
||||
export interface Dependency {
|
||||
name: string,
|
||||
location: string,
|
||||
children: {[alias: string]: string},
|
||||
depth: number,
|
||||
@@ -135,7 +147,7 @@ async function hoistGraph (
|
||||
// sort by depth and then alphabetically
|
||||
.sort((a, b) => {
|
||||
const depthDiff = a.depth - b.depth
|
||||
return depthDiff === 0 ? a.name.localeCompare(b.name) : depthDiff
|
||||
return depthDiff === 0 ? a.absolutePath.localeCompare(b.absolutePath) : depthDiff
|
||||
})
|
||||
// build the alias map and the id map
|
||||
.map((depNode) => {
|
||||
|
||||
@@ -55,6 +55,7 @@ export default function lockfileWalker (
|
||||
) {
|
||||
const walked = new Set<string>(opts?.skipped ? Array.from(opts?.skipped) : [])
|
||||
const entryNodes = [] as string[]
|
||||
const directDeps = [] as Array<{ alias: string, relDepPath: string }>
|
||||
|
||||
importerIds.forEach((importerId) => {
|
||||
const projectSnapshot = lockfile.importers[importerId]
|
||||
@@ -63,17 +64,21 @@ export default function lockfileWalker (
|
||||
...(opts?.include?.dependencies === false ? {} : projectSnapshot.dependencies),
|
||||
...(opts?.include?.optionalDependencies === false ? {} : projectSnapshot.optionalDependencies),
|
||||
})
|
||||
.map(([ pkgName, reference ]) => dp.refToRelative(reference, pkgName))
|
||||
.filter((nodeId) => nodeId !== null)
|
||||
.forEach((relDepPath) => {
|
||||
.forEach(([ pkgName, reference ]) => {
|
||||
const relDepPath = dp.refToRelative(reference, pkgName)
|
||||
if (relDepPath === null) return
|
||||
entryNodes.push(relDepPath as string)
|
||||
directDeps.push({ alias: pkgName, relDepPath })
|
||||
})
|
||||
})
|
||||
return step({
|
||||
includeOptionalDependencies: opts?.include?.optionalDependencies !== false,
|
||||
lockfile,
|
||||
walked,
|
||||
}, entryNodes)
|
||||
return {
|
||||
directDeps,
|
||||
step: step({
|
||||
includeOptionalDependencies: opts?.include?.optionalDependencies !== false,
|
||||
lockfile,
|
||||
walked,
|
||||
}, entryNodes),
|
||||
}
|
||||
}
|
||||
|
||||
function step (
|
||||
|
||||
@@ -245,7 +245,7 @@ async function _rebuild (
|
||||
optionalDependencies: opts.optional,
|
||||
},
|
||||
},
|
||||
),
|
||||
).step,
|
||||
nodesToBuildAndTransitive,
|
||||
{ pkgsToRebuild: ctx.pkgsToRebuild },
|
||||
)
|
||||
|
||||
@@ -311,7 +311,7 @@ test('should uninstall correctly peer dependencies', async (t) => {
|
||||
t.throws(() => fs.lstatSync('node_modules/ajv-keywords'), Error, 'symlink to peer dependency is deleted')
|
||||
})
|
||||
|
||||
test('hoist-pattern: only hoists the dependencies of the root workspace package', async (t) => {
|
||||
test('hoist-pattern: hoist all dependencies to the virtual store node_modules', async (t) => {
|
||||
const workspaceRootManifest = {
|
||||
name: 'root',
|
||||
|
||||
@@ -355,6 +355,9 @@ test('hoist-pattern: only hoists the dependencies of the root workspace package'
|
||||
|
||||
await projects['root'].has('pkg-with-1-dep')
|
||||
await projects['root'].has('.pnpm/node_modules/dep-of-pkg-with-1-dep')
|
||||
await projects['root'].has('.pnpm/node_modules/foobar')
|
||||
await projects['root'].has('.pnpm/node_modules/foo')
|
||||
await projects['root'].has('.pnpm/node_modules/bar')
|
||||
await projects['root'].hasNot('foobar')
|
||||
await projects['root'].hasNot('foo')
|
||||
await projects['root'].hasNot('bar')
|
||||
@@ -370,6 +373,9 @@ test('hoist-pattern: only hoists the dependencies of the root workspace package'
|
||||
|
||||
await projects['root'].has('pkg-with-1-dep')
|
||||
await projects['root'].has('.pnpm/node_modules/dep-of-pkg-with-1-dep')
|
||||
await projects['root'].has('.pnpm/node_modules/foobar')
|
||||
await projects['root'].has('.pnpm/node_modules/foo')
|
||||
await projects['root'].has('.pnpm/node_modules/bar')
|
||||
await projects['root'].hasNot('foobar')
|
||||
await projects['root'].hasNot('foo')
|
||||
await projects['root'].hasNot('bar')
|
||||
|
||||
Reference in New Issue
Block a user