diff --git a/lib/commands/query.js b/lib/commands/query.js index 371fddef9b440..60294acaf4a68 100644 --- a/lib/commands/query.js +++ b/lib/commands/query.js @@ -58,6 +58,7 @@ class Query extends BaseCommand { const opts = { ...this.npm.flatOptions, path: where, + forceActual: true, } const arb = new Arborist(opts) const tree = await arb.loadActual(opts) diff --git a/workspaces/arborist/lib/arborist/load-actual.js b/workspaces/arborist/lib/arborist/load-actual.js index d4eabe8c0fdfd..bca7cef9476ff 100644 --- a/workspaces/arborist/lib/arborist/load-actual.js +++ b/workspaces/arborist/lib/arborist/load-actual.js @@ -115,6 +115,7 @@ module.exports = cls => class ActualLoader extends cls { root = null, transplantFilter = () => true, ignoreMissing = false, + forceActual = false, } = options this[_filter] = filter this[_transplantFilter] = transplantFilter @@ -141,26 +142,30 @@ module.exports = cls => class ActualLoader extends cls { this[_actualTree].assertRootOverrides() - // Note: hidden lockfile will be rejected if it's not the latest thing - // in the folder, or if any of the entries in the hidden lockfile are - // missing. - const meta = await Shrinkwrap.load({ - path: this[_actualTree].path, - hiddenLockfile: true, - resolveOptions: this.options, - }) - if (meta.loadedFromDisk) { - this[_actualTree].meta = meta - return this[_loadActualVirtually]({ root }) - } else { + // if forceActual is set, don't even try the hidden lockfile + if (!forceActual) { + // Note: hidden lockfile will be rejected if it's not the latest thing + // in the folder, or if any of the entries in the hidden lockfile are + // missing. const meta = await Shrinkwrap.load({ path: this[_actualTree].path, - lockfileVersion: this.options.lockfileVersion, + hiddenLockfile: true, resolveOptions: this.options, }) - this[_actualTree].meta = meta - return this[_loadActualActually]({ root, ignoreMissing }) + + if (meta.loadedFromDisk) { + this[_actualTree].meta = meta + return this[_loadActualVirtually]({ root }) + } } + + const meta = await Shrinkwrap.load({ + path: this[_actualTree].path, + lockfileVersion: this.options.lockfileVersion, + resolveOptions: this.options, + }) + this[_actualTree].meta = meta + return this[_loadActualActually]({ root, ignoreMissing }) } async [_loadActualVirtually] ({ root }) { diff --git a/workspaces/arborist/tap-snapshots/test/arborist/load-actual.js.test.cjs b/workspaces/arborist/tap-snapshots/test/arborist/load-actual.js.test.cjs index b7177c7d248f6..35ba9f7cafa84 100644 --- a/workspaces/arborist/tap-snapshots/test/arborist/load-actual.js.test.cjs +++ b/workspaces/arborist/tap-snapshots/test/arborist/load-actual.js.test.cjs @@ -1084,6 +1084,39 @@ ArboristNode { } ` +exports[`test/arborist/load-actual.js TAP do not load from a hidden lockfile when forceActual is set > must match snapshot 1`] = ` +ArboristNode { + "children": Map { + "abbrev" => ArboristNode { + "edgesIn": Set { + EdgeIn { + "from": "", + "name": "abbrev", + "spec": "^1.1.1", + "type": "prod", + }, + }, + "location": "node_modules/abbrev", + "name": "abbrev", + "path": "hidden-lockfile/node_modules/abbrev", + "version": "1.1.1", + }, + }, + "edgesOut": Map { + "abbrev" => EdgeOut { + "name": "abbrev", + "spec": "^1.1.1", + "to": "node_modules/abbrev", + "type": "prod", + }, + }, + "isProjectRoot": true, + "location": "", + "name": "hidden-lockfile", + "path": "hidden-lockfile", +} +` + exports[`test/arborist/load-actual.js TAP external-dep/root > loaded tree 1`] = ` ArboristNode { "edgesOut": Map { @@ -3760,7 +3793,7 @@ ArboristNode { } ` -exports[`test/arborist/load-actual.js TAP load from a hidden lockfile > expect resolving Promise 1`] = ` +exports[`test/arborist/load-actual.js TAP load from a hidden lockfile > must match snapshot 1`] = ` ArboristNode { "children": Map { "abbrev" => ArboristNode { diff --git a/workspaces/arborist/test/arborist/load-actual.js b/workspaces/arborist/test/arborist/load-actual.js index 8b84bb330ad25..72ab5e60fbf38 100644 --- a/workspaces/arborist/test/arborist/load-actual.js +++ b/workspaces/arborist/test/arborist/load-actual.js @@ -199,8 +199,17 @@ t.test('missing symlinks', t => 'bar has error') })) -t.test('load from a hidden lockfile', t => - t.resolveMatchSnapshot(loadActual(resolve(fixtures, 'hidden-lockfile')))) +t.test('load from a hidden lockfile', async (t) => { + const tree = await loadActual(resolve(fixtures, 'hidden-lockfile')) + t.ok(tree.meta.loadedFromDisk, 'meta was loaded from disk') + t.matchSnapshot(tree) +}) + +t.test('do not load from a hidden lockfile when forceActual is set', async (t) => { + const tree = await loadActual(resolve(fixtures, 'hidden-lockfile'), { forceActual: true }) + t.not(tree.meta.loadedFromDisk, 'meta was NOT loaded from disk') + t.matchSnapshot(tree) +}) t.test('load a global space', t => t.resolveMatchSnapshot(loadActual(resolve(fixtures, 'global-style/lib'), {