@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
package/lib/arborist/reify.js
CHANGED
|
@@ -158,8 +158,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
158
158
|
|
|
159
159
|
async [_validatePath] () {
|
|
160
160
|
// don't create missing dirs on dry runs
|
|
161
|
-
if (this[_packageLockOnly] || this[_dryRun])
|
|
161
|
+
if (this[_packageLockOnly] || this[_dryRun]) {
|
|
162
162
|
return
|
|
163
|
+
}
|
|
163
164
|
|
|
164
165
|
// we do NOT want to set ownership on this folder, especially
|
|
165
166
|
// recursively, because it can have other side effects to do that
|
|
@@ -172,8 +173,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
172
173
|
|
|
173
174
|
async [_reifyPackages] () {
|
|
174
175
|
// we don't submit the audit report or write to disk on dry runs
|
|
175
|
-
if (this[_dryRun])
|
|
176
|
+
if (this[_dryRun]) {
|
|
176
177
|
return
|
|
178
|
+
}
|
|
177
179
|
|
|
178
180
|
if (this[_packageLockOnly]) {
|
|
179
181
|
// we already have the complete tree, so just audit it now,
|
|
@@ -220,8 +222,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
220
222
|
for (const action of actions) {
|
|
221
223
|
try {
|
|
222
224
|
await this[action]()
|
|
223
|
-
if (reifyTerminated)
|
|
225
|
+
if (reifyTerminated) {
|
|
224
226
|
throw reifyTerminated
|
|
227
|
+
}
|
|
225
228
|
} catch (er) {
|
|
226
229
|
await this[rollback](er)
|
|
227
230
|
/* istanbul ignore next - rollback throws, should never hit this */
|
|
@@ -233,8 +236,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
233
236
|
// no rollback for this one, just exit with the error, since the
|
|
234
237
|
// install completed and can't be safely recovered at this point.
|
|
235
238
|
await this[_removeTrash]()
|
|
236
|
-
if (reifyTerminated)
|
|
239
|
+
if (reifyTerminated) {
|
|
237
240
|
throw reifyTerminated
|
|
241
|
+
}
|
|
238
242
|
|
|
239
243
|
// done modifying the file system, no need to keep listening for sigs
|
|
240
244
|
removeHandler()
|
|
@@ -261,18 +265,21 @@ module.exports = cls => class Reifier extends cls {
|
|
|
261
265
|
filter: (node, kid) => {
|
|
262
266
|
// if it's not the project root, and we have no explicit requests,
|
|
263
267
|
// then we're already into a nested dep, so we keep it
|
|
264
|
-
if (this.explicitRequests.size === 0 || !node.isProjectRoot)
|
|
268
|
+
if (this.explicitRequests.size === 0 || !node.isProjectRoot) {
|
|
265
269
|
return true
|
|
270
|
+
}
|
|
266
271
|
|
|
267
272
|
// if we added it as an edgeOut, then we want it
|
|
268
|
-
if (this.idealTree.edgesOut.has(kid))
|
|
273
|
+
if (this.idealTree.edgesOut.has(kid)) {
|
|
269
274
|
return true
|
|
275
|
+
}
|
|
270
276
|
|
|
271
277
|
// if it's an explicit request, then we want it
|
|
272
278
|
const hasExplicit = [...this.explicitRequests]
|
|
273
279
|
.some(edge => edge.name === kid)
|
|
274
|
-
if (hasExplicit)
|
|
280
|
+
if (hasExplicit) {
|
|
275
281
|
return true
|
|
282
|
+
}
|
|
276
283
|
|
|
277
284
|
// ignore the rest of the global install folder
|
|
278
285
|
return false
|
|
@@ -280,8 +287,10 @@ module.exports = cls => class Reifier extends cls {
|
|
|
280
287
|
} : { ignoreMissing: true }
|
|
281
288
|
|
|
282
289
|
if (!this[_global]) {
|
|
283
|
-
return Promise.all([
|
|
284
|
-
.
|
|
290
|
+
return Promise.all([
|
|
291
|
+
this.loadActual(actualOpt),
|
|
292
|
+
this.buildIdealTree(bitOpt),
|
|
293
|
+
]).then(() => process.emit('timeEnd', 'reify:loadTrees'))
|
|
285
294
|
}
|
|
286
295
|
|
|
287
296
|
// the global install space tends to have a lot of stuff in it. don't
|
|
@@ -295,8 +304,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
295
304
|
}
|
|
296
305
|
|
|
297
306
|
[_diffTrees] () {
|
|
298
|
-
if (this[_packageLockOnly])
|
|
307
|
+
if (this[_packageLockOnly]) {
|
|
299
308
|
return
|
|
309
|
+
}
|
|
300
310
|
|
|
301
311
|
process.emit('time', 'reify:diffTrees')
|
|
302
312
|
// XXX if we have an existing diff already, there should be a way
|
|
@@ -311,20 +321,24 @@ module.exports = cls => class Reifier extends cls {
|
|
|
311
321
|
// children where there's an explicit request.
|
|
312
322
|
for (const { name } of this.explicitRequests) {
|
|
313
323
|
const ideal = idealTree.children.get(name)
|
|
314
|
-
if (ideal)
|
|
324
|
+
if (ideal) {
|
|
315
325
|
filterNodes.push(ideal)
|
|
326
|
+
}
|
|
316
327
|
const actual = actualTree.children.get(name)
|
|
317
|
-
if (actual)
|
|
328
|
+
if (actual) {
|
|
318
329
|
filterNodes.push(actual)
|
|
330
|
+
}
|
|
319
331
|
}
|
|
320
332
|
} else {
|
|
321
333
|
for (const ws of this[_workspaces]) {
|
|
322
334
|
const ideal = this.idealTree.children.get(ws)
|
|
323
|
-
if (ideal)
|
|
335
|
+
if (ideal) {
|
|
324
336
|
filterNodes.push(ideal)
|
|
337
|
+
}
|
|
325
338
|
const actual = this.actualTree.children.get(ws)
|
|
326
|
-
if (actual)
|
|
339
|
+
if (actual) {
|
|
327
340
|
filterNodes.push(actual)
|
|
341
|
+
}
|
|
328
342
|
}
|
|
329
343
|
}
|
|
330
344
|
|
|
@@ -360,8 +374,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
360
374
|
const retired = retirePath(path)
|
|
361
375
|
moves[path] = retired
|
|
362
376
|
this[_trashList].add(retired)
|
|
363
|
-
} else
|
|
377
|
+
} else {
|
|
364
378
|
this[_trashList].add(path)
|
|
379
|
+
}
|
|
365
380
|
}
|
|
366
381
|
}
|
|
367
382
|
|
|
@@ -393,10 +408,11 @@ module.exports = cls => class Reifier extends cls {
|
|
|
393
408
|
if (er.code === 'ENOENT') {
|
|
394
409
|
return didMkdirp ? null : mkdirp(dirname(to)).then(() =>
|
|
395
410
|
this[_renamePath](from, to, true))
|
|
396
|
-
} else if (er.code === 'EEXIST')
|
|
411
|
+
} else if (er.code === 'EEXIST') {
|
|
397
412
|
return rimraf(to).then(() => moveFile(from, to))
|
|
398
|
-
else
|
|
413
|
+
} else {
|
|
399
414
|
throw er
|
|
415
|
+
}
|
|
400
416
|
})
|
|
401
417
|
}
|
|
402
418
|
|
|
@@ -417,8 +433,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
417
433
|
// adding to the trash list will skip reifying, and delete them
|
|
418
434
|
// if they are currently in the tree and otherwise untouched.
|
|
419
435
|
[_addOmitsToTrashList] () {
|
|
420
|
-
if (!this[_omitDev] && !this[_omitOptional] && !this[_omitPeer])
|
|
436
|
+
if (!this[_omitDev] && !this[_omitOptional] && !this[_omitPeer]) {
|
|
421
437
|
return
|
|
438
|
+
}
|
|
422
439
|
|
|
423
440
|
process.emit('time', 'reify:trashOmits')
|
|
424
441
|
|
|
@@ -429,8 +446,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
429
446
|
node.optional && this[_omitOptional] ||
|
|
430
447
|
node.devOptional && this[_omitOptional] && this[_omitDev])
|
|
431
448
|
|
|
432
|
-
for (const node of this.idealTree.inventory.filter(filter))
|
|
449
|
+
for (const node of this.idealTree.inventory.filter(filter)) {
|
|
433
450
|
this[_addNodeToTrashList](node)
|
|
451
|
+
}
|
|
434
452
|
|
|
435
453
|
process.emit('timeEnd', 'reify:trashOmits')
|
|
436
454
|
}
|
|
@@ -452,10 +470,12 @@ module.exports = cls => class Reifier extends cls {
|
|
|
452
470
|
const dirsChecked = new Set()
|
|
453
471
|
return promiseAllRejectLate(leaves.map(async node => {
|
|
454
472
|
for (const d of walkUp(node.path)) {
|
|
455
|
-
if (d === node.top.path)
|
|
473
|
+
if (d === node.top.path) {
|
|
456
474
|
break
|
|
457
|
-
|
|
475
|
+
}
|
|
476
|
+
if (dirsChecked.has(d)) {
|
|
458
477
|
continue
|
|
478
|
+
}
|
|
459
479
|
dirsChecked.add(d)
|
|
460
480
|
const st = await lstat(d).catch(er => null)
|
|
461
481
|
// this can happen if we have a link to a package with a name
|
|
@@ -487,8 +507,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
487
507
|
.map(path => rimraf(path).catch(er => failures.push([path, er])))
|
|
488
508
|
return promiseAllRejectLate(unlinks)
|
|
489
509
|
.then(() => {
|
|
490
|
-
if (failures.length)
|
|
510
|
+
if (failures.length) {
|
|
491
511
|
this.log.warn('cleanup', 'Failed to remove some directories', failures)
|
|
512
|
+
}
|
|
492
513
|
})
|
|
493
514
|
.then(() => process.emit('timeEnd', 'reify:rollback:createSparse'))
|
|
494
515
|
.then(() => this[_rollbackRetireShallowNodes](er))
|
|
@@ -504,8 +525,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
504
525
|
d.ideal.hasShrinkwrap && !seen.has(d.ideal) &&
|
|
505
526
|
!this[_trashList].has(d.ideal.path))
|
|
506
527
|
|
|
507
|
-
if (!shrinkwraps.length)
|
|
528
|
+
if (!shrinkwraps.length) {
|
|
508
529
|
return
|
|
530
|
+
}
|
|
509
531
|
|
|
510
532
|
process.emit('time', 'reify:loadShrinkwraps')
|
|
511
533
|
|
|
@@ -535,8 +557,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
535
557
|
// to the trash list
|
|
536
558
|
// Always return the node.
|
|
537
559
|
[_reifyNode] (node) {
|
|
538
|
-
if (this[_trashList].has(node.path))
|
|
560
|
+
if (this[_trashList].has(node.path)) {
|
|
539
561
|
return node
|
|
562
|
+
}
|
|
540
563
|
|
|
541
564
|
const timer = `reifyNode:${node.location}`
|
|
542
565
|
process.emit('time', timer)
|
|
@@ -569,8 +592,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
569
592
|
|
|
570
593
|
// do not allow node_modules to be a symlink
|
|
571
594
|
async [_validateNodeModules] (nm) {
|
|
572
|
-
if (this[_force] || this[_nmValidated].has(nm))
|
|
595
|
+
if (this[_force] || this[_nmValidated].has(nm)) {
|
|
573
596
|
return
|
|
597
|
+
}
|
|
574
598
|
const st = await lstat(nm).catch(() => null)
|
|
575
599
|
if (!st || st.isDirectory()) {
|
|
576
600
|
this[_nmValidated].add(nm)
|
|
@@ -642,8 +666,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
642
666
|
|
|
643
667
|
[_warnDeprecated] (node) {
|
|
644
668
|
const {_id, deprecated} = node.package
|
|
645
|
-
if (deprecated)
|
|
669
|
+
if (deprecated) {
|
|
646
670
|
this.log.warn('deprecated', `${_id}: ${deprecated}`)
|
|
671
|
+
}
|
|
647
672
|
}
|
|
648
673
|
|
|
649
674
|
// if the node is optional, then the failure of the promise is nonfatal
|
|
@@ -677,8 +702,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
677
702
|
[_loadBundlesAndUpdateTrees] (
|
|
678
703
|
depth = 0, bundlesByDepth = this[_getBundlesByDepth]()
|
|
679
704
|
) {
|
|
680
|
-
if (depth === 0)
|
|
705
|
+
if (depth === 0) {
|
|
681
706
|
process.emit('time', 'reify:loadBundles')
|
|
707
|
+
}
|
|
682
708
|
|
|
683
709
|
const maxBundleDepth = bundlesByDepth.get('maxBundleDepth')
|
|
684
710
|
if (depth > maxBundleDepth) {
|
|
@@ -698,8 +724,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
698
724
|
node.target !== node.root &&
|
|
699
725
|
!this[_trashList].has(node.path))
|
|
700
726
|
|
|
701
|
-
if (!set.length)
|
|
727
|
+
if (!set.length) {
|
|
702
728
|
return this[_loadBundlesAndUpdateTrees](depth + 1, bundlesByDepth)
|
|
729
|
+
}
|
|
703
730
|
|
|
704
731
|
// extract all the nodes with bundles
|
|
705
732
|
return promiseAllRejectLate(set.map(node => {
|
|
@@ -725,12 +752,14 @@ module.exports = cls => class Reifier extends cls {
|
|
|
725
752
|
// it's actually in the bundle if it gets transplanted
|
|
726
753
|
notTransplanted.delete(node.name)
|
|
727
754
|
return true
|
|
728
|
-
} else
|
|
755
|
+
} else {
|
|
729
756
|
return false
|
|
757
|
+
}
|
|
730
758
|
},
|
|
731
759
|
})
|
|
732
|
-
for (const name of notTransplanted)
|
|
760
|
+
for (const name of notTransplanted) {
|
|
733
761
|
this[_bundleMissing].add(node.children.get(name))
|
|
762
|
+
}
|
|
734
763
|
})))
|
|
735
764
|
// move onto the next level of bundled items
|
|
736
765
|
.then(() => this[_loadBundlesAndUpdateTrees](depth + 1, bundlesByDepth))
|
|
@@ -743,18 +772,21 @@ module.exports = cls => class Reifier extends cls {
|
|
|
743
772
|
tree: this.diff,
|
|
744
773
|
visit: diff => {
|
|
745
774
|
const node = diff.ideal
|
|
746
|
-
if (!node)
|
|
775
|
+
if (!node) {
|
|
747
776
|
return
|
|
748
|
-
|
|
777
|
+
}
|
|
778
|
+
if (node.isProjectRoot) {
|
|
749
779
|
return
|
|
780
|
+
}
|
|
750
781
|
|
|
751
782
|
const { bundleDependencies } = node.package
|
|
752
783
|
if (bundleDependencies && bundleDependencies.length) {
|
|
753
784
|
maxBundleDepth = Math.max(maxBundleDepth, node.depth)
|
|
754
|
-
if (!bundlesByDepth.has(node.depth))
|
|
785
|
+
if (!bundlesByDepth.has(node.depth)) {
|
|
755
786
|
bundlesByDepth.set(node.depth, [node])
|
|
756
|
-
else
|
|
787
|
+
} else {
|
|
757
788
|
bundlesByDepth.get(node.depth).push(node)
|
|
789
|
+
}
|
|
758
790
|
}
|
|
759
791
|
},
|
|
760
792
|
getChildren: diff => diff.children,
|
|
@@ -791,13 +823,15 @@ module.exports = cls => class Reifier extends cls {
|
|
|
791
823
|
// create the list of nodes shadowed by children of bundlers
|
|
792
824
|
for (const bundles of bundlesByDepth.values()) {
|
|
793
825
|
// skip the 'maxBundleDepth' item
|
|
794
|
-
if (!Array.isArray(bundles))
|
|
826
|
+
if (!Array.isArray(bundles)) {
|
|
795
827
|
continue
|
|
828
|
+
}
|
|
796
829
|
for (const node of bundles) {
|
|
797
830
|
for (const name of node.children.keys()) {
|
|
798
831
|
const shadow = node.parent.resolve(name)
|
|
799
|
-
if (!shadow)
|
|
832
|
+
if (!shadow) {
|
|
800
833
|
continue
|
|
834
|
+
}
|
|
801
835
|
bundleShadowed.add(shadow)
|
|
802
836
|
shadow.extraneous = true
|
|
803
837
|
}
|
|
@@ -851,8 +885,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
851
885
|
}
|
|
852
886
|
|
|
853
887
|
[_submitQuickAudit] () {
|
|
854
|
-
if (this.options.audit === false)
|
|
888
|
+
if (this.options.audit === false) {
|
|
855
889
|
return this.auditReport = null
|
|
890
|
+
}
|
|
856
891
|
|
|
857
892
|
// we submit the quick audit at this point in the process, as soon as
|
|
858
893
|
// we have all the deps resolved, so that it can overlap with the other
|
|
@@ -865,8 +900,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
865
900
|
const tree = this.idealTree
|
|
866
901
|
|
|
867
902
|
// if we're operating on a workspace, only audit the workspace deps
|
|
868
|
-
if (this[_workspaces] && this[_workspaces].length)
|
|
903
|
+
if (this[_workspaces] && this[_workspaces].length) {
|
|
869
904
|
options.filterSet = this.workspaceDependencySet(tree, this[_workspaces])
|
|
905
|
+
}
|
|
870
906
|
|
|
871
907
|
this.auditReport = AuditReport.load(tree, options)
|
|
872
908
|
.then(res => {
|
|
@@ -891,8 +927,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
891
927
|
tree: this.diff,
|
|
892
928
|
visit: diff => {
|
|
893
929
|
// no unpacking if we don't want to change this thing
|
|
894
|
-
if (diff.action !== 'CHANGE' && diff.action !== 'ADD')
|
|
930
|
+
if (diff.action !== 'CHANGE' && diff.action !== 'ADD') {
|
|
895
931
|
return
|
|
932
|
+
}
|
|
896
933
|
|
|
897
934
|
const node = diff.ideal
|
|
898
935
|
const bd = this[_bundleUnpacked].has(node)
|
|
@@ -902,13 +939,18 @@ module.exports = cls => class Reifier extends cls {
|
|
|
902
939
|
// check whether we still need to unpack this one.
|
|
903
940
|
// test the inDepBundle last, since that's potentially a tree walk.
|
|
904
941
|
const doUnpack = node && // can't unpack if removed!
|
|
905
|
-
|
|
906
|
-
!
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
942
|
+
// root node already exists
|
|
943
|
+
!node.isRoot &&
|
|
944
|
+
// already unpacked to read bundle
|
|
945
|
+
!bd &&
|
|
946
|
+
// already unpacked to read sw
|
|
947
|
+
!sw &&
|
|
948
|
+
// already unpacked by another dep's bundle
|
|
949
|
+
(bundleMissing || !node.inDepBundle)
|
|
950
|
+
|
|
951
|
+
if (doUnpack) {
|
|
911
952
|
unpacks.push(this[_reifyNode](node))
|
|
953
|
+
}
|
|
912
954
|
},
|
|
913
955
|
getChildren: diff => diff.children,
|
|
914
956
|
})
|
|
@@ -933,8 +975,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
933
975
|
this[_retiredUnchanged] = {}
|
|
934
976
|
return promiseAllRejectLate(this.diff.children.map(diff => {
|
|
935
977
|
// skip if nothing was retired
|
|
936
|
-
if (diff.action !== 'CHANGE' && diff.action !== 'REMOVE')
|
|
978
|
+
if (diff.action !== 'CHANGE' && diff.action !== 'REMOVE') {
|
|
937
979
|
return
|
|
980
|
+
}
|
|
938
981
|
|
|
939
982
|
const { path: realFolder } = diff.actual
|
|
940
983
|
const retireFolder = moves[realFolder]
|
|
@@ -955,12 +998,14 @@ module.exports = cls => class Reifier extends cls {
|
|
|
955
998
|
this[_retiredUnchanged][retireFolder] = []
|
|
956
999
|
return promiseAllRejectLate(diff.unchanged.map(node => {
|
|
957
1000
|
// no need to roll back links, since we'll just delete them anyway
|
|
958
|
-
if (node.isLink)
|
|
1001
|
+
if (node.isLink) {
|
|
959
1002
|
return mkdirp(dirname(node.path)).then(() => this[_reifyNode](node))
|
|
1003
|
+
}
|
|
960
1004
|
|
|
961
1005
|
// will have been moved/unpacked along with bundler
|
|
962
|
-
if (node.inDepBundle && !this[_bundleMissing].has(node))
|
|
1006
|
+
if (node.inDepBundle && !this[_bundleMissing].has(node)) {
|
|
963
1007
|
return
|
|
1008
|
+
}
|
|
964
1009
|
|
|
965
1010
|
this[_retiredUnchanged][retireFolder].push(node)
|
|
966
1011
|
|
|
@@ -1014,8 +1059,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1014
1059
|
dfwalk({
|
|
1015
1060
|
tree: this.diff,
|
|
1016
1061
|
leave: diff => {
|
|
1017
|
-
if (!diff.ideal.isProjectRoot)
|
|
1062
|
+
if (!diff.ideal.isProjectRoot) {
|
|
1018
1063
|
nodes.push(diff.ideal)
|
|
1064
|
+
}
|
|
1019
1065
|
},
|
|
1020
1066
|
// process adds before changes, ignore removals
|
|
1021
1067
|
getChildren: diff => diff && diff.children,
|
|
@@ -1030,8 +1076,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1030
1076
|
// skip links that only live within node_modules as they are most
|
|
1031
1077
|
// likely managed by packages we installed, we only want to rebuild
|
|
1032
1078
|
// unchanged links we directly manage
|
|
1033
|
-
if (node.isLink && node.target.fsTop === tree)
|
|
1079
|
+
if (node.isLink && node.target.fsTop === tree) {
|
|
1034
1080
|
nodes.push(node)
|
|
1081
|
+
}
|
|
1035
1082
|
}
|
|
1036
1083
|
|
|
1037
1084
|
return this.rebuild({ nodes, handleOptionalFailure: true })
|
|
@@ -1048,12 +1095,14 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1048
1095
|
const failures = []
|
|
1049
1096
|
const rm = path => rimraf(path).catch(er => failures.push([path, er]))
|
|
1050
1097
|
|
|
1051
|
-
for (const path of this[_trashList])
|
|
1098
|
+
for (const path of this[_trashList]) {
|
|
1052
1099
|
promises.push(rm(path))
|
|
1100
|
+
}
|
|
1053
1101
|
|
|
1054
1102
|
return promiseAllRejectLate(promises).then(() => {
|
|
1055
|
-
if (failures.length)
|
|
1103
|
+
if (failures.length) {
|
|
1056
1104
|
this.log.warn('cleanup', 'Failed to remove some directories', failures)
|
|
1105
|
+
}
|
|
1057
1106
|
})
|
|
1058
1107
|
.then(() => process.emit('timeEnd', 'reify:trash'))
|
|
1059
1108
|
}
|
|
@@ -1067,8 +1116,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1067
1116
|
// save it first, then prune out the optional trash, and then return it.
|
|
1068
1117
|
|
|
1069
1118
|
// support save=false option
|
|
1070
|
-
if (options.save === false || this[_global] || this[_dryRun])
|
|
1119
|
+
if (options.save === false || this[_global] || this[_dryRun]) {
|
|
1071
1120
|
return false
|
|
1121
|
+
}
|
|
1072
1122
|
|
|
1073
1123
|
process.emit('time', 'reify:save')
|
|
1074
1124
|
|
|
@@ -1089,6 +1139,14 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1089
1139
|
const spec = subSpec ? subSpec.rawSpec : rawSpec
|
|
1090
1140
|
const child = edge.to
|
|
1091
1141
|
|
|
1142
|
+
// if we tried to install an optional dep, but it was a version
|
|
1143
|
+
// that we couldn't resolve, this MAY be missing. if we haven't
|
|
1144
|
+
// blown up by now, it's because it was not a problem, though, so
|
|
1145
|
+
// just move on.
|
|
1146
|
+
if (!child) {
|
|
1147
|
+
continue
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1092
1150
|
let newSpec
|
|
1093
1151
|
if (req.registry) {
|
|
1094
1152
|
const version = child.version
|
|
@@ -1105,8 +1163,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1105
1163
|
!isRange ||
|
|
1106
1164
|
spec === '*' ||
|
|
1107
1165
|
subset(prefixRange, spec, { loose: true })
|
|
1108
|
-
)
|
|
1166
|
+
) {
|
|
1109
1167
|
range = prefixRange
|
|
1168
|
+
}
|
|
1110
1169
|
|
|
1111
1170
|
const pname = child.packageName
|
|
1112
1171
|
const alias = name !== pname
|
|
@@ -1115,10 +1174,11 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1115
1174
|
// save the git+https url if it has auth, otherwise shortcut
|
|
1116
1175
|
const h = req.hosted
|
|
1117
1176
|
const opt = { noCommittish: false }
|
|
1118
|
-
if (h.https && h.auth)
|
|
1177
|
+
if (h.https && h.auth) {
|
|
1119
1178
|
newSpec = `git+${h.https(opt)}`
|
|
1120
|
-
else
|
|
1179
|
+
} else {
|
|
1121
1180
|
newSpec = h.shortcut(opt)
|
|
1181
|
+
}
|
|
1122
1182
|
} else if (req.type === 'directory' || req.type === 'file') {
|
|
1123
1183
|
// save the relative path in package.json
|
|
1124
1184
|
// Normally saveSpec is updated with the proper relative
|
|
@@ -1128,34 +1188,41 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1128
1188
|
const p = req.fetchSpec.replace(/^file:/, '')
|
|
1129
1189
|
const rel = relpath(addTree.realpath, p)
|
|
1130
1190
|
newSpec = `file:${rel}`
|
|
1131
|
-
} else
|
|
1191
|
+
} else {
|
|
1132
1192
|
newSpec = req.saveSpec
|
|
1193
|
+
}
|
|
1133
1194
|
|
|
1134
1195
|
if (options.saveType) {
|
|
1135
1196
|
const depType = saveTypeMap.get(options.saveType)
|
|
1136
1197
|
pkg[depType][name] = newSpec
|
|
1137
1198
|
// rpj will have moved it here if it was in both
|
|
1138
1199
|
// if it is empty it will be deleted later
|
|
1139
|
-
if (options.saveType === 'prod' && pkg.optionalDependencies)
|
|
1200
|
+
if (options.saveType === 'prod' && pkg.optionalDependencies) {
|
|
1140
1201
|
delete pkg.optionalDependencies[name]
|
|
1202
|
+
}
|
|
1141
1203
|
} else {
|
|
1142
|
-
if (hasSubKey(pkg, 'dependencies', name))
|
|
1204
|
+
if (hasSubKey(pkg, 'dependencies', name)) {
|
|
1143
1205
|
pkg.dependencies[name] = newSpec
|
|
1206
|
+
}
|
|
1144
1207
|
|
|
1145
1208
|
if (hasSubKey(pkg, 'devDependencies', name)) {
|
|
1146
1209
|
pkg.devDependencies[name] = newSpec
|
|
1147
1210
|
// don't update peer or optional if we don't have to
|
|
1148
|
-
if (hasSubKey(pkg, 'peerDependencies', name) && !intersects(newSpec, pkg.peerDependencies[name]))
|
|
1211
|
+
if (hasSubKey(pkg, 'peerDependencies', name) && !intersects(newSpec, pkg.peerDependencies[name])) {
|
|
1149
1212
|
pkg.peerDependencies[name] = newSpec
|
|
1213
|
+
}
|
|
1150
1214
|
|
|
1151
|
-
if (hasSubKey(pkg, 'optionalDependencies', name) && !intersects(newSpec, pkg.optionalDependencies[name]))
|
|
1215
|
+
if (hasSubKey(pkg, 'optionalDependencies', name) && !intersects(newSpec, pkg.optionalDependencies[name])) {
|
|
1152
1216
|
pkg.optionalDependencies[name] = newSpec
|
|
1217
|
+
}
|
|
1153
1218
|
} else {
|
|
1154
|
-
if (hasSubKey(pkg, 'peerDependencies', name))
|
|
1219
|
+
if (hasSubKey(pkg, 'peerDependencies', name)) {
|
|
1155
1220
|
pkg.peerDependencies[name] = newSpec
|
|
1221
|
+
}
|
|
1156
1222
|
|
|
1157
|
-
if (hasSubKey(pkg, 'optionalDependencies', name))
|
|
1223
|
+
if (hasSubKey(pkg, 'optionalDependencies', name)) {
|
|
1158
1224
|
pkg.optionalDependencies[name] = newSpec
|
|
1225
|
+
}
|
|
1159
1226
|
}
|
|
1160
1227
|
}
|
|
1161
1228
|
|
|
@@ -1196,8 +1263,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1196
1263
|
}
|
|
1197
1264
|
|
|
1198
1265
|
// grab any from explicitRequests that had deps removed
|
|
1199
|
-
for (const { from: tree } of this.explicitRequests)
|
|
1266
|
+
for (const { from: tree } of this.explicitRequests) {
|
|
1200
1267
|
updatedTrees.add(tree)
|
|
1268
|
+
}
|
|
1201
1269
|
|
|
1202
1270
|
for (const tree of updatedTrees) {
|
|
1203
1271
|
// refresh the edges so they have the correct specs
|
|
@@ -1211,8 +1279,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1211
1279
|
}
|
|
1212
1280
|
|
|
1213
1281
|
async [_saveLockFile] (saveOpt) {
|
|
1214
|
-
if (!this[_usePackageLock])
|
|
1282
|
+
if (!this[_usePackageLock]) {
|
|
1215
1283
|
return
|
|
1284
|
+
}
|
|
1216
1285
|
|
|
1217
1286
|
const { meta } = this.idealTree
|
|
1218
1287
|
|
|
@@ -1224,8 +1293,9 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1224
1293
|
for (const path of this[_trashList]) {
|
|
1225
1294
|
const loc = relpath(this.idealTree.realpath, path)
|
|
1226
1295
|
const node = this.idealTree.inventory.get(loc)
|
|
1227
|
-
if (node && node.root === this.idealTree)
|
|
1296
|
+
if (node && node.root === this.idealTree) {
|
|
1228
1297
|
node.parent = null
|
|
1298
|
+
}
|
|
1229
1299
|
}
|
|
1230
1300
|
|
|
1231
1301
|
// if we filtered to only certain nodes, then anything ELSE needs
|
|
@@ -1244,54 +1314,60 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1244
1314
|
|
|
1245
1315
|
// if it's an ideal node from the filter set, then skip it
|
|
1246
1316
|
// because we already made whatever changes were necessary
|
|
1247
|
-
if (filterSet.has(ideal))
|
|
1317
|
+
if (filterSet.has(ideal)) {
|
|
1248
1318
|
continue
|
|
1319
|
+
}
|
|
1249
1320
|
|
|
1250
1321
|
// otherwise, if it's not in the actualTree, then it's not a thing
|
|
1251
1322
|
// that we actually added. And if it IS in the actualTree, then
|
|
1252
1323
|
// it's something that we left untouched, so we need to record
|
|
1253
1324
|
// that.
|
|
1254
1325
|
const actual = this.actualTree.inventory.get(loc)
|
|
1255
|
-
if (!actual)
|
|
1326
|
+
if (!actual) {
|
|
1256
1327
|
ideal.root = null
|
|
1257
|
-
else {
|
|
1328
|
+
} else {
|
|
1258
1329
|
if ([...actual.linksIn].some(link => filterSet.has(link))) {
|
|
1259
1330
|
seen.add(actual.location)
|
|
1260
1331
|
continue
|
|
1261
1332
|
}
|
|
1262
1333
|
const { realpath, isLink } = actual
|
|
1263
|
-
if (isLink && ideal.isLink && ideal.realpath === realpath)
|
|
1334
|
+
if (isLink && ideal.isLink && ideal.realpath === realpath) {
|
|
1264
1335
|
continue
|
|
1265
|
-
else
|
|
1336
|
+
} else {
|
|
1266
1337
|
reroot.add(actual)
|
|
1338
|
+
}
|
|
1267
1339
|
}
|
|
1268
1340
|
}
|
|
1269
1341
|
|
|
1270
1342
|
// now find any actual nodes that may not be present in the ideal
|
|
1271
1343
|
// tree, but were left behind by virtue of not being in the filter
|
|
1272
1344
|
for (const [loc, actual] of this.actualTree.inventory.entries()) {
|
|
1273
|
-
if (seen.has(loc))
|
|
1345
|
+
if (seen.has(loc)) {
|
|
1274
1346
|
continue
|
|
1347
|
+
}
|
|
1275
1348
|
seen.add(loc)
|
|
1276
1349
|
|
|
1277
1350
|
// we know that this is something that ISN'T in the idealTree,
|
|
1278
1351
|
// or else we will have addressed it in the previous loop.
|
|
1279
1352
|
// If it's in the filterSet, that means we intentionally removed
|
|
1280
1353
|
// it, so nothing to do here.
|
|
1281
|
-
if (filterSet.has(actual))
|
|
1354
|
+
if (filterSet.has(actual)) {
|
|
1282
1355
|
continue
|
|
1356
|
+
}
|
|
1283
1357
|
|
|
1284
1358
|
reroot.add(actual)
|
|
1285
1359
|
}
|
|
1286
1360
|
|
|
1287
1361
|
// go through the rerooted actual nodes, and move them over.
|
|
1288
|
-
for (const actual of reroot)
|
|
1362
|
+
for (const actual of reroot) {
|
|
1289
1363
|
actual.root = this.idealTree
|
|
1364
|
+
}
|
|
1290
1365
|
|
|
1291
1366
|
// prune out any tops that lack a linkIn, they are no longer relevant.
|
|
1292
1367
|
for (const top of this.idealTree.tops) {
|
|
1293
|
-
if (top.linksIn.size === 0)
|
|
1368
|
+
if (top.linksIn.size === 0) {
|
|
1294
1369
|
top.root = null
|
|
1370
|
+
}
|
|
1295
1371
|
}
|
|
1296
1372
|
|
|
1297
1373
|
// need to calculate dep flags, since nodes may have been marked
|
|
@@ -1307,7 +1383,8 @@ module.exports = cls => class Reifier extends cls {
|
|
|
1307
1383
|
this.actualTree = this.idealTree
|
|
1308
1384
|
this.idealTree = null
|
|
1309
1385
|
|
|
1310
|
-
if (!this[_global])
|
|
1386
|
+
if (!this[_global]) {
|
|
1311
1387
|
await this.actualTree.meta.save()
|
|
1388
|
+
}
|
|
1312
1389
|
}
|
|
1313
1390
|
}
|