diff --git a/lib/arborist/build-ideal-tree.js b/lib/arborist/build-ideal-tree.js index 94647727b..08a6e0585 100644 --- a/lib/arborist/build-ideal-tree.js +++ b/lib/arborist/build-ideal-tree.js @@ -110,6 +110,10 @@ module.exports = cls => class IdealTreeBuilder extends Tracker(Virtual(Actual(cl this[_manifests] = new Map() } + get explicitRequests () { + return new Set(this[_explicitRequests]) + } + // public method buildIdealTree (options = {}) { if (this.idealTree) diff --git a/lib/arborist/reify.js b/lib/arborist/reify.js index bb0a11baf..fe82f83d1 100644 --- a/lib/arborist/reify.js +++ b/lib/arborist/reify.js @@ -35,7 +35,6 @@ const promiseCallLimit = require('promise-call-limit') const Ideal = require('./build-ideal-tree.js') const optionalSet = require('../optional-set.js') -const _diff = Symbol('diff') const _retiredPaths = Symbol('retiredPaths') const _retiredUnchanged = Symbol('retiredUnchanged') const _sparseTreeDirs = Symbol('sparseTreeDirs') @@ -109,7 +108,7 @@ module.exports = cls => class Reifier extends Ideal(cls) { this[_scriptShell] = scriptShell this[_savePrefix] = savePrefix - this[_diff] = null + this.diff = null this[_retiredPaths] = {} this[_retiredUnchanged] = {} this[_sparseTreeDirs] = new Set() @@ -169,11 +168,11 @@ module.exports = cls => class Reifier extends Ideal(cls) { // find all the nodes that need to change between the actual // and ideal trees. - this[_diff] = Diff.calculate({ + this.diff = Diff.calculate({ actual: this.actualTree, ideal: this.idealTree, }) - for (const node of this[_diff].removed) { + for (const node of this.diff.removed) { this[_addNodeToTrashList](node) } } @@ -199,7 +198,7 @@ module.exports = cls => class Reifier extends Ideal(cls) { // changed or removed, so that we can rollback if necessary. [_retireShallowNodes] () { const moves = this[_retiredPaths] = {} - for (const diff of this[_diff].children) { + for (const diff of this.diff.children) { if (diff.action === 'CHANGE' || diff.action === 'REMOVE') { // we'll have to clean these up at the end, so add them to the list this[_addNodeToTrashList](diff.actual, true) @@ -259,7 +258,7 @@ module.exports = cls => class Reifier extends Ideal(cls) { [_createSparseTree] () { // if we call this fn again, we look for the previous list // so that we can avoid making the same directory multiple times - const dirs = this[_diff].leaves + const dirs = this.diff.leaves .filter(diff => { return (diff.action === 'ADD' || diff.action === 'CHANGE') && !this[_sparseTreeDirs].has(diff.ideal.path) @@ -289,7 +288,7 @@ module.exports = cls => class Reifier extends Ideal(cls) { // we need to unpack them, read that shrinkwrap file, and then update // the tree by calling loadVirtual with the node as the root. [_loadShrinkwrapsAndUpdateTrees] (seen = new Set()) { - const shrinkwraps = this[_diff].leaves + const shrinkwraps = this.diff.leaves .filter(d => (d.action === 'CHANGE' || d.action === 'ADD') && d.ideal.hasShrinkwrap && !seen.has(d.ideal) && !this[_trashList].has(d.ideal.path)) @@ -498,7 +497,7 @@ module.exports = cls => class Reifier extends Ideal(cls) { const bundlesByDepth = new Map() let maxBundleDepth = -1 dfwalk({ - tree: this[_diff], + tree: this.diff, visit: diff => { const node = diff.ideal if (node && !node.isRoot && node.package.bundleDependencies && @@ -524,7 +523,7 @@ module.exports = cls => class Reifier extends Ideal(cls) { [_unpackNewModules] () { const unpacks = [] dfwalk({ - tree: this[_diff], + tree: this.diff, filter: diff => diff.ideal, visit: diff => { const node = diff.ideal @@ -555,7 +554,7 @@ module.exports = cls => class Reifier extends Ideal(cls) { // shallowest nodes that we moved aside in the first place. const moves = this[_retiredPaths] this[_retiredUnchanged] = {} - return promiseAllRejectLate(this[_diff].children.map(diff => { + return promiseAllRejectLate(this.diff.children.map(diff => { const realFolder = (diff.actual || diff.ideal).path const retireFolder = moves[realFolder] this[_retiredUnchanged][retireFolder] = [] @@ -620,7 +619,7 @@ module.exports = cls => class Reifier extends Ideal(cls) { // deps before attempting to build it itself const installedNodes = [] dfwalk({ - tree: this[_diff], + tree: this.diff, leave: diff => installedNodes.push(diff.ideal), // process adds before changes, ignore removals getChildren: diff => diff && diff.children, diff --git a/test/arborist/build-ideal-tree.js b/test/arborist/build-ideal-tree.js index 9c80eb297..82460203e 100644 --- a/test/arborist/build-ideal-tree.js +++ b/test/arborist/build-ideal-tree.js @@ -205,6 +205,16 @@ t.test('dedupe example - deduped', t => { return t.resolveMatchSnapshot(printIdeal(path), 'dedupe testing') }) +t.test('expose explicitRequest', async t => { + const path = resolve(__dirname, '../fixtures/simple') + const arb = new Arborist({ path }) + const tree = await arb.buildIdealTree({ add: [ 'abbrev' ] }) + t.ok(arb.explicitRequests, 'exposes the explicit request') + t.strictSame(arb.explicitRequests, new Set(['abbrev'])) + t.ok(arb.explicitRequests.has('abbrev'), 'should contain explicit item') + t.end() +}) + t.test('bundle deps example 1', t => { // NB: this results in ignoring the bundled deps when building the // ideal tree. When we reify, we'll have to ignore the deps that diff --git a/test/arborist/reify.js b/test/arborist/reify.js index 8c642a422..e3783953a 100644 --- a/test/arborist/reify.js +++ b/test/arborist/reify.js @@ -200,7 +200,9 @@ t.test('update a bundling node without updating all of its deps', t => { t.test('omit optional dep', t => { const path = fixture(t, 'tap-react15-collision-legacy-sw') const ignoreScripts = true - return new Arborist({ path, ignoreScripts }).reify({ omit: ['optional'] }) + + const arb = new Arborist({ path, ignoreScripts }) + return arb.reify({ omit: ['optional'] }) .then(tree => { t.equal(tree.children.get('fsevents'), undefined, 'no fsevents in tree') t.throws(() => fs.statSync(path + '/node_modules/fsevents'), 'no fsevents unpacked') @@ -209,6 +211,7 @@ t.test('omit optional dep', t => { optional: true, }, 'fsevents present in lockfile') }) + .then(() => t.ok(arb.diff, 'has a diff tree')) }) t.test('dev, optional, devOptional flags and omissions', t => { diff --git a/test/fixtures/simple/package.json b/test/fixtures/simple/package.json new file mode 100644 index 000000000..7a8fc947f --- /dev/null +++ b/test/fixtures/simple/package.json @@ -0,0 +1,4 @@ +{ + "name": "simple", + "version": "2.0.0" +}