mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-28 02:53:15 -04:00
fix(resolve-dependencies): dedupe deps with the same alias in direct dependencies (#6974)
close #6966
This commit is contained in:
6
.changeset/short-beds-run.md
Normal file
6
.changeset/short-beds-run.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/resolve-dependencies": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Dedupe deps with the same alias in direct dependencies [6966](https://github.com/pnpm/pnpm/issues/6966)
|
||||
@@ -233,3 +233,48 @@ test.skip('from a github repo that needs to be built. hoisted node linker is us
|
||||
await install(manifest, await testDefaults({ frozenLockfile: true, ignoreScripts: true, nodeLinker: 'hoisted' }, { ignoreScripts: true }))
|
||||
await project.hasNot('@pnpm.e2e/prepare-script-works/prepare.txt')
|
||||
})
|
||||
|
||||
test('re-adding a git repo with a different tag', async () => {
|
||||
const project = prepareEmpty()
|
||||
let manifest = await addDependenciesToPackage({}, ['kevva/is-negative#1.0.0'], await testDefaults())
|
||||
await project.has('is-negative')
|
||||
expect(manifest.dependencies).toStrictEqual({
|
||||
'is-negative': 'github:kevva/is-negative#1.0.0',
|
||||
})
|
||||
expect(JSON.parse(fs.readFileSync('./node_modules/is-negative/package.json', 'utf8')).version).toBe('1.0.0')
|
||||
let lockfile = await project.readLockfile()
|
||||
expect(lockfile.dependencies['is-negative']).toEqual({
|
||||
specifier: 'github:kevva/is-negative#1.0.0',
|
||||
version: 'github.com/kevva/is-negative/163360a8d3ae6bee9524541043197ff356f8ed99',
|
||||
})
|
||||
expect(lockfile.packages).toEqual(
|
||||
{
|
||||
'github.com/kevva/is-negative/163360a8d3ae6bee9524541043197ff356f8ed99': {
|
||||
resolution: { tarball: 'https://codeload.github.com/kevva/is-negative/tar.gz/163360a8d3ae6bee9524541043197ff356f8ed99' },
|
||||
name: 'is-negative',
|
||||
version: '1.0.0',
|
||||
engines: { node: '>=0.10.0' },
|
||||
dev: false,
|
||||
},
|
||||
}
|
||||
)
|
||||
manifest = await addDependenciesToPackage(manifest, ['kevva/is-negative#1.0.1'], await testDefaults())
|
||||
await project.has('is-negative')
|
||||
expect(JSON.parse(fs.readFileSync('./node_modules/is-negative/package.json', 'utf8')).version).toBe('1.0.1')
|
||||
lockfile = await project.readLockfile()
|
||||
expect(lockfile.dependencies['is-negative']).toEqual({
|
||||
specifier: 'github:kevva/is-negative#1.0.1',
|
||||
version: 'github.com/kevva/is-negative/9a89df745b2ec20ae7445d3d9853ceaeef5b0b72',
|
||||
})
|
||||
expect(lockfile.packages).toEqual(
|
||||
{
|
||||
'github.com/kevva/is-negative/9a89df745b2ec20ae7445d3d9853ceaeef5b0b72': {
|
||||
resolution: { tarball: 'https://codeload.github.com/kevva/is-negative/tar.gz/9a89df745b2ec20ae7445d3d9853ceaeef5b0b72' },
|
||||
name: 'is-negative',
|
||||
version: '1.0.1',
|
||||
engines: { node: '>=0.10.0' },
|
||||
dev: false,
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
@@ -187,10 +187,9 @@ export async function resolveDependencyTree<T> (
|
||||
}
|
||||
}
|
||||
|
||||
for (const { id } of importers) {
|
||||
const directDeps = directDepsByImporterId[id]
|
||||
for (const { id, wantedDependencies } of importers) {
|
||||
const directDeps = dedupeSameAliasDirectDeps(directDepsByImporterId[id], wantedDependencies)
|
||||
const [linkedDependencies, directNonLinkedDeps] = partition((dep) => dep.isLinkedDependency === true, directDeps) as [LinkedDependency[], PkgAddress[]]
|
||||
|
||||
resolvedImporters[id] = {
|
||||
directDependencies: directDeps
|
||||
.map((dep) => {
|
||||
@@ -269,3 +268,28 @@ function buildTree (
|
||||
}
|
||||
return childrenNodeIds
|
||||
}
|
||||
|
||||
/**
|
||||
* There may be cases where multiple dependencies have the same alias in the directDeps array.
|
||||
* E.g., when there is "is-negative: github:kevva/is-negative#1.0.0" in the package.json dependencies,
|
||||
* and then re-execute `pnpm add github:kevva/is-negative#1.0.1`.
|
||||
* In order to make sure that the latest 1.0.1 version is installed, we need to remove the duplicate dependency.
|
||||
* fix https://github.com/pnpm/pnpm/issues/6966
|
||||
*/
|
||||
function dedupeSameAliasDirectDeps (directDeps: Array<PkgAddress | LinkedDependency>, wantedDependencies: Array<WantedDependency & { isNew?: boolean }>) {
|
||||
const deps = new Map()
|
||||
for (const directDep of directDeps) {
|
||||
const { alias, normalizedPref } = directDep
|
||||
if (!deps.has(alias)) {
|
||||
deps.set(alias, directDep)
|
||||
} else {
|
||||
const wantedDep = wantedDependencies.find(dep =>
|
||||
dep.alias ? dep.alias === alias : dep.pref === normalizedPref
|
||||
)
|
||||
if (wantedDep?.isNew) {
|
||||
deps.set(alias, directDep)
|
||||
}
|
||||
}
|
||||
}
|
||||
return Array.from(deps.values())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user