diff --git a/releasing/plugin-commands-deploy/src/createDeployFiles.ts b/releasing/plugin-commands-deploy/src/createDeployFiles.ts index 6943c82f0a..db40558beb 100644 --- a/releasing/plugin-commands-deploy/src/createDeployFiles.ts +++ b/releasing/plugin-commands-deploy/src/createDeployFiles.ts @@ -1,6 +1,7 @@ import path from 'path' import url from 'url' import pick from 'ramda/src/pick' +import normalizePath from 'normalize-path' import { type DirectoryResolution, type LockfileObject, @@ -37,11 +38,10 @@ const INHERITED_MANIFEST_KEYS = [ export type DeployManifest = Pick export interface CreateDeployFilesOptions { - allProjects: Array> + allProjects: Array> lockfile: LockfileObject lockfileDir: string - manifest: DeployManifest - projectId: ProjectId + selectedProject: Pick } export interface DeployFiles { @@ -53,11 +53,10 @@ export function createDeployFiles ({ allProjects, lockfile, lockfileDir, - manifest, - projectId, + selectedProject, }: CreateDeployFilesOptions): DeployFiles { - const deployedProjectRealPath = path.resolve(lockfileDir, projectId) as ProjectRootDirRealPath - const inputSnapshot = lockfile.importers[projectId] + const selectedProjectId = normalizePath(path.relative(lockfileDir, selectedProject.rootDir)) as ProjectId + const inputSnapshot = lockfile.importers[selectedProjectId] const targetSnapshot: ProjectSnapshot = { ...inputSnapshot, @@ -71,12 +70,12 @@ export function createDeployFiles ({ ...lockfile.packages, } - for (const importerPath in lockfile.importers) { - if (importerPath === projectId) continue - const projectSnapshot = lockfile.importers[importerPath as ProjectId] - const importerRealPath = path.resolve(lockfileDir, importerPath) as ProjectRootDirRealPath - const packageSnapshot = convertProjectSnapshotToPackageSnapshot(projectSnapshot, importerRealPath, allProjects, deployedProjectRealPath) - const depPath = createFileUrlDepPath(importerRealPath, allProjects) + for (const project of allProjects) { + if (project.rootDir === selectedProject.rootDir) continue + const projectId = (normalizePath(path.relative(lockfileDir, project.rootDir)) || '.') as ProjectId + const projectSnapshot = lockfile.importers[projectId] + const packageSnapshot = convertProjectSnapshotToPackageSnapshot(projectSnapshot, project, selectedProject) + const depPath = createFileUrlDepPath(project) targetPackageSnapshots[depPath] = packageSnapshot } @@ -93,8 +92,14 @@ export function createDeployFiles ({ } const { targetPath } = splitPrefixResult - const targetRealPath = path.resolve(lockfileDir, projectId, targetPath) as ProjectRootDirRealPath // importer IDs are relative to its project dir - targetSpecifiers[name] = targetDependencies[name] = createFileUrlDepPath(targetRealPath, allProjects) + const depRealPath = path.resolve(selectedProject.rootDir, targetPath) as ProjectRootDirRealPath + const depProject = allProjects.find(project => project.rootDirRealPath === depRealPath) + if (depProject) { + targetSpecifiers[name] = targetDependencies[name] = createFileUrlDepPath(depProject) + } else { + // if this branch is reached, it means that there is a bug in pnpm that needs to be fixed + throw new Error(`Cannot find any project in opts.allProject whose rootDirRealPath is '${depRealPath}'`) + } } } @@ -107,7 +112,7 @@ export function createDeployFiles ({ packages: targetPackageSnapshots, }, manifest: { - ...pick(INHERITED_MANIFEST_KEYS, manifest), + ...pick(INHERITED_MANIFEST_KEYS, selectedProject.manifest), dependencies: targetSnapshot.dependencies, devDependencies: targetSnapshot.devDependencies, optionalDependencies: targetSnapshot.optionalDependencies, @@ -117,16 +122,15 @@ export function createDeployFiles ({ function convertProjectSnapshotToPackageSnapshot ( projectSnapshot: ProjectSnapshot, - importerRealPath: string, - allProjects: CreateDeployFilesOptions['allProjects'], - deployedProjectRealPath: ProjectRootDirRealPath + inputProject: Pick, + selectedProject: Pick ): PackageSnapshot { const resolution: DirectoryResolution = { type: 'directory', directory: '.', } - const dependencies = convertResolvedDependencies(projectSnapshot.dependencies, importerRealPath, allProjects, deployedProjectRealPath) - const optionalDependencies = convertResolvedDependencies(projectSnapshot.optionalDependencies, importerRealPath, allProjects, deployedProjectRealPath) + const dependencies = convertResolvedDependencies(projectSnapshot.dependencies, inputProject, selectedProject) + const optionalDependencies = convertResolvedDependencies(projectSnapshot.optionalDependencies, inputProject, selectedProject) return { dependencies, optionalDependencies, @@ -136,9 +140,8 @@ function convertProjectSnapshotToPackageSnapshot ( function convertResolvedDependencies ( input: ResolvedDependencies | undefined, - importerRealPath: string, - allProjects: CreateDeployFilesOptions['allProjects'], - deployedProjectRealPath: ProjectRootDirRealPath + inputProject: Pick, + selectedProject: Pick ): ResolvedDependencies | undefined { if (!input) return undefined const output: ResolvedDependencies = {} @@ -152,18 +155,18 @@ function convertResolvedDependencies ( } const { targetPath } = splitPrefixResult - const depRealPath = path.resolve(importerRealPath, targetPath) as ProjectRootDirRealPath - if (['', '.'].includes(path.relative(importerRealPath, depRealPath))) { + const depRealPath = path.resolve(inputProject.rootDir, targetPath) + if (['', '.'].includes(path.relative(inputProject.rootDir, depRealPath))) { output[key] = 'link:.' continue } - if (depRealPath === deployedProjectRealPath) { + if (depRealPath === selectedProject.rootDir) { output[key] = '../../..' // which is the deployed project location relative to the dependency dir within the virtual dir continue } - output[key] = createFileUrlDepPath(depRealPath, allProjects) + output[key] = createFileUrlDepPath(inputProject) } return output @@ -181,12 +184,8 @@ function splitPrefix (spec: string): SplitPrefixResult | undefined { return { prefix, targetPath } } -function createFileUrlDepPath ( - depRealPath: ProjectRootDirRealPath, - allProjects: CreateDeployFilesOptions['allProjects'] -): DepPath { - const depFileUrl = url.pathToFileURL(depRealPath).toString() - const project = allProjects.find(project => project.rootDirRealPath === depRealPath) - const name = project?.manifest.name ?? path.basename(depRealPath) +function createFileUrlDepPath (inputProject: Pick): DepPath { + const depFileUrl = url.pathToFileURL(inputProject.rootDir).toString() + const name = inputProject.manifest.name ?? path.basename(inputProject.rootDir) return `${name}@${depFileUrl}` as DepPath } diff --git a/releasing/plugin-commands-deploy/src/deploy.ts b/releasing/plugin-commands-deploy/src/deploy.ts index a14a125b09..07fa667adc 100644 --- a/releasing/plugin-commands-deploy/src/deploy.ts +++ b/releasing/plugin-commands-deploy/src/deploy.ts @@ -12,8 +12,7 @@ import rimraf from '@zkochan/rimraf' import renderHelp from 'render-help' import { deployHook } from './deployHook' import { logger, globalWarn } from '@pnpm/logger' -import { type Project, type ProjectId } from '@pnpm/types' -import normalizePath from 'normalize-path' +import { type Project } from '@pnpm/types' import { createDeployFiles } from './createDeployFiles' import { deployCatalogHook } from './deployCatalogHook' @@ -155,7 +154,7 @@ async function deployFromSharedLockfile ( }, deployDir: string ): Promise { - const { allProjects, lockfileDir, workspaceDir } = opts + const { allProjects, lockfileDir } = opts if (!allProjects) { return 'opts.allProjects is undefined. Falling back to installing without a lockfile.' @@ -165,23 +164,16 @@ async function deployFromSharedLockfile ( return 'opts.lockfileDir is undefined. Falling back to installing without a lockfile.' } - if (!workspaceDir) { - return 'opts.workspaceDir is undefined. Falling back to installing without a lockfile.' - } - const lockfile = await readWantedLockfile(lockfileDir, { ignoreIncompatible: false }) if (!lockfile) { return 'Shared lockfile not found. Falling back to installing without a lockfile.' } - const projectId = normalizePath(path.relative(workspaceDir, selectedProject.rootDir)) as ProjectId - const deployFiles = createDeployFiles({ allProjects, lockfile, lockfileDir, - manifest: selectedProject.manifest, - projectId, + selectedProject, }) await Promise.all([ diff --git a/releasing/plugin-commands-deploy/test/deploy.test.ts b/releasing/plugin-commands-deploy/test/deploy.test.ts index 3914c59796..8e016a6c14 100644 --- a/releasing/plugin-commands-deploy/test/deploy.test.ts +++ b/releasing/plugin-commands-deploy/test/deploy.test.ts @@ -199,7 +199,7 @@ test('deploy with a shared lockfile after full install', async () => { expect(fs.existsSync(`deploy/node_modules/.pnpm/${project2Name}/node_modules/project-2/index.js`)).toBeTruthy() expect(fs.existsSync(`deploy/node_modules/.pnpm/${project2Name}/node_modules/project-2/test.js`)).toBeFalsy() const project3Name = fs.readdirSync('deploy/node_modules/.pnpm').find(name => name.startsWith('project-3@')) - expect(project3Name).toBeDefined() + expect(project3Name).toBeUndefined() expect(globalWarn).not.toHaveBeenCalledWith(expect.stringContaining('Falling back to installing without a lockfile')) }