Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add dir option support in link <pkg> --global #5473

Merged
merged 4 commits into from Oct 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/few-ghosts-rule.md
@@ -0,0 +1,6 @@
---
"@pnpm/plugin-commands-installation": patch
"pnpm": patch
---

`pnpm link <pkg> --global` should work when a custom target directory is specified with the `--dir` CLI option [#5473](https://github.com/pnpm/pnpm/pull/5473).
5 changes: 5 additions & 0 deletions .changeset/heavy-tools-agree.md
@@ -0,0 +1,5 @@
---
"@pnpm/core": patch
---

Fix WARN undefined has no binaries
2 changes: 1 addition & 1 deletion packages/core/src/install/index.ts
Expand Up @@ -1005,7 +1005,7 @@ const _installInContext: InstallFunction = async (projects, ctx, opts) => {
if (opts.global && projectToInstall.mutation.includes('install')) {
projectToInstall.wantedDependencies.forEach(pkg => {
if (!linkedPackages?.includes(pkg.alias)) {
logger.warn({ message: `${pkg.alias} has no binaries`, prefix: opts.lockfileDir })
logger.warn({ message: `${pkg.alias ?? pkg.pref} has no binaries`, prefix: opts.lockfileDir })
}
})
}
Expand Down
8 changes: 5 additions & 3 deletions packages/plugin-commands-installation/src/link.ts
Expand Up @@ -113,6 +113,8 @@ export async function handler (
workspacePackages,
})

const linkCwdDir = opts.cliOptions?.dir && opts.cliOptions?.global ? path.resolve(opts.cliOptions.dir) : cwd

// pnpm link
if ((params == null) || (params.length === 0)) {
if (path.relative(linkOpts.dir, cwd) === '') {
Expand All @@ -121,7 +123,7 @@ export async function handler (
const { manifest, writeProjectManifest } = await tryReadProjectManifest(opts.dir, opts)
const newManifest = await addDependenciesToPackage(
manifest ?? {},
[`link:${opts.cliOptions?.dir ? path.resolve(opts.cliOptions.dir) : cwd}`],
[`link:${linkCwdDir}`],
linkOpts
)
await writeProjectManifest(newManifest)
Expand Down Expand Up @@ -179,7 +181,7 @@ export async function handler (
globalPkgNames.forEach((pkgName) => pkgPaths.push(path.join(globalPkgPath, 'node_modules', pkgName)))
}

const { manifest, writeProjectManifest } = await readProjectManifest(cwd, opts)
const { manifest, writeProjectManifest } = await readProjectManifest(linkCwdDir, opts)

const linkConfig = await getConfig(
{ ...opts.cliOptions, dir: cwd },
Expand All @@ -190,7 +192,7 @@ export async function handler (
}
)
const storeL = await createOrConnectStoreControllerCached(storeControllerCache, linkConfig)
const newManifest = await link(pkgPaths, path.join(cwd, 'node_modules'), {
const newManifest = await link(pkgPaths, path.join(linkCwdDir, 'node_modules'), {
...linkConfig,
targetDependenciesField: linkOpts.targetDependenciesField,
storeController: storeL.ctrl,
Expand Down
49 changes: 48 additions & 1 deletion packages/plugin-commands-installation/test/link.ts
Expand Up @@ -64,6 +64,9 @@ test('link global bin', async function () {

await link.handler({
...DEFAULT_OPTS,
cliOptions: {
global: true,
},
bin: globalBin,
dir: globalDir,
})
Expand All @@ -72,7 +75,7 @@ test('link global bin', async function () {
await isExecutable((value) => expect(value).toBeTruthy(), path.join(globalBin, 'package-with-bin'))
})

test('link --dir global bin', async function () {
test('link to global bin from the specified directory', async function () {
prepare()
process.chdir('..')

Expand All @@ -88,6 +91,7 @@ test('link --dir global bin', async function () {
await link.handler({
...DEFAULT_OPTS,
cliOptions: {
global: true,
dir: path.resolve('./dir/package-with-bin-in-dir'),
},
bin: globalBin,
Expand All @@ -98,6 +102,49 @@ test('link --dir global bin', async function () {
await isExecutable((value) => expect(value).toBeTruthy(), path.join(globalBin, 'package-with-bin-in-dir'))
})

test('link a global package to the specified directory', async function () {
const project = prepare()
process.chdir('..')

const globalDir = path.resolve('global')
const globalBin = path.join(globalDir, 'bin')
const oldPath = process.env[PATH]
process.env[PATH] = `${globalBin}${path.delimiter}${oldPath ?? ''}`
await fs.mkdir(globalBin, { recursive: true })

await writePkg('global-package-with-bin', { name: 'global-package-with-bin', version: '1.0.0', bin: 'bin.js' })
await fs.writeFile('global-package-with-bin/bin.js', '#!/usr/bin/env node\nconsole.log(/hi/)\n', 'utf8')

process.chdir('global-package-with-bin')

// link to global
await link.handler({
...DEFAULT_OPTS,
cliOptions: {
global: true,
},
bin: globalBin,
dir: globalDir,
})

process.chdir('..')

// link from global
await link.handler({
...DEFAULT_OPTS,
cliOptions: {
global: true,
dir: path.resolve('./project'),
},
bin: globalBin,
dir: globalDir,
}, ['global-package-with-bin'])

process.env[PATH] = oldPath

await project.has('global-package-with-bin')
})

test('relative link', async () => {
const project = prepare({
dependencies: {
Expand Down