From bd0157f845933ce0b3ccb058dd45daa2db8ce995 Mon Sep 17 00:00:00 2001 From: Victor Vlasenko Date: Thu, 10 Mar 2022 17:47:19 +0200 Subject: [PATCH] Linker doesn't try to create self-reference symlinks for external portals --- .yarn/versions/e724089e.yml | 25 ++++++++++ CHANGELOG.md | 3 ++ .../sources/node-modules.test.ts | 49 +++++++++++++++++++ .../sources/buildNodeModulesTree.ts | 2 +- 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 .yarn/versions/e724089e.yml diff --git a/.yarn/versions/e724089e.yml b/.yarn/versions/e724089e.yml new file mode 100644 index 000000000000..4aae89e5563f --- /dev/null +++ b/.yarn/versions/e724089e.yml @@ -0,0 +1,25 @@ +releases: + "@yarnpkg/cli": patch + "@yarnpkg/nm": patch + "@yarnpkg/plugin-nm": patch + +declined: + - "@yarnpkg/plugin-compat" + - "@yarnpkg/plugin-constraints" + - "@yarnpkg/plugin-dlx" + - "@yarnpkg/plugin-essentials" + - "@yarnpkg/plugin-init" + - "@yarnpkg/plugin-interactive-tools" + - "@yarnpkg/plugin-npm-cli" + - "@yarnpkg/plugin-pack" + - "@yarnpkg/plugin-patch" + - "@yarnpkg/plugin-pnp" + - "@yarnpkg/plugin-pnpm" + - "@yarnpkg/plugin-stage" + - "@yarnpkg/plugin-typescript" + - "@yarnpkg/plugin-version" + - "@yarnpkg/plugin-workspace-tools" + - "@yarnpkg/builder" + - "@yarnpkg/core" + - "@yarnpkg/doctor" + - "@yarnpkg/pnpify" diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b54b55bb351..c08765083334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ Yarn now accepts sponsorships! Please give a look at our [OpenCollective](https: **Note:** features in `master` can be tried out by running `yarn set version from sources` in your project (existing contrib plugins are updated automatically, while new contrib plugins can be added by running `yarn plugin import from sources `). +### Installs + +- The node-modules linker does not fail anymore if portal dependency points to an external project with multiple interdependent workspaces ## 3.2.0 Various improvements have been made in the core to improve performance. Additionally: diff --git a/packages/acceptance-tests/pkg-tests-specs/sources/node-modules.test.ts b/packages/acceptance-tests/pkg-tests-specs/sources/node-modules.test.ts index e0cc6469c679..cd235b1d6d6f 100644 --- a/packages/acceptance-tests/pkg-tests-specs/sources/node-modules.test.ts +++ b/packages/acceptance-tests/pkg-tests-specs/sources/node-modules.test.ts @@ -1619,4 +1619,53 @@ describe(`Node_Modules`, () => { }); }), ); + + it(`should support portals to external workspaces`, + makeTemporaryEnv( + { + workspaces: [`ws`], + dependencies: { + 'no-deps': `1.0.0`, + }, + }, + { + nodeLinker: `node-modules`, + }, + async ({path, run}) => { + await xfs.mktempPromise(async portalTarget => { + await xfs.writeJsonPromise(`${path}/package.json` as PortablePath, { + dependencies: { + ws1: `^1.0.0`, + ws2: `^1.0.0`, + }, + resolutions: { + ws1: `portal:${portalTarget}/ws1`, + ws2: `portal:${portalTarget}/ws2`, + }, + }); + + await xfs.writeJsonPromise(`${portalTarget}/package.json` as PortablePath, { + name: `portal`, + workspaces: [`ws1`, `ws2`], + }); + + await xfs.mkdirpPromise(ppath.join(portalTarget, `ws1` as PortablePath)); + await xfs.writeJsonPromise(`${portalTarget}/ws1/package.json` as PortablePath, { + name: `ws1`, + workspaces: [`ws1`], + }); + + await xfs.mkdirpPromise(ppath.join(portalTarget, `ws2` as PortablePath)); + await xfs.writeJsonPromise(`${portalTarget}/ws2/package.json` as PortablePath, { + name: `ws2`, + workspaces: [`ws2`], + dependencies: { + ws1: `^1.0.0`, + }, + }); + + await expect(run(`install`)).resolves.not.toThrow(); + }); + }), + ); }); diff --git a/packages/yarnpkg-nm/sources/buildNodeModulesTree.ts b/packages/yarnpkg-nm/sources/buildNodeModulesTree.ts index 4e17b3f55e24..e93679f6ddfc 100644 --- a/packages/yarnpkg-nm/sources/buildNodeModulesTree.ts +++ b/packages/yarnpkg-nm/sources/buildNodeModulesTree.ts @@ -367,7 +367,7 @@ const buildPackageTree = (pnp: PnpApi, options: NodeModulesTreeOptions): { packa } } - if (pkg !== parentPkg || pkg.linkType !== LinkType.SOFT || !options.selfReferencesByCwd || options.selfReferencesByCwd.get(parentRelativeCwd)) + if (pkg !== parentPkg || pkg.linkType !== LinkType.SOFT || (!isExternalSoftLinkPackage && (!options.selfReferencesByCwd || options.selfReferencesByCwd.get(parentRelativeCwd)))) parent.dependencies.add(node); const isWorkspaceDependency = locator !== topLocator && pkg.linkType === LinkType.SOFT && !locator.name.endsWith(WORKSPACE_NAME_SUFFIX) && !isExternalSoftLinkPackage;