Skip to content

Commit

Permalink
fix(link): do not prune packages
Browse files Browse the repository at this point in the history
`npm link <pkg>` is meant to be used as a way to link a local package to
an install tree and it's very surprising to users that it may prune
extraneous deps from the project.

This change switches the default behavior to avoid pruning deps when
reifying the dependencies in npm link.

Fixes: #2554

PR-URL: #3399
Credit: @ruyadorno
Close: #3399
Reviewed-by: @ljharb, @nlf
  • Loading branch information
ruyadorno authored and wraithgar committed Jun 11, 2021
1 parent 3f202cd commit 40829ec
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,14 @@ class Link extends ArboristWorkspaceCmd {
// reify all the pending names as symlinks there
const localArb = new Arborist({
...this.npm.flatOptions,
prune: false,
log: this.npm.log,
path: this.npm.prefix,
save,
})
await localArb.reify({
...this.npm.flatOptions,
prune: false,
path: this.npm.prefix,
log: this.npm.log,
add: names.map(l => `file:${resolve(globalTop, 'node_modules', l)}`),
Expand Down
50 changes: 50 additions & 0 deletions test/lib/link.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { resolve } = require('path')
const fs = require('fs')

const Arborist = require('@npmcli/arborist')
const t = require('tap')
Expand Down Expand Up @@ -485,6 +486,55 @@ t.test('link pkg already in global space when prefix is a symlink', (t) => {
})
})

t.test('should not prune dependencies when linking packages', async t => {
const testdir = t.testdir({
'global-prefix': {
lib: {
node_modules: {
linked: t.fixture('symlink', '../../../linked'),
},
},
},
linked: {
'package.json': JSON.stringify({
name: 'linked',
version: '1.0.0',
}),
},
'my-project': {
node_modules: {
foo: {
'package.json': JSON.stringify({ name: 'foo', version: '1.0.0' }),
},
},
'package.json': JSON.stringify({
name: 'my-project',
version: '1.0.0',
}),
},
})
npm.globalDir = resolve(testdir, 'global-prefix', 'lib', 'node_modules')
npm.prefix = resolve(testdir, 'my-project')
reifyOutput = () => {}

const _cwd = process.cwd()
process.chdir(npm.prefix)

await new Promise((res, rej) => {
link.exec(['linked'], (err) => {
if (err)
rej(err)
res()
})
})

t.ok(
fs.statSync(resolve(testdir, 'my-project/node_modules/foo')),
'should not prune any extraneous dep when running npm link'
)
process.chdir(_cwd)
})

t.test('completion', async t => {
const testdir = t.testdir({
'global-prefix': {
Expand Down

0 comments on commit 40829ec

Please sign in to comment.