Skip to content

Commit 73820c6

Browse files
committed
fix: include ideally inert in diff
1 parent 91393de commit 73820c6

File tree

4 files changed

+34
-36
lines changed

4 files changed

+34
-36
lines changed

workspaces/arborist/lib/arborist/build-ideal-tree.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
192192
}
193193

194194
async #checkEngineAndPlatform () {
195-
const { engineStrict, npmVersion, nodeVersion, omit = [] } = this.options
195+
const { engineStrict, npmVersion, nodeVersion, omit = [], cpu, os, libc } = this.options
196196
const omitSet = new Set(omit)
197197

198198
for (const node of this.idealTree.inventory.values()) {
@@ -214,6 +214,19 @@ module.exports = cls => class IdealTreeBuilder extends cls {
214214
}
215215
checkPlatform(node.package, this.options.force)
216216
}
217+
if (node.optional && !node.ideallyInert) {
218+
// Mark any optional packages we can't install as ideally inert.
219+
// We ignore the --force and --engine-strict flags.
220+
try {
221+
checkEngine(node.package, npmVersion, nodeVersion, false)
222+
checkPlatform(node.package, false, { cpu, os, libc })
223+
} catch (error) {
224+
const set = optionalSet(node)
225+
for (const node of set) {
226+
node.ideallyInert = true
227+
}
228+
}
229+
}
217230
}
218231
}
219232

workspaces/arborist/lib/arborist/reify.js

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ const pacote = require('pacote')
77
const promiseAllRejectLate = require('promise-all-reject-late')
88
const runScript = require('@npmcli/run-script')
99
const { callLimit: promiseCallLimit } = require('promise-call-limit')
10-
const { checkEngine, checkPlatform } = require('npm-install-checks')
1110
const { depth: dfwalk } = require('treeverse')
1211
const { dirname, resolve, relative, join } = require('node:path')
1312
const { log, time } = require('proc-log')
@@ -228,18 +227,6 @@ module.exports = cls => class Reifier extends cls {
228227
this.idealTree.meta.hiddenLockfile = true
229228
this.idealTree.meta.lockfileVersion = defaultLockfileVersion
230229

231-
// Preserve inertness for failed stuff.
232-
if (this.actualTree) {
233-
for (const [loc, actual] of this.actualTree.inventory.entries()) {
234-
if (actual.ideallyInert) {
235-
const ideal = this.idealTree.inventory.get(loc)
236-
if (ideal) {
237-
ideal.ideallyInert = true
238-
}
239-
}
240-
}
241-
}
242-
243230
this.actualTree = this.idealTree
244231
this.idealTree = null
245232

@@ -566,9 +553,6 @@ module.exports = cls => class Reifier extends cls {
566553
// retire the same path at the same time.
567554
const dirsChecked = new Set()
568555
return promiseAllRejectLate(leaves.map(async node => {
569-
if (node.ideallyInert) {
570-
return
571-
}
572556
for (const d of walkUp(node.path)) {
573557
if (d === node.top.path) {
574558
break
@@ -662,18 +646,7 @@ module.exports = cls => class Reifier extends cls {
662646
const timeEnd = time.start(`reifyNode:${node.location}`)
663647
this.addTracker('reify', node.name, node.location)
664648

665-
const { npmVersion, nodeVersion, cpu, os, libc } = this.options
666649
const p = Promise.resolve().then(async () => {
667-
// when we reify an optional node, check the engine and platform
668-
// first. be sure to ignore the --force and --engine-strict flags,
669-
// since we always want to skip any optional packages we can't install.
670-
// these checks throwing will result in a rollback and removal
671-
// of the mismatches
672-
// eslint-disable-next-line promise/always-return
673-
if (node.optional) {
674-
checkEngine(node.package, npmVersion, nodeVersion, false)
675-
checkPlatform(node.package, false, { cpu, os, libc })
676-
}
677650
await this[_checkBins](node)
678651
await this.#extractOrLink(node)
679652
const { _id, deprecated } = node.package
@@ -707,10 +680,6 @@ module.exports = cls => class Reifier extends cls {
707680
}
708681

709682
async #extractOrLink (node) {
710-
if (node.ideallyInert) {
711-
return
712-
}
713-
714683
const nm = resolve(node.parent.path, 'node_modules')
715684
await this.#validateNodeModules(nm)
716685

@@ -791,7 +760,7 @@ module.exports = cls => class Reifier extends cls {
791760
[_handleOptionalFailure] (node, p) {
792761
return (node.optional ? p.catch(() => {
793762
const set = optionalSet(node)
794-
for (node of set) {
763+
for (const node of set) {
795764
log.verbose('reify', 'failed optional dependency', node.path)
796765
node.ideallyInert = true
797766
this[_addNodeToTrashList](node)
@@ -1165,9 +1134,6 @@ module.exports = cls => class Reifier extends cls {
11651134

11661135
this.#retiredUnchanged[retireFolder] = []
11671136
return promiseAllRejectLate(diff.unchanged.map(node => {
1168-
if (node.ideallyInert) {
1169-
return
1170-
}
11711137
// no need to roll back links, since we'll just delete them anyway
11721138
if (node.isLink) {
11731139
return mkdir(dirname(node.path), { recursive: true, force: true })

workspaces/arborist/lib/diff.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,17 @@ const diffNode = ({
257257
return
258258
}
259259

260+
// Treat inert nodes as undefined for the purposes of diffing.
261+
if (actual?.ideallyInert) {
262+
actual = undefined
263+
}
264+
if (ideal?.ideallyInert) {
265+
ideal = undefined
266+
}
267+
if (!actual && !ideal) {
268+
return
269+
}
270+
260271
const action = getAction({ actual, ideal, omit, omitted })
261272

262273
// if it's a match, then get its children

workspaces/arborist/test/arborist/reify.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,14 @@ t.test('do not install optional deps with mismatched platform specifications', a
496496
await t.resolveMatchSnapshot(printReified(fixture(t, 'optional-platform-specification')))
497497
})
498498

499+
t.test('do not report failed optional deps as installed', async t => {
500+
createRegistry(t, true)
501+
const path = fixture(t, 'optional-platform-specification')
502+
const arb = newArb({ path })
503+
await arb.reify()
504+
t.equal(arb.diff.children.length, 0, 'no changes, nothing installed')
505+
})
506+
499507
t.test('still do not install optional deps with mismatched platform specifications even when forced', async t => {
500508
createRegistry(t, true)
501509
await t.resolveMatchSnapshot(printReified(fixture(t, 'optional-platform-specification'), { force: true }))

0 commit comments

Comments
 (0)