diff --git a/.changeset/three-apricots-wonder.md b/.changeset/three-apricots-wonder.md new file mode 100644 index 0000000000..1a6f0e0d5e --- /dev/null +++ b/.changeset/three-apricots-wonder.md @@ -0,0 +1,6 @@ +--- +"@pnpm/deps.graph-builder": patch +"pnpm": patch +--- + +Fixed a performance regression on running installation on a project with an up to date lockfile [#7297](https://github.com/pnpm/pnpm/issues/7297). diff --git a/deps/graph-builder/src/lockfileToDepGraph.ts b/deps/graph-builder/src/lockfileToDepGraph.ts index 75ad9fbcf2..a5e81435fe 100644 --- a/deps/graph-builder/src/lockfileToDepGraph.ts +++ b/deps/graph-builder/src/lockfileToDepGraph.ts @@ -134,8 +134,8 @@ export async function lockfileToDepGraph ( currentPackages[depPath] && equals(currentPackages[depPath].dependencies, lockfile.packages![depPath].dependencies) let dirExists: boolean | undefined if ( - depIsPresent && isEmpty(currentPackages[depPath].optionalDependencies) && - isEmpty(lockfile.packages![depPath].optionalDependencies) + depIsPresent && isEmpty(currentPackages[depPath].optionalDependencies ?? {}) && + isEmpty(lockfile.packages![depPath].optionalDependencies ?? {}) ) { dirExists = await pathExists(dir) if (dirExists) { diff --git a/pkg-manager/core/src/install/link.ts b/pkg-manager/core/src/install/link.ts index 18118f59ed..37177c2d29 100644 --- a/pkg-manager/core/src/install/link.ts +++ b/pkg-manager/core/src/install/link.ts @@ -342,8 +342,8 @@ async function linkNewPackages ( for (const depPath of wantedRelDepPaths) { if (currentLockfile.packages[depPath] && (!equals(currentLockfile.packages[depPath].dependencies, wantedLockfile.packages[depPath].dependencies) || - !isEmpty(currentLockfile.packages[depPath].optionalDependencies) || - !isEmpty(wantedLockfile.packages[depPath].optionalDependencies)) + !isEmpty(currentLockfile.packages[depPath].optionalDependencies ?? {}) || + !isEmpty(wantedLockfile.packages[depPath].optionalDependencies ?? {})) ) { // TODO: come up with a test that triggers the usecase of depGraph[depPath] undefined // see related issue: https://github.com/pnpm/pnpm/issues/870 diff --git a/pkg-manager/core/test/install/misc.ts b/pkg-manager/core/test/install/misc.ts index b114af15fe..80c0790039 100644 --- a/pkg-manager/core/test/install/misc.ts +++ b/pkg-manager/core/test/install/misc.ts @@ -145,6 +145,19 @@ test('no dependencies (lodash)', async () => { expect(typeof m.clone).toBe('function') }) +test('only the new packages are added', async () => { + prepareEmpty() + const manifest = await addDependenciesToPackage({}, ['@pnpm/x'], await testDefaults()) + const reporter = sinon.spy() + await addDependenciesToPackage(manifest, ['@pnpm/y'], await testDefaults({ reporter })) + + expect(reporter.calledWithMatch({ + added: 1, + level: 'debug', + name: 'pnpm:stats', + } as StatsLog)).toBeTruthy() +}) + test('scoped modules without version spec', async () => { const project = prepareEmpty() await addDependenciesToPackage({}, ['@zkochan/foo'], await testDefaults()) diff --git a/pkg-manager/headless/test/index.ts b/pkg-manager/headless/test/index.ts index bde625a39b..92515595ab 100644 --- a/pkg-manager/headless/test/index.ts +++ b/pkg-manager/headless/test/index.ts @@ -76,6 +76,20 @@ test('installing a simple project', async () => { requester: prefix, status: 'resolved', })).toBeTruthy() + + reporter.resetHistory() + await headlessInstall(await testDefaults({ + lockfileDir: prefix, + reporter, + })) + // On repeat install no new packages should be added + // covers https://github.com/pnpm/pnpm/issues/7297 + expect(reporter.calledWithMatch({ + added: 0, + level: 'debug', + name: 'pnpm:stats', + prefix, + } as StatsLog)).toBeTruthy() }) test('installing only prod deps', async () => {