diff --git a/packages/zpm/src/linker/pnpm.rs b/packages/zpm/src/linker/pnpm.rs index ffd72b54..51f827ae 100644 --- a/packages/zpm/src/linker/pnpm.rs +++ b/packages/zpm/src/linker/pnpm.rs @@ -194,7 +194,7 @@ pub async fn link_project_pnpm<'a>(project: &'a Project, install: &'a Install) - .relative_to(&link_abs_dirname); link_abs_path - .fs_rm_file() + .fs_rm() .ok_missing()? .unwrap_or(&link_abs_path) .fs_create_parent()? @@ -240,7 +240,7 @@ pub async fn link_project_pnpm<'a>(project: &'a Project, install: &'a Install) - .relative_to(&link_abs_dirname); link_abs_path - .fs_rm_file() + .fs_rm() .ok_missing()? .unwrap_or(&link_abs_path) .fs_create_parent()? @@ -304,7 +304,7 @@ pub async fn link_project_pnpm<'a>(project: &'a Project, install: &'a Install) - .relative_to(&link_abs_dirname); link_abs_path - .fs_rm_file() + .fs_rm() .ok_missing()? .unwrap_or(&link_abs_path) .fs_create_parent()? diff --git a/tests/acceptance-tests/pkg-tests-specs/sources/features/pnpm.test.ts b/tests/acceptance-tests/pkg-tests-specs/sources/features/pnpm.test.ts index d80caec0..56d91a44 100644 --- a/tests/acceptance-tests/pkg-tests-specs/sources/features/pnpm.test.ts +++ b/tests/acceptance-tests/pkg-tests-specs/sources/features/pnpm.test.ts @@ -129,6 +129,47 @@ describe(`Features`, () => { ), ); + test( + `it should replace leftover workspace node_modules directories when switching from the node-modules linker`, + makeTemporaryMonorepoEnv( + { + workspaces: [`packages/*`], + dependencies: { + [`no-deps`]: `1.0.0`, + }, + }, + { + [`packages/pkg-a`]: { + name: `pkg-a`, + version: `1.0.0`, + dependencies: { + [`no-deps`]: `2.0.0`, + }, + }, + }, + async ({path, run}) => { + // Install with the node-modules linker first. The version conflict + // forces no-deps@2.0.0 to live as a real directory inside the + // workspace's own node_modules rather than being hoisted to the root. + await run(`config`, `set`, `nodeLinker`, `node-modules`); + await run(`install`); + + const workspaceDep = npath.toPortablePath(`${path}/packages/pkg-a/node_modules/no-deps`); + const beforeStat = await xfs.lstatPromise(workspaceDep); + expect(beforeStat.isSymbolicLink()).toBeFalsy(); + expect(beforeStat.isDirectory()).toBeTruthy(); + + // Switching to the pnpm linker must overwrite that leftover real + // directory with a symlink rather than failing to unlink it. + await run(`config`, `set`, `nodeLinker`, `pnpm`); + await run(`install`); + + const afterStat = await xfs.lstatPromise(workspaceDep); + expect(afterStat.isSymbolicLink()).toBeTruthy(); + }, + ), + ); + test( `pnpmHoistPatterns should hoist matching packages to store node_modules`, makeTemporaryEnv(