diff --git a/lib/arborist/load-actual.js b/lib/arborist/load-actual.js index 6c59a064b..43a9e65ca 100644 --- a/lib/arborist/load-actual.js +++ b/lib/arborist/load-actual.js @@ -27,6 +27,7 @@ const _cache = Symbol('nodeLoadingCache') const _loadActualVirtually = Symbol('loadActualVirtually') const _loadActualActually = Symbol('loadActualActually') const _transplant = Symbol('transplant') +const _transplantFilter = Symbol('transplantFilter') const _filter = Symbol('filter') const _global = Symbol.for('global') @@ -69,8 +70,14 @@ module.exports = cls => class ActualLoader extends cls { if (this.actualTree) return this.actualTree - const { global = false, filter = () => true, root = null } = options + const { + global = false, + filter = () => true, + root = null, + transplantFilter = () => true, + } = options this[_filter] = filter + this[_transplantFilter] = transplantFilter if (global) { const real = await realpath(this.path, this[_rpcache], this[_stcache]) const newNodeOrLink = this.path === real ? _newNode : _newLink @@ -132,8 +139,8 @@ module.exports = cls => class ActualLoader extends cls { await this[_loadFSTree](this.actualTree) this[_findFSParents]() this[_transplant](root) - // only reset the flags if we're not re-rooting, otherwise leave as-is - calcDepFlags(this.actualTree, root === null) + // only reset root flags if we're not re-rooting, otherwise leave as-is + calcDepFlags(this.actualTree, !root) return this.actualTree } @@ -148,7 +155,8 @@ module.exports = cls => class ActualLoader extends cls { node.fsParent = root } for (const node of this.actualTree.children.values()) { - node.parent = root + if (this[_transplantFilter](node)) + node.parent = root } this.actualTree = root } diff --git a/test/arborist/load-actual.js b/test/arborist/load-actual.js index a7a78fbde..deb6f257b 100644 --- a/test/arborist/load-actual.js +++ b/test/arborist/load-actual.js @@ -133,6 +133,29 @@ t.test('load a tree rooted on a different node', async t => { // should look the same, once we strip off the other/fixture paths t.equal(format(printTree(actual)), format(printTree(transp)), 'similar trees') + + // now try with a transplant filter that keeps out the 'a' module + const rootFiltered = new Node({ + meta: await Shrinkwrap.reset({path: other}), + path: other, + realpath: other, + pkg: require(path + '/package.json'), + }) + rootFiltered.extraneous = false + rootFiltered.dev = false + rootFiltered.devOptional = false + rootFiltered.optional = false + rootFiltered.peer = false + const transpFilter = await new Arborist({path}).loadActual({ + root: rootFiltered, + transplantFilter: n => n.name !== 'a' + }) + t.equal(transpFilter.children.get('a'), undefined) + t.equal(transpFilter.children.get('b').path, resolve(other, 'node_modules/b')) + t.equal(transpFilter.children.get('c').path, resolve(other, 'node_modules/c')) + t.equal(transpFilter.children.get('a'), undefined) + t.equal(transpFilter.children.get('b').realpath, resolve(other, 'packages/b')) + t.equal(transpFilter.children.get('c').realpath, resolve(other, 'packages/c')) }) t.test('looking outside of cwd', t => {