fix: dedupe dependencies when adding new ones (#3877)

close #1041
This commit is contained in:
Zoltan Kochan
2021-10-16 03:18:09 +03:00
committed by GitHub
parent 7b0906043b
commit 4b163f69ce
4 changed files with 43 additions and 11 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/resolve-dependencies": patch
---
Dedupe dependencies when one of the packages is updated or a new one is added.

View File

@@ -116,6 +116,7 @@ export interface ChildrenByParentDepPath {
}
export interface ResolutionContext {
updatedSet: Set<string>
defaultTag: string
dryRun: boolean
forceFullResolution: boolean
@@ -241,8 +242,11 @@ export default async function resolveDependencies (
.filter(Boolean) as PkgAddress[]
const newPreferredVersions = { ...preferredVersions }
for (const { depPath } of pkgAddresses) {
const resolvedPackage = ctx.resolvedPackagesByDepPath[depPath]
for (const pkgAddress of pkgAddresses) {
if (pkgAddress.updated) {
ctx.updatedSet.add(pkgAddress.alias)
}
const resolvedPackage = ctx.resolvedPackagesByDepPath[pkgAddress.depPath]
if (!resolvedPackage) continue // This will happen only with linked dependencies
if (!newPreferredVersions[resolvedPackage.name]) {
newPreferredVersions[resolvedPackage.name] = {}
@@ -271,11 +275,11 @@ async function resolveDependenciesOfDependency (
? extendedWantedDep.wantedDependency.updateDepth
: options.updateDepth
const updateShouldContinue = options.currentDepth <= updateDepth
const update = (
const update = ((extendedWantedDep.infoFromLockfile?.dependencyLockfile) == null) ||
(
updateShouldContinue && (
(ctx.updateMatching == null) ||
((extendedWantedDep.infoFromLockfile?.dependencyLockfile) == null) ||
ctx.updateMatching(extendedWantedDep.infoFromLockfile.dependencyLockfile.name ?? extendedWantedDep.wantedDependency.alias)
ctx.updateMatching(extendedWantedDep.infoFromLockfile.name!)
)
) || Boolean(
(options.workspacePackages != null) &&
@@ -284,14 +288,15 @@ async function resolveDependenciesOfDependency (
extendedWantedDep.wantedDependency,
{ defaultTag: ctx.defaultTag, registry: ctx.registries.default }
)
)
) || ctx.updatedSet.has(extendedWantedDep.infoFromLockfile.name!)
const resolveDependencyOpts: ResolveDependencyOptions = {
currentDepth: options.currentDepth,
parentPkg: options.parentPkg,
preferredVersions,
workspacePackages: options.workspacePackages,
currentPkg: extendedWantedDep.infoFromLockfile ?? undefined,
proceed: extendedWantedDep.proceed || updateShouldContinue,
proceed: extendedWantedDep.proceed || updateShouldContinue || ctx.updatedSet.size > 0,
update,
updateDepth,
}
@@ -478,14 +483,19 @@ function referenceSatisfiesWantedSpec (
return semver.satisfies(version, wantedDep.pref, true)
}
interface InfoFromLockfile {
dependencyLockfile?: PackageSnapshot
type InfoFromLockfile = {
depPath: string
pkgId: string
dependencyLockfile?: PackageSnapshot
name?: string
version?: string
pkgId: string
resolution?: Resolution
}
} & ({
dependencyLockfile: PackageSnapshot
name: string
version: string
resolution: Resolution
} | {})
function getInfoFromLockfile (
lockfile: Lockfile,

View File

@@ -109,6 +109,7 @@ export default async function<T> (
const linkedDependencies = [] as LinkedDependency[]
const resolveCtx = {
...ctx,
updatedSet: new Set<string>(),
linkedDependencies,
modulesDir: importer.modulesDir,
prefix: importer.rootDir,

View File

@@ -177,3 +177,19 @@ test('prefer version of package that also satisfies the range of the same packag
]
)
})
test('dedupe subdependency when a newer version of the same package is installed', async () => {
const project = prepareEmpty()
await addDistTag({ package: 'dep-of-pkg-with-1-dep', version: '100.0.0', distTag: 'latest' })
const manifest = await addDependenciesToPackage({}, ['dep-of-pkg-with-1-dep@100.0.0', 'pkg-with-1-dep@100.0.0'], await testDefaults())
await addDistTag({ package: 'dep-of-pkg-with-1-dep', version: '100.1.0', distTag: 'latest' })
await addDependenciesToPackage(manifest, ['dep-of-pkg-with-1-dep@100.1.0'], await testDefaults())
const lockfile = await project.readLockfile()
expect(lockfile.packages).toHaveProperty(['/dep-of-pkg-with-1-dep/100.1.0'])
expect(lockfile.packages).not.toHaveProperty(['/dep-of-pkg-with-1-dep/100.0.0'])
})