diff --git a/.changeset/nice-flowers-kneel.md b/.changeset/nice-flowers-kneel.md new file mode 100644 index 0000000000..aaff9fa422 --- /dev/null +++ b/.changeset/nice-flowers-kneel.md @@ -0,0 +1,5 @@ +--- +"@pnpm/real-hoist": patch +--- + +When the same package is installed through different aliases, hoist each of the aliases. diff --git a/packages/core/test/hoistedNodeLinker/install.ts b/packages/core/test/hoistedNodeLinker/install.ts index c60ff099cb..e2ed494934 100644 --- a/packages/core/test/hoistedNodeLinker/install.ts +++ b/packages/core/test/hoistedNodeLinker/install.ts @@ -109,3 +109,18 @@ test('adding a new dependency to one of the the workspace projects', async () => expect(loadJsonFile<{ version: string }>('node_modules/bar/package.json').version).toBe('100.0.0') expect(loadJsonFile<{ version: string }>('node_modules/is-negative/package.json').version).toBe('1.0.0') }) + +test('installing the same package with alias and no alias', async () => { + await addDistTag('dep-of-pkg-with-1-dep', '100.0.0', 'latest') + prepareEmpty() + + await addDependenciesToPackage( + {}, + ['pkg-with-1-aliased-dep@100.0.0', 'dep-of-pkg-with-1-dep@^100.0.0'], + await testDefaults({ nodeLinker: 'hoisted' }) + ) + + expect(loadJsonFile<{ version: string }>('node_modules/pkg-with-1-aliased-dep/package.json').version).toBe('100.0.0') + expect(loadJsonFile<{ version: string }>('node_modules/dep-of-pkg-with-1-dep/package.json').version).toBe('100.0.0') + expect(loadJsonFile<{ version: string }>('node_modules/dep/package.json').version).toBe('100.0.0') +}) diff --git a/packages/real-hoist/src/index.ts b/packages/real-hoist/src/index.ts index 5883760d33..fdb62f646b 100644 --- a/packages/real-hoist/src/index.ts +++ b/packages/real-hoist/src/index.ts @@ -45,7 +45,8 @@ function toTree (nodes: Map, lockfile: Lockfile, deps: Reco return new Set(Object.entries(deps).map(([alias, ref]) => { const depPath = dp.refToRelative(ref, alias)! if (!depPath) { - let node = nodes.get(ref) + const key = `${alias}:${ref}` + let node = nodes.get(key) if (!node) { node = { name: alias, @@ -55,11 +56,12 @@ function toTree (nodes: Map, lockfile: Lockfile, deps: Reco dependencies: new Set(), peerNames: new Set(), } - nodes.set(depPath, node) + nodes.set(key, node) } return node } - let node = nodes.get(depPath) + const key = `${alias}:${depPath}` + let node = nodes.get(key) if (!node) { // const { name, version, peersSuffix } = nameVerFromPkgSnapshot(depPath, lockfile.packages![depPath]) const pkgSnapshot = lockfile.packages![depPath] @@ -75,7 +77,7 @@ function toTree (nodes: Map, lockfile: Lockfile, deps: Reco ...(pkgSnapshot.transitivePeerDependencies ?? []), ]), } - nodes.set(depPath, node) + nodes.set(key, node) node.dependencies = toTree(nodes, lockfile, { ...pkgSnapshot.dependencies, ...pkgSnapshot.optionalDependencies }) } return node