@npmcli/arborist 2.8.2 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/actual.js +4 -2
- package/bin/audit.js +12 -6
- package/bin/dedupe.js +6 -3
- package/bin/funding.js +4 -2
- package/bin/ideal.js +2 -1
- package/bin/lib/logging.js +4 -3
- package/bin/lib/options.js +14 -12
- package/bin/lib/timers.js +6 -3
- package/bin/license.js +9 -5
- package/bin/prune.js +6 -3
- package/bin/reify.js +6 -3
- package/bin/virtual.js +4 -2
- package/lib/add-rm-pkg-deps.js +28 -15
- package/lib/arborist/audit.js +2 -1
- package/lib/arborist/build-ideal-tree.js +139 -72
- package/lib/arborist/deduper.js +2 -1
- package/lib/arborist/index.js +8 -4
- package/lib/arborist/load-actual.js +28 -13
- package/lib/arborist/load-virtual.js +37 -20
- package/lib/arborist/load-workspaces.js +4 -2
- package/lib/arborist/rebuild.js +34 -17
- package/lib/arborist/reify.js +153 -76
- package/lib/audit-report.js +44 -23
- package/lib/calc-dep-flags.js +18 -9
- package/lib/can-place-dep.js +59 -30
- package/lib/case-insensitive-map.js +4 -2
- package/lib/consistent-resolve.js +2 -1
- package/lib/deepest-nesting-target.js +4 -2
- package/lib/dep-valid.js +8 -4
- package/lib/diff.js +74 -22
- package/lib/edge.js +26 -13
- package/lib/gather-dep-set.js +2 -1
- package/lib/inventory.js +12 -6
- package/lib/link.js +14 -9
- package/lib/node.js +216 -113
- package/lib/optional-set.js +4 -2
- package/lib/peer-entry-sets.js +10 -5
- package/lib/place-dep.js +111 -37
- package/lib/printable.js +46 -25
- package/lib/realpath.js +12 -6
- package/lib/shrinkwrap.js +164 -90
- package/lib/signal-handling.js +6 -3
- package/lib/spec-from-lock.js +7 -4
- package/lib/tracker.js +24 -18
- package/lib/tree-check.js +12 -6
- package/lib/version-from-tgz.js +4 -2
- package/lib/vuln.js +44 -22
- package/lib/yarn-lock.js +34 -21
- package/package.json +8 -10
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// mixin implementing the buildIdealTree method
|
|
2
|
+
const localeCompare = require('@isaacs/string-locale-compare')('en')
|
|
2
3
|
const rpj = require('read-package-json-fast')
|
|
3
4
|
const npa = require('npm-package-arg')
|
|
4
5
|
const pacote = require('pacote')
|
|
@@ -137,8 +138,9 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
137
138
|
this[_globalStyle] = this[_global] || globalStyle
|
|
138
139
|
this[_follow] = !!follow
|
|
139
140
|
|
|
140
|
-
if (this[_workspaces].length && this[_global])
|
|
141
|
+
if (this[_workspaces].length && this[_global]) {
|
|
141
142
|
throw new Error('Cannot operate on workspaces in global mode')
|
|
143
|
+
}
|
|
142
144
|
|
|
143
145
|
this[_explicitRequests] = new Set()
|
|
144
146
|
this[_preferDedupe] = false
|
|
@@ -168,18 +170,21 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
168
170
|
|
|
169
171
|
// public method
|
|
170
172
|
async buildIdealTree (options = {}) {
|
|
171
|
-
if (this.idealTree)
|
|
173
|
+
if (this.idealTree) {
|
|
172
174
|
return Promise.resolve(this.idealTree)
|
|
175
|
+
}
|
|
173
176
|
|
|
174
177
|
// allow the user to set reify options on the ctor as well.
|
|
175
178
|
// XXX: deprecate separate reify() options object.
|
|
176
179
|
options = { ...this.options, ...options }
|
|
177
180
|
|
|
178
181
|
// an empty array or any falsey value is the same as null
|
|
179
|
-
if (!options.add || options.add.length === 0)
|
|
182
|
+
if (!options.add || options.add.length === 0) {
|
|
180
183
|
options.add = null
|
|
181
|
-
|
|
184
|
+
}
|
|
185
|
+
if (!options.rm || options.rm.length === 0) {
|
|
182
186
|
options.rm = null
|
|
187
|
+
}
|
|
183
188
|
|
|
184
189
|
process.emit('time', 'idealTree')
|
|
185
190
|
|
|
@@ -230,11 +235,12 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
230
235
|
|
|
231
236
|
[_checkEngine] (node) {
|
|
232
237
|
const { engineStrict, npmVersion, nodeVersion } = this.options
|
|
233
|
-
const c = () =>
|
|
238
|
+
const c = () =>
|
|
239
|
+
checkEngine(node.package, npmVersion, nodeVersion, this[_force])
|
|
234
240
|
|
|
235
|
-
if (engineStrict)
|
|
241
|
+
if (engineStrict) {
|
|
236
242
|
c()
|
|
237
|
-
else {
|
|
243
|
+
} else {
|
|
238
244
|
try {
|
|
239
245
|
c()
|
|
240
246
|
} catch (er) {
|
|
@@ -252,8 +258,9 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
252
258
|
: Array.isArray(options.update) ? { names: options.update }
|
|
253
259
|
: options.update || {}
|
|
254
260
|
|
|
255
|
-
if (update.all || !Array.isArray(update.names))
|
|
261
|
+
if (update.all || !Array.isArray(update.names)) {
|
|
256
262
|
update.names = []
|
|
263
|
+
}
|
|
257
264
|
|
|
258
265
|
this[_complete] = !!options.complete
|
|
259
266
|
this[_preferDedupe] = !!options.preferDedupe
|
|
@@ -283,8 +290,9 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
283
290
|
: rpj(this.path + '/package.json').then(
|
|
284
291
|
pkg => this[_rootNodeFromPackage](pkg),
|
|
285
292
|
er => {
|
|
286
|
-
if (er.code === 'EJSONPARSE')
|
|
293
|
+
if (er.code === 'EJSONPARSE') {
|
|
287
294
|
throw er
|
|
295
|
+
}
|
|
288
296
|
return this[_rootNodeFromPackage]({})
|
|
289
297
|
}
|
|
290
298
|
))
|
|
@@ -312,8 +320,9 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
312
320
|
// even though we didn't load it from a package-lock.json FILE,
|
|
313
321
|
// we still loaded it "from disk", meaning we have to reset
|
|
314
322
|
// dep flags before assuming that any mutations were reflected.
|
|
315
|
-
if (tree.children.size)
|
|
323
|
+
if (tree.children.size) {
|
|
316
324
|
root.meta.loadedFromDisk = true
|
|
325
|
+
}
|
|
317
326
|
}
|
|
318
327
|
return root
|
|
319
328
|
})
|
|
@@ -382,9 +391,9 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
382
391
|
process.emit('time', 'idealTree:userRequests')
|
|
383
392
|
const tree = this.idealTree.target
|
|
384
393
|
|
|
385
|
-
if (!this[_workspaces].length)
|
|
394
|
+
if (!this[_workspaces].length) {
|
|
386
395
|
await this[_applyUserRequestsToNode](tree, options)
|
|
387
|
-
else {
|
|
396
|
+
} else {
|
|
388
397
|
await Promise.all(this.workspaceNodes(tree, this[_workspaces])
|
|
389
398
|
.map(node => this[_applyUserRequestsToNode](node, options)))
|
|
390
399
|
}
|
|
@@ -396,8 +405,9 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
396
405
|
// If we have a list of package names to update, and we know it's
|
|
397
406
|
// going to update them wherever they are, add any paths into those
|
|
398
407
|
// named nodes to the buildIdealTree queue.
|
|
399
|
-
if (!this[_global] && this[_updateNames].length)
|
|
408
|
+
if (!this[_global] && this[_updateNames].length) {
|
|
400
409
|
this[_queueNamedUpdates]()
|
|
410
|
+
}
|
|
401
411
|
|
|
402
412
|
// global updates only update the globalTop nodes, but we need to know
|
|
403
413
|
// that they're there, and not reinstall the world unnecessarily.
|
|
@@ -408,46 +418,55 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
408
418
|
tree.package.dependencies = tree.package.dependencies || {}
|
|
409
419
|
const updateName = this[_updateNames].includes(name)
|
|
410
420
|
if (this[_updateAll] || updateName) {
|
|
411
|
-
if (updateName)
|
|
421
|
+
if (updateName) {
|
|
412
422
|
globalExplicitUpdateNames.push(name)
|
|
423
|
+
}
|
|
413
424
|
const dir = resolve(nm, name)
|
|
414
|
-
const st = await lstat(dir)
|
|
425
|
+
const st = await lstat(dir)
|
|
426
|
+
.catch(/* istanbul ignore next */ er => null)
|
|
415
427
|
if (st && st.isSymbolicLink()) {
|
|
416
428
|
const target = await readlink(dir)
|
|
417
429
|
const real = resolve(dirname(dir), target)
|
|
418
430
|
tree.package.dependencies[name] = `file:${real}`
|
|
419
|
-
} else
|
|
431
|
+
} else {
|
|
420
432
|
tree.package.dependencies[name] = '*'
|
|
433
|
+
}
|
|
421
434
|
}
|
|
422
435
|
}
|
|
423
436
|
}
|
|
424
437
|
|
|
425
|
-
if (this.auditReport && this.auditReport.size > 0)
|
|
438
|
+
if (this.auditReport && this.auditReport.size > 0) {
|
|
426
439
|
await this[_queueVulnDependents](options)
|
|
440
|
+
}
|
|
427
441
|
|
|
428
442
|
const { add, rm } = options
|
|
429
443
|
|
|
430
444
|
if (rm && rm.length) {
|
|
431
445
|
addRmPkgDeps.rm(tree.package, rm)
|
|
432
|
-
for (const name of rm)
|
|
446
|
+
for (const name of rm) {
|
|
433
447
|
this[_explicitRequests].add({ from: tree, name, action: 'DELETE' })
|
|
448
|
+
}
|
|
434
449
|
}
|
|
435
450
|
|
|
436
|
-
if (add && add.length)
|
|
451
|
+
if (add && add.length) {
|
|
437
452
|
await this[_add](tree, options)
|
|
453
|
+
}
|
|
438
454
|
|
|
439
455
|
// triggers a refresh of all edgesOut. this has to be done BEFORE
|
|
440
456
|
// adding the edges to explicitRequests, because the package setter
|
|
441
457
|
// resets all edgesOut.
|
|
442
|
-
if (add && add.length || rm && rm.length || this[_global])
|
|
458
|
+
if (add && add.length || rm && rm.length || this[_global]) {
|
|
443
459
|
tree.package = tree.package
|
|
460
|
+
}
|
|
444
461
|
|
|
445
462
|
for (const spec of this[_resolvedAdd]) {
|
|
446
|
-
if (spec.tree === tree)
|
|
463
|
+
if (spec.tree === tree) {
|
|
447
464
|
this[_explicitRequests].add(tree.edgesOut.get(spec.name))
|
|
465
|
+
}
|
|
448
466
|
}
|
|
449
|
-
for (const name of globalExplicitUpdateNames)
|
|
467
|
+
for (const name of globalExplicitUpdateNames) {
|
|
450
468
|
this[_explicitRequests].add(tree.edgesOut.get(name))
|
|
469
|
+
}
|
|
451
470
|
|
|
452
471
|
this[_depsQueue].push(tree)
|
|
453
472
|
}
|
|
@@ -487,21 +506,24 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
487
506
|
// if it's an explicit tag, we need to install that specific tag version
|
|
488
507
|
const isTag = spec.rawSpec && spec.type === 'tag'
|
|
489
508
|
|
|
490
|
-
if (spec.name && !isTag)
|
|
509
|
+
if (spec.name && !isTag) {
|
|
491
510
|
return spec
|
|
511
|
+
}
|
|
492
512
|
|
|
493
513
|
const mani = await pacote.manifest(spec, { ...this.options })
|
|
494
514
|
// if it's a tag type, then we need to run it down to an actual version
|
|
495
|
-
if (isTag)
|
|
515
|
+
if (isTag) {
|
|
496
516
|
return npa(`${mani.name}@${mani.version}`)
|
|
517
|
+
}
|
|
497
518
|
|
|
498
519
|
spec.name = mani.name
|
|
499
520
|
return spec
|
|
500
521
|
}
|
|
501
522
|
|
|
502
523
|
async [_updateFilePath] (spec) {
|
|
503
|
-
if (spec.type === 'file')
|
|
524
|
+
if (spec.type === 'file') {
|
|
504
525
|
return this[_getRelpathSpec](spec, spec.fetchSpec)
|
|
526
|
+
}
|
|
505
527
|
|
|
506
528
|
return spec
|
|
507
529
|
}
|
|
@@ -601,8 +623,9 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
601
623
|
nodesTouched.add(node)
|
|
602
624
|
}
|
|
603
625
|
}
|
|
604
|
-
for (const node of nodesTouched)
|
|
626
|
+
for (const node of nodesTouched) {
|
|
605
627
|
node.package = node.package
|
|
628
|
+
}
|
|
606
629
|
}
|
|
607
630
|
}
|
|
608
631
|
|
|
@@ -611,11 +634,13 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
611
634
|
}
|
|
612
635
|
|
|
613
636
|
[_avoidRange] (name) {
|
|
614
|
-
if (!this.auditReport)
|
|
637
|
+
if (!this.auditReport) {
|
|
615
638
|
return null
|
|
639
|
+
}
|
|
616
640
|
const vuln = this.auditReport.get(name)
|
|
617
|
-
if (!vuln)
|
|
641
|
+
if (!vuln) {
|
|
618
642
|
return null
|
|
643
|
+
}
|
|
619
644
|
return vuln.range
|
|
620
645
|
}
|
|
621
646
|
|
|
@@ -652,8 +677,9 @@ module.exports = cls => class IdealTreeBuilder extends cls {
|
|
|
652
677
|
const ancient = meta.ancientLockfile
|
|
653
678
|
const old = meta.loadedFromDisk && !(meta.originalLockfileVersion >= 2)
|
|
654
679
|
|
|
655
|
-
if (inventory.size === 0 || !ancient && !old)
|
|
680
|
+
if (inventory.size === 0 || !ancient && !old) {
|
|
656
681
|
return
|
|
682
|
+
}
|
|
657
683
|
|
|
658
684
|
// if the lockfile is from node v5 or earlier, then we'll have to reload
|
|
659
685
|
// all the manifests of everything we encounter. this is costly, but at
|
|
@@ -672,8 +698,9 @@ This is a one-time fix-up, please be patient...
|
|
|
672
698
|
this.addTracker('idealTree:inflate')
|
|
673
699
|
const queue = []
|
|
674
700
|
for (const node of inventory.values()) {
|
|
675
|
-
if (node.isProjectRoot)
|
|
701
|
+
if (node.isProjectRoot) {
|
|
676
702
|
continue
|
|
703
|
+
}
|
|
677
704
|
|
|
678
705
|
queue.push(async () => {
|
|
679
706
|
this.log.silly('inflate', node.location)
|
|
@@ -738,13 +765,14 @@ This is a one-time fix-up, please be patient...
|
|
|
738
765
|
this[_currentDep] = null
|
|
739
766
|
}
|
|
740
767
|
|
|
741
|
-
if (!this[_depsQueue].length)
|
|
768
|
+
if (!this[_depsQueue].length) {
|
|
742
769
|
return this[_resolveLinks]()
|
|
770
|
+
}
|
|
743
771
|
|
|
744
772
|
// sort physically shallower deps up to the front of the queue,
|
|
745
773
|
// because they'll affect things deeper in, then alphabetical
|
|
746
774
|
this[_depsQueue].sort((a, b) =>
|
|
747
|
-
(a.depth - b.depth) || a.path
|
|
775
|
+
(a.depth - b.depth) || localeCompare(a.path, b.path))
|
|
748
776
|
|
|
749
777
|
const node = this[_depsQueue].shift()
|
|
750
778
|
const bd = node.package.bundleDependencies
|
|
@@ -757,8 +785,9 @@ This is a one-time fix-up, please be patient...
|
|
|
757
785
|
// satisfied by whatever's in that file anyway.
|
|
758
786
|
if (this[_depsSeen].has(node) ||
|
|
759
787
|
node.root !== this.idealTree ||
|
|
760
|
-
hasShrinkwrap && !this[_complete])
|
|
788
|
+
hasShrinkwrap && !this[_complete]) {
|
|
761
789
|
return this[_buildDepStep]()
|
|
790
|
+
}
|
|
762
791
|
|
|
763
792
|
this[_depsSeen].add(node)
|
|
764
793
|
this[_currentDep] = node
|
|
@@ -841,8 +870,9 @@ This is a one-time fix-up, please be patient...
|
|
|
841
870
|
const tasks = []
|
|
842
871
|
const peerSource = this[_peerSetSource].get(node) || node
|
|
843
872
|
for (const edge of this[_problemEdges](node)) {
|
|
844
|
-
if (edge.overridden)
|
|
873
|
+
if (edge.overridden) {
|
|
845
874
|
continue
|
|
875
|
+
}
|
|
846
876
|
|
|
847
877
|
// peerSetSource is only relevant when we have a peerEntryEdge
|
|
848
878
|
// otherwise we're setting regular non-peer deps as if they have
|
|
@@ -878,15 +908,16 @@ This is a one-time fix-up, please be patient...
|
|
|
878
908
|
|
|
879
909
|
/* istanbul ignore next */
|
|
880
910
|
debug(() => {
|
|
881
|
-
if (!dep)
|
|
911
|
+
if (!dep) {
|
|
882
912
|
throw new Error('no dep??')
|
|
913
|
+
}
|
|
883
914
|
})
|
|
884
915
|
|
|
885
916
|
tasks.push({edge, dep})
|
|
886
917
|
}
|
|
887
918
|
|
|
888
919
|
const placeDeps = tasks
|
|
889
|
-
.sort((a, b) => a.edge.name
|
|
920
|
+
.sort((a, b) => localeCompare(a.edge.name, b.edge.name))
|
|
890
921
|
.map(({ edge, dep }) => new PlaceDep({
|
|
891
922
|
edge,
|
|
892
923
|
dep,
|
|
@@ -912,17 +943,20 @@ This is a one-time fix-up, please be patient...
|
|
|
912
943
|
visit: pd => {
|
|
913
944
|
const { placed, edge, canPlace: cpd } = pd
|
|
914
945
|
// if we didn't place anything, nothing to do here
|
|
915
|
-
if (!placed)
|
|
946
|
+
if (!placed) {
|
|
916
947
|
return
|
|
948
|
+
}
|
|
917
949
|
|
|
918
950
|
// we placed something, that means we changed the tree
|
|
919
|
-
if (placed.errors.length)
|
|
951
|
+
if (placed.errors.length) {
|
|
920
952
|
this[_loadFailures].add(placed)
|
|
953
|
+
}
|
|
921
954
|
this[_mutateTree] = true
|
|
922
955
|
if (cpd.canPlaceSelf === OK) {
|
|
923
956
|
for (const edgeIn of placed.edgesIn) {
|
|
924
|
-
if (edgeIn === edge)
|
|
957
|
+
if (edgeIn === edge) {
|
|
925
958
|
continue
|
|
959
|
+
}
|
|
926
960
|
const { from, valid, overridden } = edgeIn
|
|
927
961
|
if (!overridden && !valid && !this[_depsSeen].has(from)) {
|
|
928
962
|
this.addTracker('idealTree', from.name, from.location)
|
|
@@ -936,8 +970,9 @@ This is a one-time fix-up, please be patient...
|
|
|
936
970
|
// intentionally causing something to get nested which was
|
|
937
971
|
// previously placed in this location.
|
|
938
972
|
for (const edgeIn of placed.edgesIn) {
|
|
939
|
-
if (edgeIn === edge)
|
|
973
|
+
if (edgeIn === edge) {
|
|
940
974
|
continue
|
|
975
|
+
}
|
|
941
976
|
|
|
942
977
|
const { valid, overridden } = edgeIn
|
|
943
978
|
if (!valid && !overridden) {
|
|
@@ -959,8 +994,13 @@ This is a one-time fix-up, please be patient...
|
|
|
959
994
|
return
|
|
960
995
|
}
|
|
961
996
|
|
|
962
|
-
// lastly, also check for the missing deps of the node we placed
|
|
997
|
+
// lastly, also check for the missing deps of the node we placed,
|
|
998
|
+
// and any holes created by pruning out conflicted peer sets.
|
|
963
999
|
this[_depsQueue].push(placed)
|
|
1000
|
+
for (const dep of pd.needEvaluation) {
|
|
1001
|
+
this[_depsSeen].delete(dep)
|
|
1002
|
+
this[_depsQueue].push(dep)
|
|
1003
|
+
}
|
|
964
1004
|
|
|
965
1005
|
// pre-fetch any problem edges, since we'll need these soon
|
|
966
1006
|
// if it fails at this point, though, dont' worry because it
|
|
@@ -975,8 +1015,9 @@ This is a one-time fix-up, please be patient...
|
|
|
975
1015
|
}
|
|
976
1016
|
|
|
977
1017
|
for (const { to } of node.edgesOut.values()) {
|
|
978
|
-
if (to && to.isLink && to.target)
|
|
1018
|
+
if (to && to.isLink && to.target) {
|
|
979
1019
|
this[_linkNodes].add(to)
|
|
1020
|
+
}
|
|
980
1021
|
}
|
|
981
1022
|
|
|
982
1023
|
await Promise.all(promises)
|
|
@@ -1019,8 +1060,9 @@ This is a one-time fix-up, please be patient...
|
|
|
1019
1060
|
|
|
1020
1061
|
if (required.has(edge.from) && edge.type !== 'peerOptional' ||
|
|
1021
1062
|
secondEdge && (
|
|
1022
|
-
required.has(secondEdge.from) && secondEdge.type !== 'peerOptional'))
|
|
1063
|
+
required.has(secondEdge.from) && secondEdge.type !== 'peerOptional')) {
|
|
1023
1064
|
required.add(node)
|
|
1065
|
+
}
|
|
1024
1066
|
|
|
1025
1067
|
// keep track of the thing that caused this node to be included.
|
|
1026
1068
|
const src = parent.sourceReference
|
|
@@ -1030,16 +1072,18 @@ This is a one-time fix-up, please be patient...
|
|
|
1030
1072
|
// otherwise we'll be tempted to put peers as other top-level installed
|
|
1031
1073
|
// things, potentially clobbering what's there already, which is not
|
|
1032
1074
|
// what we want. the missing edges will be picked up on the next pass.
|
|
1033
|
-
if (this[_global] && edge.from.isProjectRoot)
|
|
1075
|
+
if (this[_global] && edge.from.isProjectRoot) {
|
|
1034
1076
|
return node
|
|
1077
|
+
}
|
|
1035
1078
|
|
|
1036
1079
|
// otherwise, we have to make sure that our peers can go along with us.
|
|
1037
1080
|
return this[_loadPeerSet](node, required)
|
|
1038
1081
|
}
|
|
1039
1082
|
|
|
1040
1083
|
[_virtualRoot] (node, reuse = false) {
|
|
1041
|
-
if (reuse && this[_virtualRoots].has(node))
|
|
1084
|
+
if (reuse && this[_virtualRoots].has(node)) {
|
|
1042
1085
|
return this[_virtualRoots].get(node)
|
|
1086
|
+
}
|
|
1043
1087
|
|
|
1044
1088
|
const vr = new Node({
|
|
1045
1089
|
path: node.realpath,
|
|
@@ -1081,16 +1125,19 @@ This is a one-time fix-up, please be patient...
|
|
|
1081
1125
|
return [...node.edgesOut.values()]
|
|
1082
1126
|
.filter(edge => {
|
|
1083
1127
|
// If it's included in a bundle, we take whatever is specified.
|
|
1084
|
-
if (bundled.has(edge.name))
|
|
1128
|
+
if (bundled.has(edge.name)) {
|
|
1085
1129
|
return false
|
|
1130
|
+
}
|
|
1086
1131
|
|
|
1087
1132
|
// If it's already been logged as a load failure, skip it.
|
|
1088
|
-
if (edge.to && this[_loadFailures].has(edge.to))
|
|
1133
|
+
if (edge.to && this[_loadFailures].has(edge.to)) {
|
|
1089
1134
|
return false
|
|
1135
|
+
}
|
|
1090
1136
|
|
|
1091
1137
|
// If it's shrinkwrapped, we use what the shrinkwap wants.
|
|
1092
|
-
if (edge.to && edge.to.inShrinkwrap)
|
|
1138
|
+
if (edge.to && edge.to.inShrinkwrap) {
|
|
1093
1139
|
return false
|
|
1140
|
+
}
|
|
1094
1141
|
|
|
1095
1142
|
// If the edge has no destination, that's a problem, unless
|
|
1096
1143
|
// if it's peerOptional and not explicitly requested.
|
|
@@ -1100,20 +1147,24 @@ This is a one-time fix-up, please be patient...
|
|
|
1100
1147
|
}
|
|
1101
1148
|
|
|
1102
1149
|
// If the edge has an error, there's a problem.
|
|
1103
|
-
if (!edge.valid)
|
|
1150
|
+
if (!edge.valid) {
|
|
1104
1151
|
return true
|
|
1152
|
+
}
|
|
1105
1153
|
|
|
1106
|
-
//
|
|
1107
|
-
if (this[_updateNames].includes(edge.name))
|
|
1154
|
+
// user explicitly asked to update this package by name, problem
|
|
1155
|
+
if (this[_updateNames].includes(edge.name)) {
|
|
1108
1156
|
return true
|
|
1157
|
+
}
|
|
1109
1158
|
|
|
1110
|
-
//
|
|
1111
|
-
if (this[_isVulnerable](edge.to))
|
|
1159
|
+
// fixing a security vulnerability with this package, problem
|
|
1160
|
+
if (this[_isVulnerable](edge.to)) {
|
|
1112
1161
|
return true
|
|
1162
|
+
}
|
|
1113
1163
|
|
|
1114
|
-
//
|
|
1115
|
-
if (this[_explicitRequests].has(edge))
|
|
1164
|
+
// user has explicitly asked to install this package, problem
|
|
1165
|
+
if (this[_explicitRequests].has(edge)) {
|
|
1116
1166
|
return true
|
|
1167
|
+
}
|
|
1117
1168
|
|
|
1118
1169
|
// No problems!
|
|
1119
1170
|
return false
|
|
@@ -1129,9 +1180,9 @@ This is a one-time fix-up, please be patient...
|
|
|
1129
1180
|
// if available and valid.
|
|
1130
1181
|
spec = this.idealTree.meta.checkYarnLock(spec, options)
|
|
1131
1182
|
|
|
1132
|
-
if (this[_manifests].has(spec.raw))
|
|
1183
|
+
if (this[_manifests].has(spec.raw)) {
|
|
1133
1184
|
return this[_manifests].get(spec.raw)
|
|
1134
|
-
else {
|
|
1185
|
+
} else {
|
|
1135
1186
|
this.log.silly('fetch manifest', spec.raw)
|
|
1136
1187
|
const p = pacote.manifest(spec, options)
|
|
1137
1188
|
.then(mani => {
|
|
@@ -1197,12 +1248,13 @@ This is a one-time fix-up, please be patient...
|
|
|
1197
1248
|
// we typically only install non-optional peers, but we have to
|
|
1198
1249
|
// factor them into the peerSet so that we can avoid conflicts
|
|
1199
1250
|
.filter(e => e.peer && !(e.valid && e.to))
|
|
1200
|
-
.sort(({name: a}, {name: b}) =>
|
|
1251
|
+
.sort(({name: a}, {name: b}) => localeCompare(a, b))
|
|
1201
1252
|
|
|
1202
1253
|
for (const edge of peerEdges) {
|
|
1203
1254
|
// already placed this one, and we're happy with it.
|
|
1204
|
-
if (edge.valid && edge.to)
|
|
1255
|
+
if (edge.valid && edge.to) {
|
|
1205
1256
|
continue
|
|
1257
|
+
}
|
|
1206
1258
|
|
|
1207
1259
|
const parentEdge = node.parent.edgesOut.get(edge.name)
|
|
1208
1260
|
const {isProjectRoot, isWorkspace} = node.parent.sourceReference
|
|
@@ -1223,11 +1275,17 @@ This is a one-time fix-up, please be patient...
|
|
|
1223
1275
|
// a conflict. this is always a problem in strict mode, never
|
|
1224
1276
|
// in force mode, and a problem in non-strict mode if this isn't
|
|
1225
1277
|
// on behalf of our project. in all such cases, we warn at least.
|
|
1226
|
-
const dep = await this[_nodeFromEdge](
|
|
1278
|
+
const dep = await this[_nodeFromEdge](
|
|
1279
|
+
parentEdge,
|
|
1280
|
+
node.parent,
|
|
1281
|
+
edge,
|
|
1282
|
+
required
|
|
1283
|
+
)
|
|
1227
1284
|
|
|
1228
1285
|
// hooray! that worked!
|
|
1229
|
-
if (edge.valid)
|
|
1286
|
+
if (edge.valid) {
|
|
1230
1287
|
continue
|
|
1288
|
+
}
|
|
1231
1289
|
|
|
1232
1290
|
// allow it. either we're overriding, or it's not something
|
|
1233
1291
|
// that will be installed by default anyway, and we'll fail when
|
|
@@ -1260,8 +1318,9 @@ This is a one-time fix-up, please be patient...
|
|
|
1260
1318
|
// isn't also required, then there's a good chance we won't need it,
|
|
1261
1319
|
// so allow it for now and let it conflict if it turns out to actually
|
|
1262
1320
|
// be necessary for the installation.
|
|
1263
|
-
if (conflictOK || !required.has(edge.from))
|
|
1321
|
+
if (conflictOK || !required.has(edge.from)) {
|
|
1264
1322
|
continue
|
|
1323
|
+
}
|
|
1265
1324
|
|
|
1266
1325
|
// ok, it's the root, or we're in unforced strict mode, so this is bad
|
|
1267
1326
|
this[_failPeerConflict](edge, parentEdge)
|
|
@@ -1304,15 +1363,17 @@ This is a one-time fix-up, please be patient...
|
|
|
1304
1363
|
this[_linkNodes].delete(link)
|
|
1305
1364
|
|
|
1306
1365
|
// link we never ended up placing, skip it
|
|
1307
|
-
if (link.root !== this.idealTree)
|
|
1366
|
+
if (link.root !== this.idealTree) {
|
|
1308
1367
|
continue
|
|
1368
|
+
}
|
|
1309
1369
|
|
|
1310
1370
|
const tree = this.idealTree.target
|
|
1311
1371
|
const external = !link.target.isDescendantOf(tree)
|
|
1312
1372
|
|
|
1313
1373
|
// outside the root, somebody else's problem, ignore it
|
|
1314
|
-
if (external && !this[_follow])
|
|
1374
|
+
if (external && !this[_follow]) {
|
|
1315
1375
|
continue
|
|
1376
|
+
}
|
|
1316
1377
|
|
|
1317
1378
|
// didn't find a parent for it or it has not been seen yet
|
|
1318
1379
|
// so go ahead and process it.
|
|
@@ -1328,8 +1389,9 @@ This is a one-time fix-up, please be patient...
|
|
|
1328
1389
|
}
|
|
1329
1390
|
}
|
|
1330
1391
|
|
|
1331
|
-
if (this[_depsQueue].length)
|
|
1392
|
+
if (this[_depsQueue].length) {
|
|
1332
1393
|
return this[_buildDepStep]()
|
|
1394
|
+
}
|
|
1333
1395
|
}
|
|
1334
1396
|
|
|
1335
1397
|
[_fixDepFlags] () {
|
|
@@ -1344,8 +1406,9 @@ This is a one-time fix-up, please be patient...
|
|
|
1344
1406
|
// all set to true, and there can be nothing extraneous, so there's
|
|
1345
1407
|
// nothing to prune, because we built it from scratch. if we didn't
|
|
1346
1408
|
// add or remove anything, then also nothing to do.
|
|
1347
|
-
if (metaFromDisk && mutateTree)
|
|
1409
|
+
if (metaFromDisk && mutateTree) {
|
|
1348
1410
|
resetDepFlags(this.idealTree)
|
|
1411
|
+
}
|
|
1349
1412
|
|
|
1350
1413
|
// update all the dev/optional/etc flags in the tree
|
|
1351
1414
|
// either we started with a fresh tree, or we
|
|
@@ -1353,9 +1416,9 @@ This is a one-time fix-up, please be patient...
|
|
|
1353
1416
|
//
|
|
1354
1417
|
// if we started from a blank slate, or changed something, then
|
|
1355
1418
|
// the dep flags will be all set to true.
|
|
1356
|
-
if (!metaFromDisk || mutateTree)
|
|
1419
|
+
if (!metaFromDisk || mutateTree) {
|
|
1357
1420
|
calcDepFlags(this.idealTree)
|
|
1358
|
-
else {
|
|
1421
|
+
} else {
|
|
1359
1422
|
// otherwise just unset all the flags on the root node
|
|
1360
1423
|
// since they will sometimes have the default value
|
|
1361
1424
|
this.idealTree.extraneous = false
|
|
@@ -1370,25 +1433,29 @@ This is a one-time fix-up, please be patient...
|
|
|
1370
1433
|
// then the tree is suspect. Prune what is marked as extraneous.
|
|
1371
1434
|
// otherwise, don't bother.
|
|
1372
1435
|
const needPrune = metaFromDisk && (mutateTree || flagsSuspect)
|
|
1373
|
-
if (this[_prune] && needPrune)
|
|
1436
|
+
if (this[_prune] && needPrune) {
|
|
1374
1437
|
this[_idealTreePrune]()
|
|
1438
|
+
}
|
|
1375
1439
|
|
|
1376
1440
|
process.emit('timeEnd', 'idealTree:fixDepFlags')
|
|
1377
1441
|
}
|
|
1378
1442
|
|
|
1379
1443
|
[_idealTreePrune] () {
|
|
1380
|
-
for (const node of this.idealTree.inventory.filter(n => n.extraneous))
|
|
1444
|
+
for (const node of this.idealTree.inventory.filter(n => n.extraneous)) {
|
|
1381
1445
|
node.parent = null
|
|
1446
|
+
}
|
|
1382
1447
|
}
|
|
1383
1448
|
|
|
1384
1449
|
[_pruneFailedOptional] () {
|
|
1385
1450
|
for (const node of this[_loadFailures]) {
|
|
1386
|
-
if (!node.optional)
|
|
1451
|
+
if (!node.optional) {
|
|
1387
1452
|
throw node.errors[0]
|
|
1453
|
+
}
|
|
1388
1454
|
|
|
1389
1455
|
const set = optionalSet(node)
|
|
1390
|
-
for (const node of set)
|
|
1456
|
+
for (const node of set) {
|
|
1391
1457
|
node.parent = null
|
|
1458
|
+
}
|
|
1392
1459
|
}
|
|
1393
1460
|
}
|
|
1394
1461
|
}
|
package/lib/arborist/deduper.js
CHANGED
|
@@ -6,8 +6,9 @@ module.exports = cls => class Deduper extends cls {
|
|
|
6
6
|
const tree = await this.loadVirtual().catch(() => this.loadActual())
|
|
7
7
|
const names = []
|
|
8
8
|
for (const name of tree.inventory.query('name')) {
|
|
9
|
-
if (tree.inventory.query('name', name).size > 1)
|
|
9
|
+
if (tree.inventory.query('name', name).size > 1) {
|
|
10
10
|
names.push(name)
|
|
11
|
+
}
|
|
11
12
|
}
|
|
12
13
|
return this.reify({
|
|
13
14
|
...options,
|
package/lib/arborist/index.js
CHANGED
|
@@ -59,8 +59,9 @@ class Arborist extends Base {
|
|
|
59
59
|
packumentCache: options.packumentCache || new Map(),
|
|
60
60
|
log: options.log || procLog,
|
|
61
61
|
}
|
|
62
|
-
if (options.saveType && !saveTypeMap.get(options.saveType))
|
|
62
|
+
if (options.saveType && !saveTypeMap.get(options.saveType)) {
|
|
63
63
|
throw new Error(`Invalid saveType ${options.saveType}`)
|
|
64
|
+
}
|
|
64
65
|
this.cache = resolve(this.options.cache)
|
|
65
66
|
this.path = resolve(this.options.path)
|
|
66
67
|
process.emit('timeEnd', 'arborist:ctor')
|
|
@@ -81,17 +82,20 @@ class Arborist extends Base {
|
|
|
81
82
|
const dep = edge.to
|
|
82
83
|
if (dep) {
|
|
83
84
|
set.add(dep)
|
|
84
|
-
if (dep.isLink)
|
|
85
|
+
if (dep.isLink) {
|
|
85
86
|
set.add(dep.target)
|
|
87
|
+
}
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
for (const child of node.children.values()) {
|
|
89
|
-
if (child.extraneous)
|
|
91
|
+
if (child.extraneous) {
|
|
90
92
|
extraneous.add(child)
|
|
93
|
+
}
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
|
-
for (const extra of extraneous)
|
|
96
|
+
for (const extra of extraneous) {
|
|
94
97
|
set.add(extra)
|
|
98
|
+
}
|
|
95
99
|
return set
|
|
96
100
|
}
|
|
97
101
|
}
|