@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/shrinkwrap.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// We cannot bump to v3 until npm v6 is out of common usage, and
|
|
10
10
|
// definitely not before npm v8.
|
|
11
11
|
|
|
12
|
+
const localeCompare = require('@isaacs/string-locale-compare')('en')
|
|
12
13
|
const lockfileVersion = 2
|
|
13
14
|
|
|
14
15
|
// for comparing nodes to yarn.lock entries
|
|
@@ -47,8 +48,9 @@ const readlink = promisify(fs.readlink)
|
|
|
47
48
|
const lstat = promisify(fs.lstat)
|
|
48
49
|
/* istanbul ignore next - version specific polyfill */
|
|
49
50
|
const readdir = async (path, opt) => {
|
|
50
|
-
if (!opt || !opt.withFileTypes)
|
|
51
|
+
if (!opt || !opt.withFileTypes) {
|
|
51
52
|
return readdir_(path, opt)
|
|
53
|
+
}
|
|
52
54
|
const ents = await readdir_(path, opt)
|
|
53
55
|
if (typeof ents[0] === 'string') {
|
|
54
56
|
return Promise.all(ents.map(async ent => {
|
|
@@ -97,20 +99,22 @@ const consistentResolve = require('./consistent-resolve.js')
|
|
|
97
99
|
const maybeReadFile = file => {
|
|
98
100
|
return readFile(file, 'utf8').then(d => d, er => {
|
|
99
101
|
/* istanbul ignore else - can't test without breaking module itself */
|
|
100
|
-
if (er.code === 'ENOENT')
|
|
102
|
+
if (er.code === 'ENOENT') {
|
|
101
103
|
return ''
|
|
102
|
-
else
|
|
104
|
+
} else {
|
|
103
105
|
throw er
|
|
106
|
+
}
|
|
104
107
|
})
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
const maybeStatFile = file => {
|
|
108
111
|
return stat(file).then(st => st.isFile(), er => {
|
|
109
112
|
/* istanbul ignore else - can't test without breaking module itself */
|
|
110
|
-
if (er.code === 'ENOENT')
|
|
113
|
+
if (er.code === 'ENOENT') {
|
|
111
114
|
return null
|
|
112
|
-
else
|
|
115
|
+
} else {
|
|
113
116
|
throw er
|
|
117
|
+
}
|
|
114
118
|
})
|
|
115
119
|
}
|
|
116
120
|
|
|
@@ -163,13 +167,16 @@ const assertNoNewer = async (path, data, lockTime, dir = path, seen = null) => {
|
|
|
163
167
|
const rel = relpath(path, dir)
|
|
164
168
|
if (dir !== path) {
|
|
165
169
|
const dirTime = (await stat(dir)).mtime
|
|
166
|
-
if (dirTime > lockTime)
|
|
170
|
+
if (dirTime > lockTime) {
|
|
167
171
|
throw 'out of date, updated: ' + rel
|
|
168
|
-
|
|
172
|
+
}
|
|
173
|
+
if (!isScope && !isNM && !data.packages[rel]) {
|
|
169
174
|
throw 'missing from lockfile: ' + rel
|
|
175
|
+
}
|
|
170
176
|
seen.add(rel)
|
|
171
|
-
} else
|
|
177
|
+
} else {
|
|
172
178
|
seen = new Set([rel])
|
|
179
|
+
}
|
|
173
180
|
|
|
174
181
|
const parent = isParent ? dir : resolve(dir, 'node_modules')
|
|
175
182
|
const children = dir === path
|
|
@@ -179,26 +186,29 @@ const assertNoNewer = async (path, data, lockTime, dir = path, seen = null) => {
|
|
|
179
186
|
return children.catch(() => [])
|
|
180
187
|
.then(ents => Promise.all(ents.map(async ent => {
|
|
181
188
|
const child = resolve(parent, ent.name)
|
|
182
|
-
if (ent.isDirectory() && !/^\./.test(ent.name))
|
|
189
|
+
if (ent.isDirectory() && !/^\./.test(ent.name)) {
|
|
183
190
|
await assertNoNewer(path, data, lockTime, child, seen)
|
|
184
|
-
else if (ent.isSymbolicLink()) {
|
|
191
|
+
} else if (ent.isSymbolicLink()) {
|
|
185
192
|
const target = resolve(parent, await readlink(child))
|
|
186
193
|
const tstat = await stat(target).catch(
|
|
187
194
|
/* istanbul ignore next - windows */ () => null)
|
|
188
195
|
seen.add(relpath(path, child))
|
|
189
196
|
/* istanbul ignore next - windows cannot do this */
|
|
190
|
-
if (tstat && tstat.isDirectory() && !seen.has(relpath(path, target)))
|
|
197
|
+
if (tstat && tstat.isDirectory() && !seen.has(relpath(path, target))) {
|
|
191
198
|
await assertNoNewer(path, data, lockTime, target, seen)
|
|
199
|
+
}
|
|
192
200
|
}
|
|
193
201
|
})))
|
|
194
202
|
.then(() => {
|
|
195
|
-
if (dir !== path)
|
|
203
|
+
if (dir !== path) {
|
|
196
204
|
return
|
|
205
|
+
}
|
|
197
206
|
|
|
198
207
|
// assert that all the entries in the lockfile were seen
|
|
199
208
|
for (const loc of new Set(Object.keys(data.packages))) {
|
|
200
|
-
if (!seen.has(loc))
|
|
209
|
+
if (!seen.has(loc)) {
|
|
201
210
|
throw 'missing from node_modules: ' + loc
|
|
211
|
+
}
|
|
202
212
|
}
|
|
203
213
|
})
|
|
204
214
|
}
|
|
@@ -252,39 +262,48 @@ class Shrinkwrap {
|
|
|
252
262
|
const meta = {}
|
|
253
263
|
pkgMetaKeys.forEach(key => {
|
|
254
264
|
const val = metaFieldFromPkg(node.package, key)
|
|
255
|
-
if (val)
|
|
265
|
+
if (val) {
|
|
256
266
|
meta[key.replace(/^_/, '')] = val
|
|
267
|
+
}
|
|
257
268
|
})
|
|
258
269
|
// we only include name if different from the node path name, and for the
|
|
259
270
|
// root to help prevent churn based on the name of the directory the
|
|
260
271
|
// project is in
|
|
261
272
|
const pname = node.packageName
|
|
262
|
-
if (pname && (node === node.root || pname !== node.name))
|
|
273
|
+
if (pname && (node === node.root || pname !== node.name)) {
|
|
263
274
|
meta.name = pname
|
|
275
|
+
}
|
|
264
276
|
|
|
265
|
-
if (node.isTop && node.package.devDependencies)
|
|
277
|
+
if (node.isTop && node.package.devDependencies) {
|
|
266
278
|
meta.devDependencies = node.package.devDependencies
|
|
279
|
+
}
|
|
267
280
|
|
|
268
281
|
nodeMetaKeys.forEach(key => {
|
|
269
|
-
if (node[key])
|
|
282
|
+
if (node[key]) {
|
|
270
283
|
meta[key] = node[key]
|
|
284
|
+
}
|
|
271
285
|
})
|
|
272
286
|
|
|
273
287
|
const resolved = consistentResolve(node.resolved, node.path, path, true)
|
|
274
|
-
if (resolved)
|
|
288
|
+
if (resolved) {
|
|
275
289
|
meta.resolved = resolved
|
|
290
|
+
}
|
|
276
291
|
|
|
277
|
-
if (node.extraneous)
|
|
292
|
+
if (node.extraneous) {
|
|
278
293
|
meta.extraneous = true
|
|
279
|
-
else {
|
|
280
|
-
if (node.peer)
|
|
294
|
+
} else {
|
|
295
|
+
if (node.peer) {
|
|
281
296
|
meta.peer = true
|
|
282
|
-
|
|
297
|
+
}
|
|
298
|
+
if (node.dev) {
|
|
283
299
|
meta.dev = true
|
|
284
|
-
|
|
300
|
+
}
|
|
301
|
+
if (node.optional) {
|
|
285
302
|
meta.optional = true
|
|
286
|
-
|
|
303
|
+
}
|
|
304
|
+
if (node.devOptional && !node.dev && !node.optional) {
|
|
287
305
|
meta.devOptional = true
|
|
306
|
+
}
|
|
288
307
|
}
|
|
289
308
|
return meta
|
|
290
309
|
}
|
|
@@ -423,8 +442,9 @@ class Shrinkwrap {
|
|
|
423
442
|
this.indent = indent !== undefined ? indent : this.indent
|
|
424
443
|
this.newline = newline !== undefined ? newline : this.newline
|
|
425
444
|
|
|
426
|
-
if (!this.hiddenLockfile || !data.packages)
|
|
445
|
+
if (!this.hiddenLockfile || !data.packages) {
|
|
427
446
|
return data
|
|
447
|
+
}
|
|
428
448
|
|
|
429
449
|
// add a few ms just to account for jitter
|
|
430
450
|
const lockTime = +(await stat(this.filename)).mtime + 10
|
|
@@ -467,8 +487,9 @@ class Shrinkwrap {
|
|
|
467
487
|
// migrate a v1 package lock to the new format.
|
|
468
488
|
const meta = this[_metaFromLock](location, name, lock)
|
|
469
489
|
// dependencies nested under a link are actually under the link target
|
|
470
|
-
if (meta.link)
|
|
490
|
+
if (meta.link) {
|
|
471
491
|
location = meta.resolved
|
|
492
|
+
}
|
|
472
493
|
if (lock.dependencies) {
|
|
473
494
|
for (const [name, dep] of Object.entries(lock.dependencies)) {
|
|
474
495
|
const loc = location + (location ? '/' : '') + 'node_modules/' + name
|
|
@@ -488,13 +509,15 @@ class Shrinkwrap {
|
|
|
488
509
|
pkgMetaKeys.forEach(key => {
|
|
489
510
|
const val = metaFieldFromPkg(pkg, key)
|
|
490
511
|
const k = key.replace(/^_/, '')
|
|
491
|
-
if (val)
|
|
512
|
+
if (val) {
|
|
492
513
|
root[k] = val
|
|
514
|
+
}
|
|
493
515
|
})
|
|
494
516
|
|
|
495
517
|
for (const [loc, meta] of Object.entries(this.data.packages)) {
|
|
496
|
-
if (!meta.requires || !loc)
|
|
518
|
+
if (!meta.requires || !loc) {
|
|
497
519
|
continue
|
|
520
|
+
}
|
|
498
521
|
|
|
499
522
|
// resolve each require to a meta entry
|
|
500
523
|
// if this node isn't optional, but the dep is, then it's an optionalDep
|
|
@@ -523,27 +546,33 @@ class Shrinkwrap {
|
|
|
523
546
|
[_resolveMetaNode] (loc, name) {
|
|
524
547
|
for (let path = loc; true; path = path.replace(/(^|\/)[^/]*$/, '')) {
|
|
525
548
|
const check = `${path}${path ? '/' : ''}node_modules/${name}`
|
|
526
|
-
if (this.data.packages[check])
|
|
549
|
+
if (this.data.packages[check]) {
|
|
527
550
|
return this.data.packages[check]
|
|
551
|
+
}
|
|
528
552
|
|
|
529
|
-
if (!path)
|
|
553
|
+
if (!path) {
|
|
530
554
|
break
|
|
555
|
+
}
|
|
531
556
|
}
|
|
532
557
|
return null
|
|
533
558
|
}
|
|
534
559
|
|
|
535
560
|
[_lockFromLoc] (lock, path, i = 0) {
|
|
536
|
-
if (!lock)
|
|
561
|
+
if (!lock) {
|
|
537
562
|
return null
|
|
563
|
+
}
|
|
538
564
|
|
|
539
|
-
if (path[i] === '')
|
|
565
|
+
if (path[i] === '') {
|
|
540
566
|
i++
|
|
567
|
+
}
|
|
541
568
|
|
|
542
|
-
if (i >= path.length)
|
|
569
|
+
if (i >= path.length) {
|
|
543
570
|
return lock
|
|
571
|
+
}
|
|
544
572
|
|
|
545
|
-
if (!lock.dependencies)
|
|
573
|
+
if (!lock.dependencies) {
|
|
546
574
|
return null
|
|
575
|
+
}
|
|
547
576
|
|
|
548
577
|
return this[_lockFromLoc](lock.dependencies[path[i]], path, i + 1)
|
|
549
578
|
}
|
|
@@ -555,8 +584,9 @@ class Shrinkwrap {
|
|
|
555
584
|
}
|
|
556
585
|
|
|
557
586
|
delete (nodePath) {
|
|
558
|
-
if (!this.data)
|
|
587
|
+
if (!this.data) {
|
|
559
588
|
throw new Error('run load() before getting or setting data')
|
|
589
|
+
}
|
|
560
590
|
const location = this[_pathToLoc](nodePath)
|
|
561
591
|
this[_awaitingUpdate].delete(location)
|
|
562
592
|
|
|
@@ -564,22 +594,26 @@ class Shrinkwrap {
|
|
|
564
594
|
const path = location.split(/(?:^|\/)node_modules\//)
|
|
565
595
|
const name = path.pop()
|
|
566
596
|
const pLock = this[_lockFromLoc](this.data, path)
|
|
567
|
-
if (pLock && pLock.dependencies)
|
|
597
|
+
if (pLock && pLock.dependencies) {
|
|
568
598
|
delete pLock.dependencies[name]
|
|
599
|
+
}
|
|
569
600
|
}
|
|
570
601
|
|
|
571
602
|
get (nodePath) {
|
|
572
|
-
if (!this.data)
|
|
603
|
+
if (!this.data) {
|
|
573
604
|
throw new Error('run load() before getting or setting data')
|
|
605
|
+
}
|
|
574
606
|
|
|
575
607
|
const location = this[_pathToLoc](nodePath)
|
|
576
|
-
if (this[_awaitingUpdate].has(location))
|
|
608
|
+
if (this[_awaitingUpdate].has(location)) {
|
|
577
609
|
this[_updateWaitingNode](location)
|
|
610
|
+
}
|
|
578
611
|
|
|
579
612
|
// first try to get from the newer spot, which we know has
|
|
580
613
|
// all the things we need.
|
|
581
|
-
if (this.data.packages[location])
|
|
614
|
+
if (this.data.packages[location]) {
|
|
582
615
|
return this.data.packages[location]
|
|
616
|
+
}
|
|
583
617
|
|
|
584
618
|
// otherwise, fall back to the legacy metadata, and hope for the best
|
|
585
619
|
// get the node in the shrinkwrap corresponding to this spot
|
|
@@ -595,8 +629,9 @@ class Shrinkwrap {
|
|
|
595
629
|
// from a lockfile which may be outdated or incomplete. Since v1
|
|
596
630
|
// lockfiles used the "version" field to contain a variety of
|
|
597
631
|
// different possible types of data, this gets a little complicated.
|
|
598
|
-
if (!lock)
|
|
632
|
+
if (!lock) {
|
|
599
633
|
return {}
|
|
634
|
+
}
|
|
600
635
|
|
|
601
636
|
// try to figure out a npm-package-arg spec from the lockfile entry
|
|
602
637
|
// This will return null if we could not get anything valid out of it.
|
|
@@ -613,29 +648,35 @@ class Shrinkwrap {
|
|
|
613
648
|
}
|
|
614
649
|
// also save the link target, omitting version since we don't know
|
|
615
650
|
// what it is, but we know it isn't a link to itself!
|
|
616
|
-
if (!this.data.packages[target])
|
|
651
|
+
if (!this.data.packages[target]) {
|
|
617
652
|
this[_metaFromLock](target, name, { ...lock, version: null })
|
|
653
|
+
}
|
|
618
654
|
return this.data.packages[location]
|
|
619
655
|
}
|
|
620
656
|
|
|
621
657
|
const meta = {}
|
|
622
658
|
// when calling loadAll we'll change these into proper dep objects
|
|
623
|
-
if (lock.requires && typeof lock.requires === 'object')
|
|
659
|
+
if (lock.requires && typeof lock.requires === 'object') {
|
|
624
660
|
meta.requires = lock.requires
|
|
661
|
+
}
|
|
625
662
|
|
|
626
|
-
if (lock.optional)
|
|
663
|
+
if (lock.optional) {
|
|
627
664
|
meta.optional = true
|
|
628
|
-
|
|
665
|
+
}
|
|
666
|
+
if (lock.dev) {
|
|
629
667
|
meta.dev = true
|
|
668
|
+
}
|
|
630
669
|
|
|
631
670
|
// the root will typically have a name from the root project's
|
|
632
671
|
// package.json file.
|
|
633
|
-
if (location === '')
|
|
672
|
+
if (location === '') {
|
|
634
673
|
meta.name = lock.name
|
|
674
|
+
}
|
|
635
675
|
|
|
636
676
|
// if we have integrity, save it now.
|
|
637
|
-
if (lock.integrity)
|
|
677
|
+
if (lock.integrity) {
|
|
638
678
|
meta.integrity = lock.integrity
|
|
679
|
+
}
|
|
639
680
|
|
|
640
681
|
if (lock.version && !lock.integrity) {
|
|
641
682
|
// this is usually going to be a git url or symlink, but it could
|
|
@@ -668,12 +709,13 @@ class Shrinkwrap {
|
|
|
668
709
|
// have a fetchSpec equal to the fully resolved thing.
|
|
669
710
|
// Registry deps, we take what's in the lockfile.
|
|
670
711
|
if (lock.resolved || (spec.type && !spec.registry)) {
|
|
671
|
-
if (spec.registry)
|
|
712
|
+
if (spec.registry) {
|
|
672
713
|
meta.resolved = lock.resolved
|
|
673
|
-
else if (spec.type === 'file')
|
|
714
|
+
} else if (spec.type === 'file') {
|
|
674
715
|
meta.resolved = consistentResolve(spec, this.path, this.path, true)
|
|
675
|
-
else if (spec.fetchSpec)
|
|
716
|
+
} else if (spec.fetchSpec) {
|
|
676
717
|
meta.resolved = spec.fetchSpec
|
|
718
|
+
}
|
|
677
719
|
}
|
|
678
720
|
|
|
679
721
|
// at this point, if still we don't have a version, do our best to
|
|
@@ -685,32 +727,37 @@ class Shrinkwrap {
|
|
|
685
727
|
versionFromTgz(spec.name, meta.resolved)
|
|
686
728
|
if (fromTgz) {
|
|
687
729
|
meta.version = fromTgz.version
|
|
688
|
-
if (fromTgz.name !== name)
|
|
730
|
+
if (fromTgz.name !== name) {
|
|
689
731
|
meta.name = fromTgz.name
|
|
732
|
+
}
|
|
690
733
|
}
|
|
691
734
|
} else if (spec.type === 'alias') {
|
|
692
735
|
meta.name = spec.subSpec.name
|
|
693
736
|
meta.version = spec.subSpec.fetchSpec
|
|
694
|
-
} else if (spec.type === 'version')
|
|
737
|
+
} else if (spec.type === 'version') {
|
|
695
738
|
meta.version = spec.fetchSpec
|
|
739
|
+
}
|
|
696
740
|
// ok, I did my best! good luck!
|
|
697
741
|
}
|
|
698
742
|
|
|
699
|
-
if (lock.bundled)
|
|
743
|
+
if (lock.bundled) {
|
|
700
744
|
meta.inBundle = true
|
|
745
|
+
}
|
|
701
746
|
|
|
702
747
|
// save it for next time
|
|
703
748
|
return this.data.packages[location] = meta
|
|
704
749
|
}
|
|
705
750
|
|
|
706
751
|
add (node) {
|
|
707
|
-
if (!this.data)
|
|
752
|
+
if (!this.data) {
|
|
708
753
|
throw new Error('run load() before getting or setting data')
|
|
754
|
+
}
|
|
709
755
|
|
|
710
756
|
// will be actually updated on read
|
|
711
757
|
const loc = relpath(this.path, node.path)
|
|
712
|
-
if (node.path === this.path)
|
|
758
|
+
if (node.path === this.path) {
|
|
713
759
|
this.tree = node
|
|
760
|
+
}
|
|
714
761
|
|
|
715
762
|
// if we have metadata about this node, and it's a match, then
|
|
716
763
|
// try to decorate it.
|
|
@@ -758,18 +805,21 @@ class Shrinkwrap {
|
|
|
758
805
|
}
|
|
759
806
|
|
|
760
807
|
addEdge (edge) {
|
|
761
|
-
if (!this.yarnLock || !edge.valid)
|
|
808
|
+
if (!this.yarnLock || !edge.valid) {
|
|
762
809
|
return
|
|
810
|
+
}
|
|
763
811
|
|
|
764
812
|
const { to: node } = edge
|
|
765
813
|
|
|
766
814
|
// if it's already set up, nothing to do
|
|
767
|
-
if (node.resolved !== null && node.integrity !== null)
|
|
815
|
+
if (node.resolved !== null && node.integrity !== null) {
|
|
768
816
|
return
|
|
817
|
+
}
|
|
769
818
|
|
|
770
819
|
// if the yarn lock is empty, nothing to do
|
|
771
|
-
if (!this.yarnLock.entries || !this.yarnLock.entries.size)
|
|
820
|
+
if (!this.yarnLock.entries || !this.yarnLock.entries.size) {
|
|
772
821
|
return
|
|
822
|
+
}
|
|
773
823
|
|
|
774
824
|
// we relativize the path here because that's how it shows up in the lock
|
|
775
825
|
// XXX how is this different from pathFixed above??
|
|
@@ -783,11 +833,13 @@ class Shrinkwrap {
|
|
|
783
833
|
if (!entry ||
|
|
784
834
|
mismatch(node.version, entry.version) ||
|
|
785
835
|
mismatch(node.integrity, entry.integrity) ||
|
|
786
|
-
mismatch(pathFixed, entry.resolved))
|
|
836
|
+
mismatch(pathFixed, entry.resolved)) {
|
|
787
837
|
return
|
|
838
|
+
}
|
|
788
839
|
|
|
789
|
-
if (entry.resolved && yarnRegRe.test(entry.resolved) && spec.registry)
|
|
840
|
+
if (entry.resolved && yarnRegRe.test(entry.resolved) && spec.registry) {
|
|
790
841
|
entry.resolved = entry.resolved.replace(yarnRegRe, 'https://registry.npmjs.org/')
|
|
842
|
+
}
|
|
791
843
|
|
|
792
844
|
node.integrity = node.integrity || entry.integrity || null
|
|
793
845
|
node.resolved = node.resolved ||
|
|
@@ -804,30 +856,35 @@ class Shrinkwrap {
|
|
|
804
856
|
|
|
805
857
|
commit () {
|
|
806
858
|
if (this.tree) {
|
|
807
|
-
if (this.yarnLock)
|
|
859
|
+
if (this.yarnLock) {
|
|
808
860
|
this.yarnLock.fromTree(this.tree)
|
|
861
|
+
}
|
|
809
862
|
const root = Shrinkwrap.metaFromNode(this.tree.target, this.path)
|
|
810
863
|
this.data.packages = {}
|
|
811
|
-
if (Object.keys(root).length)
|
|
864
|
+
if (Object.keys(root).length) {
|
|
812
865
|
this.data.packages[''] = root
|
|
866
|
+
}
|
|
813
867
|
for (const node of this.tree.root.inventory.values()) {
|
|
814
868
|
// only way this.tree is not root is if the root is a link to it
|
|
815
|
-
if (node === this.tree || node.isRoot || node.location === '')
|
|
869
|
+
if (node === this.tree || node.isRoot || node.location === '') {
|
|
816
870
|
continue
|
|
871
|
+
}
|
|
817
872
|
const loc = relpath(this.path, node.path)
|
|
818
873
|
this.data.packages[loc] = Shrinkwrap.metaFromNode(node, this.path)
|
|
819
874
|
}
|
|
820
875
|
} else if (this[_awaitingUpdate].size > 0) {
|
|
821
|
-
for (const loc of this[_awaitingUpdate].keys())
|
|
876
|
+
for (const loc of this[_awaitingUpdate].keys()) {
|
|
822
877
|
this[_updateWaitingNode](loc)
|
|
878
|
+
}
|
|
823
879
|
}
|
|
824
880
|
|
|
825
881
|
// hidden lockfiles don't include legacy metadata or a root entry
|
|
826
882
|
if (this.hiddenLockfile) {
|
|
827
883
|
delete this.data.packages['']
|
|
828
884
|
delete this.data.dependencies
|
|
829
|
-
} else if (this.tree)
|
|
885
|
+
} else if (this.tree) {
|
|
830
886
|
this[_buildLegacyLockfile](this.tree, this.data)
|
|
887
|
+
}
|
|
831
888
|
|
|
832
889
|
return this.data
|
|
833
890
|
}
|
|
@@ -836,8 +893,9 @@ class Shrinkwrap {
|
|
|
836
893
|
if (node === this.tree) {
|
|
837
894
|
// the root node
|
|
838
895
|
lock.name = node.packageName || node.name
|
|
839
|
-
if (node.version)
|
|
896
|
+
if (node.version) {
|
|
840
897
|
lock.version = node.version
|
|
898
|
+
}
|
|
841
899
|
}
|
|
842
900
|
|
|
843
901
|
// npm v6 and before tracked 'from', meaning "the request that led
|
|
@@ -854,7 +912,7 @@ class Shrinkwrap {
|
|
|
854
912
|
/* istanbul ignore next - sort calling order is indeterminate */
|
|
855
913
|
return aloc.length > bloc.length ? 1
|
|
856
914
|
: bloc.length > aloc.length ? -1
|
|
857
|
-
: aloc[aloc.length - 1]
|
|
915
|
+
: localeCompare(aloc[aloc.length - 1], bloc[bloc.length - 1])
|
|
858
916
|
})[0]
|
|
859
917
|
|
|
860
918
|
const res = consistentResolve(node.resolved, this.path, this.path, true)
|
|
@@ -868,26 +926,29 @@ class Shrinkwrap {
|
|
|
868
926
|
const spec = !edge ? rSpec
|
|
869
927
|
: npa.resolve(node.name, edge.spec, edge.from.realpath)
|
|
870
928
|
|
|
871
|
-
if (node.isLink)
|
|
929
|
+
if (node.isLink) {
|
|
872
930
|
lock.version = `file:${relpath(this.path, node.realpath)}`
|
|
873
|
-
else if (spec && (spec.type === 'file' || spec.type === 'remote'))
|
|
931
|
+
} else if (spec && (spec.type === 'file' || spec.type === 'remote')) {
|
|
874
932
|
lock.version = spec.saveSpec
|
|
875
|
-
else if (spec && spec.type === 'git' || rSpec.type === 'git') {
|
|
933
|
+
} else if (spec && spec.type === 'git' || rSpec.type === 'git') {
|
|
876
934
|
lock.version = node.resolved
|
|
877
935
|
/* istanbul ignore else - don't think there are any cases where a git
|
|
878
936
|
* spec (or indeed, ANY npa spec) doesn't have a .raw member */
|
|
879
|
-
if (spec.raw)
|
|
937
|
+
if (spec.raw) {
|
|
880
938
|
lock.from = spec.raw
|
|
939
|
+
}
|
|
881
940
|
} else if (!node.isRoot &&
|
|
882
941
|
node.package &&
|
|
883
942
|
node.packageName &&
|
|
884
|
-
node.packageName !== node.name)
|
|
943
|
+
node.packageName !== node.name) {
|
|
885
944
|
lock.version = `npm:${node.packageName}@${node.version}`
|
|
886
|
-
else if (node.package && node.version)
|
|
945
|
+
} else if (node.package && node.version) {
|
|
887
946
|
lock.version = node.version
|
|
947
|
+
}
|
|
888
948
|
|
|
889
|
-
if (node.inDepBundle)
|
|
949
|
+
if (node.inDepBundle) {
|
|
890
950
|
lock.bundled = true
|
|
951
|
+
}
|
|
891
952
|
|
|
892
953
|
// when we didn't resolve to git, file, or dir, and didn't request
|
|
893
954
|
// git, file, dir, or remote, then the resolved value is necessary.
|
|
@@ -899,77 +960,90 @@ class Shrinkwrap {
|
|
|
899
960
|
spec.type !== 'directory' &&
|
|
900
961
|
spec.type !== 'git' &&
|
|
901
962
|
spec.type !== 'file' &&
|
|
902
|
-
spec.type !== 'remote')
|
|
963
|
+
spec.type !== 'remote') {
|
|
903
964
|
lock.resolved = node.resolved
|
|
965
|
+
}
|
|
904
966
|
|
|
905
|
-
if (node.integrity)
|
|
967
|
+
if (node.integrity) {
|
|
906
968
|
lock.integrity = node.integrity
|
|
969
|
+
}
|
|
907
970
|
|
|
908
|
-
if (node.extraneous)
|
|
971
|
+
if (node.extraneous) {
|
|
909
972
|
lock.extraneous = true
|
|
910
|
-
else if (!node.isLink) {
|
|
911
|
-
if (node.peer)
|
|
973
|
+
} else if (!node.isLink) {
|
|
974
|
+
if (node.peer) {
|
|
912
975
|
lock.peer = true
|
|
976
|
+
}
|
|
913
977
|
|
|
914
|
-
if (node.devOptional && !node.dev && !node.optional)
|
|
978
|
+
if (node.devOptional && !node.dev && !node.optional) {
|
|
915
979
|
lock.devOptional = true
|
|
980
|
+
}
|
|
916
981
|
|
|
917
|
-
if (node.dev)
|
|
982
|
+
if (node.dev) {
|
|
918
983
|
lock.dev = true
|
|
984
|
+
}
|
|
919
985
|
|
|
920
|
-
if (node.optional)
|
|
986
|
+
if (node.optional) {
|
|
921
987
|
lock.optional = true
|
|
988
|
+
}
|
|
922
989
|
}
|
|
923
990
|
|
|
924
991
|
const depender = node.target
|
|
925
992
|
if (depender.edgesOut.size > 0) {
|
|
926
993
|
if (node !== this.tree) {
|
|
927
|
-
|
|
994
|
+
const entries = [...depender.edgesOut.entries()]
|
|
995
|
+
lock.requires = entries.reduce((set, [k, v]) => {
|
|
928
996
|
// omit peer deps from legacy lockfile requires field, because
|
|
929
997
|
// npm v6 doesn't handle peer deps, and this triggers some bad
|
|
930
998
|
// behavior if the dep can't be found in the dependencies list.
|
|
931
999
|
const { spec, peer } = v
|
|
932
|
-
if (peer)
|
|
1000
|
+
if (peer) {
|
|
933
1001
|
return set
|
|
1002
|
+
}
|
|
934
1003
|
if (spec.startsWith('file:')) {
|
|
935
1004
|
// turn absolute file: paths into relative paths from the node
|
|
936
1005
|
// this especially shows up with workspace edges when the root
|
|
937
1006
|
// node is also a workspace in the set.
|
|
938
1007
|
const p = resolve(node.realpath, spec.substr('file:'.length))
|
|
939
1008
|
set[k] = `file:${relpath(node.realpath, p)}`
|
|
940
|
-
} else
|
|
1009
|
+
} else {
|
|
941
1010
|
set[k] = spec
|
|
1011
|
+
}
|
|
942
1012
|
return set
|
|
943
1013
|
}, {})
|
|
944
|
-
} else
|
|
1014
|
+
} else {
|
|
945
1015
|
lock.requires = true
|
|
1016
|
+
}
|
|
946
1017
|
}
|
|
947
1018
|
|
|
948
1019
|
// now we walk the children, putting them in the 'dependencies' object
|
|
949
1020
|
const {children} = node.target
|
|
950
|
-
if (!children.size)
|
|
1021
|
+
if (!children.size) {
|
|
951
1022
|
delete lock.dependencies
|
|
952
|
-
else {
|
|
1023
|
+
} else {
|
|
953
1024
|
const kidPath = [...path, node.realpath]
|
|
954
1025
|
const dependencies = {}
|
|
955
1026
|
// skip any that are already in the descent path, so cyclical link
|
|
956
1027
|
// dependencies don't blow up with ELOOP.
|
|
957
1028
|
let found = false
|
|
958
1029
|
for (const [name, kid] of children.entries()) {
|
|
959
|
-
if (path.includes(kid.realpath))
|
|
1030
|
+
if (path.includes(kid.realpath)) {
|
|
960
1031
|
continue
|
|
1032
|
+
}
|
|
961
1033
|
dependencies[name] = this[_buildLegacyLockfile](kid, {}, kidPath)
|
|
962
1034
|
found = true
|
|
963
1035
|
}
|
|
964
|
-
if (found)
|
|
1036
|
+
if (found) {
|
|
965
1037
|
lock.dependencies = dependencies
|
|
1038
|
+
}
|
|
966
1039
|
}
|
|
967
1040
|
return lock
|
|
968
1041
|
}
|
|
969
1042
|
|
|
970
1043
|
save (options = {}) {
|
|
971
|
-
if (!this.data)
|
|
1044
|
+
if (!this.data) {
|
|
972
1045
|
throw new Error('run load() before saving data')
|
|
1046
|
+
}
|
|
973
1047
|
|
|
974
1048
|
const { format = true } = options
|
|
975
1049
|
const defaultIndent = this.indent || 2
|
package/lib/signal-handling.js
CHANGED
|
@@ -13,8 +13,9 @@ const setup = fn => {
|
|
|
13
13
|
const sigListeners = { loaded: false }
|
|
14
14
|
|
|
15
15
|
const unload = () => {
|
|
16
|
-
if (!sigListeners.loaded)
|
|
16
|
+
if (!sigListeners.loaded) {
|
|
17
17
|
return
|
|
18
|
+
}
|
|
18
19
|
for (const sig of signals) {
|
|
19
20
|
try {
|
|
20
21
|
process.removeListener(sig, sigListeners[sig])
|
|
@@ -43,8 +44,9 @@ const setup = fn => {
|
|
|
43
44
|
// if we exit normally, but caught a signal which would have been fatal,
|
|
44
45
|
// then re-send it once we're done with whatever cleanup we have to do.
|
|
45
46
|
unload()
|
|
46
|
-
if (process.listeners(sig).length < 1)
|
|
47
|
+
if (process.listeners(sig).length < 1) {
|
|
47
48
|
process.once('beforeExit', onBeforeExit)
|
|
49
|
+
}
|
|
48
50
|
|
|
49
51
|
fn({ signal: sig })
|
|
50
52
|
}
|
|
@@ -56,8 +58,9 @@ const setup = fn => {
|
|
|
56
58
|
try {
|
|
57
59
|
// if we call this a bunch of times, avoid triggering the warning
|
|
58
60
|
const { length } = process.listeners(sig)
|
|
59
|
-
if (length >= max)
|
|
61
|
+
if (length >= max) {
|
|
60
62
|
process.setMaxListeners(length + 1)
|
|
63
|
+
}
|
|
61
64
|
process.on(sig, sigListeners[sig])
|
|
62
65
|
} catch (er) {}
|
|
63
66
|
}
|
package/lib/spec-from-lock.js
CHANGED
|
@@ -5,19 +5,22 @@ const specFromLock = (name, lock, where) => {
|
|
|
5
5
|
try {
|
|
6
6
|
if (lock.version) {
|
|
7
7
|
const spec = npa.resolve(name, lock.version, where)
|
|
8
|
-
if (lock.integrity || spec.type === 'git')
|
|
8
|
+
if (lock.integrity || spec.type === 'git') {
|
|
9
9
|
return spec
|
|
10
|
+
}
|
|
10
11
|
}
|
|
11
12
|
if (lock.from) {
|
|
12
13
|
// legacy metadata includes "from", but not integrity
|
|
13
14
|
const spec = npa.resolve(name, lock.from, where)
|
|
14
|
-
if (spec.registry && lock.version)
|
|
15
|
+
if (spec.registry && lock.version) {
|
|
15
16
|
return npa.resolve(name, lock.version, where)
|
|
16
|
-
else if (!lock.resolved)
|
|
17
|
+
} else if (!lock.resolved) {
|
|
17
18
|
return spec
|
|
19
|
+
}
|
|
18
20
|
}
|
|
19
|
-
if (lock.resolved)
|
|
21
|
+
if (lock.resolved) {
|
|
20
22
|
return npa.resolve(name, lock.resolved, where)
|
|
23
|
+
}
|
|
21
24
|
} catch (_) { }
|
|
22
25
|
try {
|
|
23
26
|
return npa.resolve(name, lock.version, where)
|