mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-24 23:58:07 -05:00
fix: reference root manifest directory instead of the dependent dir (#9132)
* fix: reference root manifest directory instead of the dependent dir This fixes https://github.com/pnpm/pnpm/issues/9066. * refactor: link test * docs: add changeset --------- Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
6
.changeset/pink-mugs-run.md
Normal file
6
.changeset/pink-mugs-run.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-installation": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
`pnpm link <path>` should calculate relative path from the root of the workspace directory [#9132](https://github.com/pnpm/pnpm/pull/9132).
|
||||
@@ -39,6 +39,7 @@
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@pnpm/test-ipc-server": "workspace:*",
|
||||
"@pnpm/workspace.filter-packages-from-dir": "workspace:*",
|
||||
"@types/normalize-path": "catalog:",
|
||||
"@types/proxyquire": "catalog:",
|
||||
"@types/ramda": "catalog:",
|
||||
"@types/sinon": "catalog:",
|
||||
@@ -47,6 +48,7 @@
|
||||
"@types/zkochan__table": "catalog:",
|
||||
"delay": "catalog:",
|
||||
"jest-diff": "catalog:",
|
||||
"normalize-path": "catalog:",
|
||||
"path-name": "catalog:",
|
||||
"proxyquire": "catalog:",
|
||||
"read-yaml-file": "catalog:",
|
||||
|
||||
@@ -140,7 +140,7 @@ export async function handler (
|
||||
await checkPeerDeps(cwd, opts)
|
||||
|
||||
const newManifest = opts.rootProjectManifest ?? {}
|
||||
await addLinkToManifest(opts, newManifest, cwd, linkOpts.dir)
|
||||
await addLinkToManifest(opts, newManifest, cwd, opts.rootProjectManifestDir)
|
||||
await writeProjectManifest(newManifest)
|
||||
await install.handler({
|
||||
...linkOpts,
|
||||
@@ -157,7 +157,7 @@ export async function handler (
|
||||
const newManifest = opts.rootProjectManifest ?? {}
|
||||
await Promise.all(
|
||||
pkgPaths.map(async (dir) => {
|
||||
await addLinkToManifest(opts, newManifest, dir, opts.dir)
|
||||
await addLinkToManifest(opts, newManifest, dir, opts.rootProjectManifestDir)
|
||||
await checkPeerDeps(dir, opts)
|
||||
})
|
||||
)
|
||||
@@ -170,7 +170,7 @@ export async function handler (
|
||||
})
|
||||
}
|
||||
|
||||
async function addLinkToManifest (opts: ReadProjectManifestOpts, manifest: ProjectManifest, linkedDepDir: string, dependentDir: string) {
|
||||
async function addLinkToManifest (opts: ReadProjectManifestOpts, manifest: ProjectManifest, linkedDepDir: string, manifestDir: string) {
|
||||
if (!manifest.pnpm) {
|
||||
manifest.pnpm = {
|
||||
overrides: {},
|
||||
@@ -180,7 +180,7 @@ async function addLinkToManifest (opts: ReadProjectManifestOpts, manifest: Proje
|
||||
}
|
||||
const { manifest: linkedManifest } = await tryReadProjectManifest(linkedDepDir, opts)
|
||||
const linkedPkgName = linkedManifest?.name ?? path.basename(linkedDepDir)
|
||||
const linkedPkgSpec = `link:${path.relative(dependentDir, linkedDepDir)}`
|
||||
const linkedPkgSpec = `link:${path.relative(manifestDir, linkedDepDir)}`
|
||||
manifest.pnpm.overrides![linkedPkgName] = linkedPkgSpec
|
||||
if (DEPENDENCIES_FIELDS.every((depField) => manifest[depField]?.[linkedPkgName] == null)) {
|
||||
manifest.dependencies = manifest.dependencies ?? {}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { install, link } from '@pnpm/plugin-commands-installation'
|
||||
import { prepare, preparePackages } from '@pnpm/prepare'
|
||||
import { isExecutable } from '@pnpm/assert-project'
|
||||
import { prepare, preparePackages, prepareEmpty } from '@pnpm/prepare'
|
||||
import { isExecutable, assertProject } from '@pnpm/assert-project'
|
||||
import { fixtures } from '@pnpm/test-fixtures'
|
||||
import { logger } from '@pnpm/logger'
|
||||
import { sync as loadJsonFile } from 'load-json-file'
|
||||
@@ -10,6 +10,8 @@ import PATH from 'path-name'
|
||||
import writePkg from 'write-pkg'
|
||||
import { DEFAULT_OPTS } from './utils'
|
||||
import { type PnpmError } from '@pnpm/error'
|
||||
import { sync as writeYamlFile } from 'write-yaml-file'
|
||||
import normalize from 'normalize-path'
|
||||
|
||||
const f = fixtures(__dirname)
|
||||
|
||||
@@ -355,3 +357,56 @@ test('link: fail when global bin directory is not found', async () => {
|
||||
}
|
||||
expect(err.code).toBe('ERR_PNPM_NO_GLOBAL_BIN_DIR')
|
||||
})
|
||||
|
||||
test('relative link from workspace package', async () => {
|
||||
prepareEmpty()
|
||||
|
||||
const rootProjectManifest = {
|
||||
name: 'project',
|
||||
version: '1.0.0',
|
||||
dependencies: {
|
||||
'@pnpm.e2e/hello-world-js-bin': '*',
|
||||
},
|
||||
}
|
||||
await writePkg('workspace/packages/project', rootProjectManifest)
|
||||
const workspaceDir = path.resolve('workspace')
|
||||
writeYamlFile(path.join(workspaceDir, 'pnpm-workspace.yaml'), { packages: ['packages/*'] })
|
||||
|
||||
f.copy('hello-world-js-bin', 'hello-world-js-bin')
|
||||
|
||||
const projectDir = path.resolve('workspace/packages/project')
|
||||
const helloWorldJsBinDir = path.resolve('hello-world-js-bin')
|
||||
|
||||
process.chdir(projectDir)
|
||||
|
||||
await link.handler({
|
||||
...DEFAULT_OPTS,
|
||||
dedupeDirectDeps: false,
|
||||
dir: process.cwd(),
|
||||
globalPkgDir: '',
|
||||
lockfileDir: workspaceDir,
|
||||
rootProjectManifest,
|
||||
rootProjectManifestDir: workspaceDir,
|
||||
workspaceDir,
|
||||
workspacePackagePatterns: ['packages/*'],
|
||||
}, ['../../../hello-world-js-bin'])
|
||||
|
||||
const manifest = loadJsonFile<{ pnpm?: { overrides?: Record<string, string> } }>(path.join(workspaceDir, 'package.json'))
|
||||
expect(normalize(manifest.pnpm?.overrides?.['@pnpm.e2e/hello-world-js-bin'] ?? '')).toBe('link:../hello-world-js-bin')
|
||||
|
||||
const workspace = assertProject(workspaceDir)
|
||||
;[workspace.readLockfile(), workspace.readCurrentLockfile()].forEach(lockfile => {
|
||||
expect(normalize(lockfile.importers['.'].dependencies?.['@pnpm.e2e/hello-world-js-bin'].version ?? ''))
|
||||
.toBe('link:../hello-world-js-bin')
|
||||
expect(normalize(lockfile.importers['packages/project'].dependencies?.['@pnpm.e2e/hello-world-js-bin'].version ?? ''))
|
||||
.toBe('link:../../../hello-world-js-bin')
|
||||
})
|
||||
|
||||
const validateSymlink = (basePath: string) => {
|
||||
process.chdir(path.join(basePath, 'node_modules', '@pnpm.e2e'))
|
||||
expect(path.resolve(fs.readlinkSync('hello-world-js-bin'))).toBe(helloWorldJsBinDir)
|
||||
}
|
||||
|
||||
validateSymlink(workspaceDir)
|
||||
validateSymlink(projectDir)
|
||||
})
|
||||
|
||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -5370,6 +5370,9 @@ importers:
|
||||
'@pnpm/workspace.filter-packages-from-dir':
|
||||
specifier: workspace:*
|
||||
version: link:../../workspace/filter-packages-from-dir
|
||||
'@types/normalize-path':
|
||||
specifier: 'catalog:'
|
||||
version: 3.0.2
|
||||
'@types/proxyquire':
|
||||
specifier: 'catalog:'
|
||||
version: 1.3.31
|
||||
@@ -5394,6 +5397,9 @@ importers:
|
||||
jest-diff:
|
||||
specifier: 'catalog:'
|
||||
version: 29.7.0
|
||||
normalize-path:
|
||||
specifier: 'catalog:'
|
||||
version: 3.0.0
|
||||
path-name:
|
||||
specifier: 'catalog:'
|
||||
version: 1.0.0
|
||||
|
||||
Reference in New Issue
Block a user