From 4a4b2ac93bf4911fb1d829751d957c59e656c4d1 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Mon, 14 Nov 2022 02:51:40 +0200 Subject: [PATCH] fix: error that sometimes happen on projects with linked deps (#5628) close #5327 close #5614 --- .changeset/mighty-waves-tan.md | 5 ++ .changeset/poor-berries-yell.md | 5 ++ packages/core/test/install/local.ts | 77 +++++++++++++++++++ packages/resolve-dependencies/package.json | 2 + packages/resolve-dependencies/src/index.ts | 3 +- .../src/resolveDependencies.ts | 7 +- pnpm-lock.yaml | 6 ++ 7 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 .changeset/mighty-waves-tan.md create mode 100644 .changeset/poor-berries-yell.md diff --git a/.changeset/mighty-waves-tan.md b/.changeset/mighty-waves-tan.md new file mode 100644 index 00000000000..bc2c6920c6f --- /dev/null +++ b/.changeset/mighty-waves-tan.md @@ -0,0 +1,5 @@ +--- +"pnpm": patch +--- + +Fix an error that sometimes happen on projects with linked local dependencies [#5327](https://github.com/pnpm/pnpm/issues/5327). diff --git a/.changeset/poor-berries-yell.md b/.changeset/poor-berries-yell.md new file mode 100644 index 00000000000..c6ca71988dd --- /dev/null +++ b/.changeset/poor-berries-yell.md @@ -0,0 +1,5 @@ +--- +"@pnpm/resolve-dependencies": patch +--- + +Fix the nodeId in dependenciesTree for linked local packages. diff --git a/packages/core/test/install/local.ts b/packages/core/test/install/local.ts index e450b6a566a..8d40caf0105 100644 --- a/packages/core/test/install/local.ts +++ b/packages/core/test/install/local.ts @@ -8,6 +8,8 @@ import { fixtures } from '@pnpm/test-fixtures' import { addDependenciesToPackage, install, + mutateModules, + MutatedProject, mutateModulesInSingleProject, } from '@pnpm/core' import rimraf from '@zkochan/rimraf' @@ -276,3 +278,78 @@ test('deep local', async () => { const lockfile = await readYamlFile('pnpm-lock.yaml') expect(Object.keys(lockfile.packages ?? {})).toStrictEqual(['file:../project-2', 'file:../project-2/project-3']) }) + +// Covers https://github.com/pnpm/pnpm/issues/5327 +test('resolution should not fail when a peer is resolved from a local package and there are many circular dependencies', async () => { + const manifest1 = { + name: 'chained-iterator', + version: '0.0.4', + dependencies: { + '@bryntum/siesta': '6.0.0-beta-1', + }, + } + const manifest2 = { + name: '@bryntum/chronograph', + version: '2.0.3', + dependencies: { + '@bryntum/siesta': '6.0.0-beta-1', + 'typescript-serializable-mixin': '0.0.3', + 'typescript-mixin-class': 'link:../typescript-mixin-class', + }, + } + const manifest3 = { + name: 'typescript-mixin-class', + version: '0.0.3', + dependencies: { + '@bryntum/siesta': '6.0.0-beta-1', + }, + } + + preparePackages([ + { + location: manifest1.name, + package: manifest1, + }, + { + location: manifest2.name, + package: manifest2, + }, + { + location: manifest3.name, + package: manifest3, + }, + ]) + const importers: MutatedProject[] = [ + { + mutation: 'install', + rootDir: path.resolve(manifest1.name), + }, + { + mutation: 'install', + rootDir: path.resolve(manifest2.name), + }, + { + mutation: 'install', + rootDir: path.resolve(manifest3.name), + }, + ] + const allProjects = [ + { + buildIndex: 0, + manifest: manifest1, + rootDir: path.resolve(manifest1.name), + }, + { + buildIndex: 0, + manifest: manifest2, + rootDir: path.resolve(manifest2.name), + }, + { + buildIndex: 0, + manifest: manifest3, + rootDir: path.resolve(manifest3.name), + }, + ] + await mutateModules(importers, await testDefaults({ allProjects, lockfileOnly: true, strictPeerDependencies: false })) + // All we need to know in this test is that installation doesn't fail +}) diff --git a/packages/resolve-dependencies/package.json b/packages/resolve-dependencies/package.json index 2a5723a992d..58d774c6605 100644 --- a/packages/resolve-dependencies/package.json +++ b/packages/resolve-dependencies/package.json @@ -50,6 +50,7 @@ "get-npm-tarball-url": "^2.0.3", "is-inner-link": "^4.0.0", "is-subdir": "^1.2.0", + "normalize-path": "^3.0.0", "p-defer": "^3.0.0", "path-exists": "^4.0.0", "promise-share": "^1.0.0", @@ -63,6 +64,7 @@ }, "devDependencies": { "@pnpm/resolve-dependencies": "workspace:*", + "@types/normalize-path": "^3.0.0", "@types/ramda": "0.28.15", "@types/semver": "7.3.13" }, diff --git a/packages/resolve-dependencies/src/index.ts b/packages/resolve-dependencies/src/index.ts index 6e23b604168..0df48f58a2e 100644 --- a/packages/resolve-dependencies/src/index.ts +++ b/packages/resolve-dependencies/src/index.ts @@ -25,6 +25,7 @@ import promiseShare from 'promise-share' import difference from 'ramda/src/difference' import { getWantedDependencies, WantedDependency } from './getWantedDependencies' import { depPathToRef } from './depPathToRef' +import { createNodeIdForLinkedLocalPkg } from './resolveDependencies' import { Importer, LinkedDependency, @@ -179,7 +180,7 @@ export async function resolveDependencies ( topParents.push({ name: linkedDependency.alias, version: linkedDependency.version, - linkedDir: `link:${path.relative(opts.lockfileDir, linkedDependency.resolution.directory)}`, + linkedDir: createNodeIdForLinkedLocalPkg(opts.lockfileDir, linkedDependency.resolution.directory), }) }) diff --git a/packages/resolve-dependencies/src/resolveDependencies.ts b/packages/resolve-dependencies/src/resolveDependencies.ts index a9c10d9d3b2..f07e5fb0f20 100644 --- a/packages/resolve-dependencies/src/resolveDependencies.ts +++ b/packages/resolve-dependencies/src/resolveDependencies.ts @@ -39,6 +39,7 @@ import { Registries, } from '@pnpm/types' import * as dp from 'dependency-path' +import normalizePath from 'normalize-path' import exists from 'path-exists' import pDefer from 'p-defer' import pShare from 'promise-share' @@ -665,7 +666,7 @@ async function resolveDependenciesOfDependency ( if (resolveDependencyResult == null) return { resolveDependencyResult: null } if (resolveDependencyResult.isLinkedDependency) { - ctx.dependenciesTree[resolveDependencyResult.pkgId] = { + ctx.dependenciesTree[createNodeIdForLinkedLocalPkg(ctx.lockfileDir, resolveDependencyResult.resolution.directory)] = { children: {}, depth: -1, installable: true, @@ -708,6 +709,10 @@ async function resolveDependenciesOfDependency ( } } +export function createNodeIdForLinkedLocalPkg (lockfileDir: string, pkgDir: string) { + return `link:${normalizePath(path.relative(lockfileDir, pkgDir))}` +} + function filterMissingPeers ( { missingPeers, resolvedPeers }: PeersResolutionResult, parentPkgAliases: ParentPkgAliases diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f57be463c88..8a83cde7606 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4882,6 +4882,9 @@ importers: is-subdir: specifier: ^1.2.0 version: 1.2.0 + normalize-path: + specifier: ^3.0.0 + version: 3.0.0 p-defer: specifier: ^3.0.0 version: 3.0.0 @@ -4916,6 +4919,9 @@ importers: '@pnpm/resolve-dependencies': specifier: workspace:* version: 'link:' + '@types/normalize-path': + specifier: ^3.0.0 + version: 3.0.0 '@types/ramda': specifier: 0.28.15 version: 0.28.15