From da98092afe8abe2df72ea36a5b87ceb4cc4fd9f2 Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Thu, 10 Jun 2021 17:11:08 -0400 Subject: [PATCH] fix(link): do not prune packages `npm link ` 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: https://github.com/npm/cli/issues/2554 --- lib/link.js | 2 ++ test/lib/link.js | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/lib/link.js b/lib/link.js index 47fe4b17a272b..d6abf139730bd 100644 --- a/lib/link.js +++ b/lib/link.js @@ -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)}`), diff --git a/test/lib/link.js b/test/lib/link.js index 3cad0ff90362d..64375cfc13c2c 100644 --- a/test/lib/link.js +++ b/test/lib/link.js @@ -1,4 +1,5 @@ const { resolve } = require('path') +const fs = require('fs') const Arborist = require('@npmcli/arborist') const t = require('tap') @@ -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': {