From b458ef5025e75dd9a34728d61fb946d85819a9ef Mon Sep 17 00:00:00 2001 From: Kenrick Date: Wed, 17 Aug 2022 16:21:39 +0800 Subject: [PATCH] feat(resolve-dependencies): add more projects to install when resolving --- .../packages/f/package.json | 3 +- .../core/src/install/extendInstallOptions.ts | 4 ++ packages/core/src/install/index.ts | 2 + .../src/installDeps.ts | 2 + .../test/installDeep.ts | 28 ++++++-- packages/resolve-dependencies/package.json | 1 + packages/resolve-dependencies/src/index.ts | 67 ++++++++++++++++++- pnpm-lock.yaml | 5 +- 8 files changed, 104 insertions(+), 8 deletions(-) diff --git a/fixtures/workspace-external-depends-deep/packages/f/package.json b/fixtures/workspace-external-depends-deep/packages/f/package.json index 39ea2c1942c..4ce399ec780 100644 --- a/fixtures/workspace-external-depends-deep/packages/f/package.json +++ b/fixtures/workspace-external-depends-deep/packages/f/package.json @@ -2,7 +2,8 @@ "name": "@kenrick95/internal-f", "version": "1.0.0", "dependencies": { - "is-positive": "1.0.0" + "is-positive": "1.0.0", + "is-negative": "1.0.0" } } diff --git a/packages/core/src/install/extendInstallOptions.ts b/packages/core/src/install/extendInstallOptions.ts index 933f2e226bf..870b64b451e 100644 --- a/packages/core/src/install/extendInstallOptions.ts +++ b/packages/core/src/install/extendInstallOptions.ts @@ -12,6 +12,7 @@ import { PeerDependencyRules, ReadPackageHook, Registries, + Project, } from '@pnpm/types' import pnpmPkgJson from '../pnpmPkgJson' import { ReporterFunction } from '../types' @@ -109,6 +110,9 @@ export interface StrictInstallOptions { global: boolean globalBin?: string patchedDependencies?: Record + + allProjects?: Project[] + workspaceDir?: string } export type InstallOptions = diff --git a/packages/core/src/install/index.ts b/packages/core/src/install/index.ts index 7931da2c882..831f444699c 100644 --- a/packages/core/src/install/index.ts +++ b/packages/core/src/install/index.ts @@ -806,6 +806,8 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => { { allowBuild: createAllowBuildFunction(opts), allowedDeprecatedVersions: opts.allowedDeprecatedVersions, + allProjects: opts.allProjects, + workspaceDir: opts.workspaceDir, autoInstallPeers: opts.autoInstallPeers, currentLockfile: ctx.currentLockfile, defaultUpdateDepth: (opts.update || (opts.updateMatching != null)) ? opts.depth : -1, diff --git a/packages/plugin-commands-installation/src/installDeps.ts b/packages/plugin-commands-installation/src/installDeps.ts index 31dfbe4b56d..9261e88c11f 100644 --- a/packages/plugin-commands-installation/src/installDeps.ts +++ b/packages/plugin-commands-installation/src/installDeps.ts @@ -190,6 +190,8 @@ when running add/update with the --workspace option') storeController: store.ctrl, storeDir: store.dir, workspacePackages, + workspaceDir: opts.workspaceDir, + allProjects: opts.allProjects, } if (opts.global && opts.pnpmHomeDir != null) { const nodeExecPath = await getNodeExecPath() diff --git a/packages/plugin-commands-installation/test/installDeep.ts b/packages/plugin-commands-installation/test/installDeep.ts index c21bf016e62..00605f6af20 100644 --- a/packages/plugin-commands-installation/test/installDeep.ts +++ b/packages/plugin-commands-installation/test/installDeep.ts @@ -12,11 +12,12 @@ const f = fixtures(__dirname) test('Installing a package deeply installs all required dependencies', async () => { f.prepare('workspace-external-depends-deep') + const cwd = process.cwd() const { allProjects, selectedProjectsGraph, } = await readProjects(process.cwd(), [ - { namePattern: '@kenrick95/internal-f' }, + { namePattern: '@kenrick95/internal-g' }, ]) for (const project of allProjects) { await rimraf(path.join(project.dir, 'node_modules')) @@ -25,24 +26,41 @@ test('Installing a package deeply installs all required dependencies', async () const projectGraphKeys = Object.keys(selectedProjectsGraph) expect(projectGraphKeys).toHaveLength(1) expect(selectedProjectsGraph[projectGraphKeys[0]].package.manifest.name).toBe( - '@kenrick95/internal-f' + '@kenrick95/internal-g' ) + console.log('projectGraphKeys', projectGraphKeys) + console.log('cwd', cwd) + await install.handler({ ...DEFAULT_OPTS, - dir: process.cwd(), - workspaceDir: process.cwd(), + dir: cwd, + workspaceDir: cwd, + allProjects, + recursive: true, selectedProjectsGraph, preferWorkspacePackages: true, linkWorkspacePackages: 'deep', }) for (const project of allProjects) { - console.log(project.dir, await fs.readdir(project.dir)) + const files = await fs.readdir(project.dir) + console.log(project.dir, files) + if (files.includes('node_modules')) { + console.log( + project.dir, + 'node_modules', + await fs.readdir(path.join(project.dir, 'node_modules')) + ) + // Somehow "g" now has pnpm-lock.yaml ??? + } } for (const project of allProjects) { + if (project.dir === cwd) { + continue + } const projectAssertion = assertProject(project.dir) expect(projectAssertion.requireModule('is-positive')).toBeTruthy() } diff --git a/packages/resolve-dependencies/package.json b/packages/resolve-dependencies/package.json index 1c0e7c5ec63..f87b185f660 100644 --- a/packages/resolve-dependencies/package.json +++ b/packages/resolve-dependencies/package.json @@ -32,6 +32,7 @@ "@pnpm/constants": "workspace:*", "@pnpm/core-loggers": "workspace:*", "@pnpm/error": "workspace:*", + "@pnpm/filter-workspace-packages": "workspace:*", "@pnpm/lockfile-types": "workspace:*", "@pnpm/lockfile-utils": "workspace:*", "@pnpm/manifest-utils": "workspace:*", diff --git a/packages/resolve-dependencies/src/index.ts b/packages/resolve-dependencies/src/index.ts index 944435d8f0b..94aafb6a5a6 100644 --- a/packages/resolve-dependencies/src/index.ts +++ b/packages/resolve-dependencies/src/index.ts @@ -13,8 +13,10 @@ import { getSpecFromPackageManifest, PinnedVersion, } from '@pnpm/manifest-utils' +import { filterPkgsBySelectorObjects } from '@pnpm/filter-workspace-packages' import { safeReadPackageFromDir as safeReadPkgFromDir } from '@pnpm/read-package-json' import { + Project, DEPENDENCIES_FIELDS, DependencyManifest, ProjectManifest, @@ -79,6 +81,8 @@ export type ImporterToResolve = Importer<{ export default async function ( importers: ImporterToResolve[], opts: ResolveDependenciesOptions & { + allProjects?: Project[] + workspaceDir?: string defaultUpdateDepth: number preserveWorkspaceProtocol: boolean saveWorkspaceProtocol: 'rolling' | boolean @@ -93,8 +97,10 @@ export default async function ( virtualStoreDir: opts.virtualStoreDir, workspacePackages: opts.workspacePackages, }) + console.log('importers', JSON.stringify(importers)) const projectsToResolve = await Promise.all(importers.map(async (project) => _toResolveImporter(project))) - const { + console.log('projectsToResolve', JSON.stringify(projectsToResolve)) + let { dependenciesTree, outdatedDependencies, resolvedImporters, @@ -103,6 +109,65 @@ export default async function ( appliedPatches, } = await resolveDependencyTree(projectsToResolve, opts) + while (true) { + if (!opts.workspaceDir || !opts.allProjects) { + break + } + + const allProjectsToResolve = new Set(projectsToResolve.map(p => p.manifest.name)) + console.log('dependenciesTree', dependenciesTree) + + const newProjects = [] + for (const node of Object.values(dependenciesTree)) { + if (node.depth === -1 && node.resolvedPackage.name) { + if (!allProjectsToResolve.has(node.resolvedPackage.name)) { + newProjects.push(node.resolvedPackage.name) + } + } + } + if (newProjects.length === 0) { + break + } + + { + const { selectedProjectsGraph } = await filterPkgsBySelectorObjects( + opts.allProjects, + newProjects.map(newP => ({ + namePattern: newP, + includeDependencies: true, + })), + { + workspaceDir: opts.workspaceDir, + } + ) + + for (const node of Object.values(selectedProjectsGraph)) { + const importer = { + id: '.', // What value should I use? + manifest: node.package.manifest, + originalManifest: node.package.manifest, + modulesDir: path.join(node.package.dir, 'node_modules'), + rootDir: node.package.dir, + binsDir: path.join(node.package.dir, 'node_modules', '.bin'), + wantedDependencies: [], + updatePackageManifest: false, + mutation: 'install', // How to do this only for mutation == install? + } as ImporterToResolve + importers.push(importer) + const projectToResolve = await _toResolveImporter(importer) + projectsToResolve.push(projectToResolve) + } + } + + const result = await resolveDependencyTree(projectsToResolve, opts) + dependenciesTree = result.dependenciesTree + outdatedDependencies = result.outdatedDependencies + resolvedImporters = result.resolvedImporters + resolvedPackagesByDepPath = result.resolvedPackagesByDepPath + wantedToBeSkippedPackageIds = result.wantedToBeSkippedPackageIds + appliedPatches = result.appliedPatches + } + // We only check whether patches were applied in cases when the whole lockfile was reanalyzed. if ( opts.patchedDependencies && diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0bd896b3c05..9be21668d45 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4694,6 +4694,9 @@ importers: '@pnpm/error': specifier: workspace:* version: link:../error + '@pnpm/filter-workspace-packages': + specifier: workspace:* + version: link:../filter-workspace-packages '@pnpm/lockfile-types': specifier: workspace:* version: link:../lockfile-types @@ -5561,7 +5564,7 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.17.10 + '@babel/types': 7.18.10 dev: true /@babel/parser/7.18.11: