@npmcli/arborist 2.2.8 → 2.4.1
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/lib/logging.js +10 -2
- package/bin/lib/options.js +7 -1
- package/bin/lib/timers.js +6 -2
- package/bin/virtual.js +2 -1
- package/lib/add-rm-pkg-deps.js +1 -1
- package/lib/arborist/build-ideal-tree.js +260 -73
- package/lib/arborist/index.js +1 -1
- package/lib/arborist/load-actual.js +28 -2
- package/lib/arborist/load-virtual.js +9 -6
- package/lib/arborist/rebuild.js +5 -4
- package/lib/arborist/reify.js +163 -35
- package/lib/debug.js +8 -1
- package/lib/diff.js +70 -11
- package/lib/index.js +1 -0
- package/lib/link.js +13 -7
- package/lib/node.js +43 -2
- package/lib/printable.js +18 -0
- package/lib/tree-check.js +46 -1
- package/package.json +6 -9
package/lib/link.js
CHANGED
|
@@ -23,13 +23,19 @@ class Link extends Node {
|
|
|
23
23
|
: null),
|
|
24
24
|
})
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
if (target)
|
|
27
|
+
this.target = target
|
|
28
|
+
else if (this.realpath === this.root.path)
|
|
29
|
+
this.target = this.root
|
|
30
|
+
else {
|
|
31
|
+
this.target = new Node({
|
|
32
|
+
...options,
|
|
33
|
+
path: realpath,
|
|
34
|
+
parent: null,
|
|
35
|
+
fsParent: null,
|
|
36
|
+
root: this.root,
|
|
37
|
+
})
|
|
38
|
+
}
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
get version () {
|
package/lib/node.js
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
// where we need to quickly find all instances of a given package name within a
|
|
29
29
|
// tree.
|
|
30
30
|
|
|
31
|
+
const semver = require('semver')
|
|
31
32
|
const nameFromFolder = require('@npmcli/name-from-folder')
|
|
32
33
|
const Edge = require('./edge.js')
|
|
33
34
|
const Inventory = require('./inventory.js')
|
|
@@ -685,6 +686,7 @@ class Node {
|
|
|
685
686
|
...this.children.values(),
|
|
686
687
|
...this.inventory.values(),
|
|
687
688
|
].filter(n => n !== this))
|
|
689
|
+
|
|
688
690
|
for (const child of family) {
|
|
689
691
|
if (child.root !== root) {
|
|
690
692
|
child[_delistFromMeta]()
|
|
@@ -704,12 +706,14 @@ class Node {
|
|
|
704
706
|
}
|
|
705
707
|
|
|
706
708
|
// if we had a target, and didn't find one in the new root, then bring
|
|
707
|
-
// it over as well
|
|
708
|
-
|
|
709
|
+
// it over as well, but only if we're setting the link into a new root,
|
|
710
|
+
// as we don't want to lose the target any time we remove a link.
|
|
711
|
+
if (this.isLink && target && !this.target && root !== this)
|
|
709
712
|
target.root = root
|
|
710
713
|
|
|
711
714
|
// tree should always be valid upon root setter completion.
|
|
712
715
|
treeCheck(this)
|
|
716
|
+
treeCheck(root)
|
|
713
717
|
}
|
|
714
718
|
|
|
715
719
|
get root () {
|
|
@@ -882,6 +886,43 @@ class Node {
|
|
|
882
886
|
return node.canReplaceWith(this)
|
|
883
887
|
}
|
|
884
888
|
|
|
889
|
+
// return true if it's safe to remove this node, because anything that
|
|
890
|
+
// is depending on it would be fine with the thing that they would resolve
|
|
891
|
+
// to if it was removed, or nothing is depending on it in the first place.
|
|
892
|
+
canDedupe (preferDedupe = false) {
|
|
893
|
+
// not allowed to mess with shrinkwraps or bundles
|
|
894
|
+
if (this.inDepBundle || this.inShrinkwrap)
|
|
895
|
+
return false
|
|
896
|
+
|
|
897
|
+
// it's a top level pkg, or a dep of one
|
|
898
|
+
if (!this.parent || !this.parent.parent)
|
|
899
|
+
return false
|
|
900
|
+
|
|
901
|
+
// no one wants it, remove it
|
|
902
|
+
if (this.edgesIn.size === 0)
|
|
903
|
+
return true
|
|
904
|
+
|
|
905
|
+
const other = this.parent.parent.resolve(this.name)
|
|
906
|
+
|
|
907
|
+
// nothing else, need this one
|
|
908
|
+
if (!other)
|
|
909
|
+
return false
|
|
910
|
+
|
|
911
|
+
// if it's the same thing, then always fine to remove
|
|
912
|
+
if (other.matches(this))
|
|
913
|
+
return true
|
|
914
|
+
|
|
915
|
+
// if the other thing can't replace this, then skip it
|
|
916
|
+
if (!other.canReplace(this))
|
|
917
|
+
return false
|
|
918
|
+
|
|
919
|
+
// if we prefer dedupe, or if the version is greater/equal, take the other
|
|
920
|
+
if (preferDedupe || semver.gte(other.version, this.version))
|
|
921
|
+
return true
|
|
922
|
+
|
|
923
|
+
return false
|
|
924
|
+
}
|
|
925
|
+
|
|
885
926
|
satisfies (requested) {
|
|
886
927
|
if (requested instanceof Edge)
|
|
887
928
|
return this.name === requested.name && requested.satisfiedBy(this)
|
package/lib/printable.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// of the current node and its descendents
|
|
3
3
|
|
|
4
4
|
const util = require('util')
|
|
5
|
+
const relpath = require('./relpath.js')
|
|
5
6
|
|
|
6
7
|
class ArboristNode {
|
|
7
8
|
constructor (tree, path) {
|
|
@@ -28,6 +29,15 @@ class ArboristNode {
|
|
|
28
29
|
this.peer = true
|
|
29
30
|
if (tree.inBundle)
|
|
30
31
|
this.bundled = true
|
|
32
|
+
if (tree.inDepBundle)
|
|
33
|
+
this.bundler = tree.getBundler().location
|
|
34
|
+
const bd = tree.package && tree.package.bundleDependencies
|
|
35
|
+
if (bd && bd.length)
|
|
36
|
+
this.bundleDependencies = bd
|
|
37
|
+
if (tree.inShrinkwrap)
|
|
38
|
+
this.inShrinkwrap = true
|
|
39
|
+
else if (tree.hasShrinkwrap)
|
|
40
|
+
this.hasShrinkwrap = true
|
|
31
41
|
if (tree.error)
|
|
32
42
|
this.error = treeError(tree.error)
|
|
33
43
|
if (tree.errors && tree.errors.length)
|
|
@@ -47,6 +57,11 @@ class ArboristNode {
|
|
|
47
57
|
.map(edge => new EdgeIn(edge)))
|
|
48
58
|
}
|
|
49
59
|
|
|
60
|
+
if (tree.workspaces && tree.workspaces.size) {
|
|
61
|
+
this.workspaces = new Map([...tree.workspaces.entries()]
|
|
62
|
+
.map(([name, path]) => [name, relpath(tree.root.realpath, path)]))
|
|
63
|
+
}
|
|
64
|
+
|
|
50
65
|
// fsChildren sorted by path
|
|
51
66
|
if (tree.fsChildren.size) {
|
|
52
67
|
this.fsChildren = new Set([...tree.fsChildren]
|
|
@@ -126,6 +141,9 @@ class EdgeIn extends Edge {
|
|
|
126
141
|
}
|
|
127
142
|
|
|
128
143
|
const printableTree = (tree, path = []) => {
|
|
144
|
+
if (!tree)
|
|
145
|
+
return tree
|
|
146
|
+
|
|
129
147
|
const Cls = tree.isLink ? ArboristLink
|
|
130
148
|
: tree.sourceReference ? ArboristVirtualNode
|
|
131
149
|
: ArboristNode
|
package/lib/tree-check.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const debug = require('./debug.js')
|
|
2
2
|
|
|
3
3
|
const checkTree = (tree, checkUnreachable = true) => {
|
|
4
|
+
const log = [['START TREE CHECK', tree.path]]
|
|
5
|
+
|
|
4
6
|
// this can only happen in tests where we have a "tree" object
|
|
5
7
|
// that isn't actually a tree.
|
|
6
8
|
if (!tree.root || !tree.root.inventory)
|
|
@@ -9,8 +11,21 @@ const checkTree = (tree, checkUnreachable = true) => {
|
|
|
9
11
|
const { inventory } = tree.root
|
|
10
12
|
const seen = new Set()
|
|
11
13
|
const check = (node, via = tree, viaType = 'self') => {
|
|
14
|
+
log.push([
|
|
15
|
+
'CHECK',
|
|
16
|
+
node && node.location,
|
|
17
|
+
via && via.location,
|
|
18
|
+
viaType,
|
|
19
|
+
'seen=' + seen.has(node),
|
|
20
|
+
'promise=' + !!(node && node.then),
|
|
21
|
+
'root=' + !!(node && node.isRoot),
|
|
22
|
+
])
|
|
23
|
+
|
|
12
24
|
if (!node || seen.has(node) || node.then)
|
|
13
25
|
return
|
|
26
|
+
|
|
27
|
+
seen.add(node)
|
|
28
|
+
|
|
14
29
|
if (node.isRoot && node !== tree.root) {
|
|
15
30
|
throw Object.assign(new Error('double root'), {
|
|
16
31
|
node: node.path,
|
|
@@ -19,6 +34,7 @@ const checkTree = (tree, checkUnreachable = true) => {
|
|
|
19
34
|
root: tree.root.path,
|
|
20
35
|
via: via.path,
|
|
21
36
|
viaType,
|
|
37
|
+
log,
|
|
22
38
|
})
|
|
23
39
|
}
|
|
24
40
|
|
|
@@ -31,6 +47,7 @@ const checkTree = (tree, checkUnreachable = true) => {
|
|
|
31
47
|
via: via.path,
|
|
32
48
|
viaType,
|
|
33
49
|
otherRoot: node.root && node.root.path,
|
|
50
|
+
log,
|
|
34
51
|
})
|
|
35
52
|
}
|
|
36
53
|
|
|
@@ -43,6 +60,7 @@ const checkTree = (tree, checkUnreachable = true) => {
|
|
|
43
60
|
viaType,
|
|
44
61
|
inventory: [...node.inventory.values()].map(node =>
|
|
45
62
|
[node.path, node.location]),
|
|
63
|
+
log,
|
|
46
64
|
})
|
|
47
65
|
}
|
|
48
66
|
|
|
@@ -53,6 +71,7 @@ const checkTree = (tree, checkUnreachable = true) => {
|
|
|
53
71
|
root: tree.root.path,
|
|
54
72
|
via: via.path,
|
|
55
73
|
viaType,
|
|
74
|
+
log,
|
|
56
75
|
})
|
|
57
76
|
}
|
|
58
77
|
|
|
@@ -65,14 +84,38 @@ const checkTree = (tree, checkUnreachable = true) => {
|
|
|
65
84
|
via: via.path,
|
|
66
85
|
viaType,
|
|
67
86
|
devEdges: devEdges.map(e => [e.type, e.name, e.spec, e.error]),
|
|
87
|
+
log,
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (node.path === tree.root.path && node !== tree.root) {
|
|
92
|
+
throw Object.assign(new Error('node with same path as root'), {
|
|
93
|
+
node: node.path,
|
|
94
|
+
tree: tree.path,
|
|
95
|
+
root: tree.root.path,
|
|
96
|
+
via: via.path,
|
|
97
|
+
viaType,
|
|
98
|
+
log,
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!node.isLink && node.path !== node.realpath) {
|
|
103
|
+
throw Object.assign(new Error('non-link with mismatched path/realpath'), {
|
|
104
|
+
node: node.path,
|
|
105
|
+
tree: tree.path,
|
|
106
|
+
realpath: node.realpath,
|
|
107
|
+
root: tree.root.path,
|
|
108
|
+
via: via.path,
|
|
109
|
+
viaType,
|
|
110
|
+
log,
|
|
68
111
|
})
|
|
69
112
|
}
|
|
70
113
|
|
|
71
114
|
const { parent, fsParent, target } = node
|
|
72
|
-
seen.add(node)
|
|
73
115
|
check(parent, node, 'parent')
|
|
74
116
|
check(fsParent, node, 'fsParent')
|
|
75
117
|
check(target, node, 'target')
|
|
118
|
+
log.push(['CHILDREN', node.location, ...node.children.keys()])
|
|
76
119
|
for (const kid of node.children.values())
|
|
77
120
|
check(kid, node, 'children')
|
|
78
121
|
for (const kid of node.fsChildren)
|
|
@@ -81,6 +124,7 @@ const checkTree = (tree, checkUnreachable = true) => {
|
|
|
81
124
|
check(link, node, 'linksIn')
|
|
82
125
|
for (const top of node.tops)
|
|
83
126
|
check(top, node, 'tops')
|
|
127
|
+
log.push(['DONE', node.location])
|
|
84
128
|
}
|
|
85
129
|
check(tree)
|
|
86
130
|
if (checkUnreachable) {
|
|
@@ -92,6 +136,7 @@ const checkTree = (tree, checkUnreachable = true) => {
|
|
|
92
136
|
location: node.location,
|
|
93
137
|
root: tree.root.path,
|
|
94
138
|
tree: tree.path,
|
|
139
|
+
log,
|
|
95
140
|
})
|
|
96
141
|
}
|
|
97
142
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@npmcli/arborist",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "Manage node_modules trees",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@npmcli/installed-package-contents": "^1.0.7",
|
|
@@ -14,19 +14,19 @@
|
|
|
14
14
|
"cacache": "^15.0.3",
|
|
15
15
|
"common-ancestor-path": "^1.0.1",
|
|
16
16
|
"json-parse-even-better-errors": "^2.3.1",
|
|
17
|
-
"json-stringify-nice": "^1.1.
|
|
17
|
+
"json-stringify-nice": "^1.1.2",
|
|
18
18
|
"mkdirp-infer-owner": "^2.0.0",
|
|
19
19
|
"npm-install-checks": "^4.0.0",
|
|
20
20
|
"npm-package-arg": "^8.1.0",
|
|
21
21
|
"npm-pick-manifest": "^6.1.0",
|
|
22
|
-
"npm-registry-fetch": "^
|
|
22
|
+
"npm-registry-fetch": "^10.0.0",
|
|
23
23
|
"pacote": "^11.2.6",
|
|
24
24
|
"parse-conflict-json": "^1.1.1",
|
|
25
25
|
"promise-all-reject-late": "^1.0.0",
|
|
26
26
|
"promise-call-limit": "^1.0.1",
|
|
27
27
|
"read-package-json-fast": "^2.0.2",
|
|
28
28
|
"readdir-scoped-modules": "^1.1.0",
|
|
29
|
-
"semver": "^7.3.
|
|
29
|
+
"semver": "^7.3.5",
|
|
30
30
|
"tar": "^6.1.0",
|
|
31
31
|
"treeverse": "^1.0.4",
|
|
32
32
|
"walk-up-path": "^1.0.0"
|
|
@@ -41,8 +41,7 @@
|
|
|
41
41
|
"eslint-plugin-standard": "^4.0.1",
|
|
42
42
|
"minify-registry-metadata": "^2.1.0",
|
|
43
43
|
"mutate-fs": "^2.1.1",
|
|
44
|
-
"
|
|
45
|
-
"tap": "^14.11.0",
|
|
44
|
+
"tap": "^15.0.4",
|
|
46
45
|
"tcompare": "^3.0.4"
|
|
47
46
|
},
|
|
48
47
|
"scripts": {
|
|
@@ -76,10 +75,8 @@
|
|
|
76
75
|
"arborist": "bin/index.js"
|
|
77
76
|
},
|
|
78
77
|
"tap": {
|
|
79
|
-
"100": true,
|
|
80
78
|
"after": "test/fixtures/cleanup.js",
|
|
81
79
|
"coverage-map": "map.js",
|
|
82
|
-
"esm": false,
|
|
83
80
|
"test-env": [
|
|
84
81
|
"NODE_OPTIONS=--no-warnings"
|
|
85
82
|
],
|
|
@@ -87,6 +84,6 @@
|
|
|
87
84
|
"--no-warnings",
|
|
88
85
|
"--no-deprecation"
|
|
89
86
|
],
|
|
90
|
-
"timeout": "
|
|
87
|
+
"timeout": "240"
|
|
91
88
|
}
|
|
92
89
|
}
|