Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornlf <quitlahok@gmail.com>2021-12-03 01:45:44 +0300
committerGar <gar+gh@danger.computer>2021-12-09 00:26:22 +0300
commit4b0c29a7c5860410c7b453bec389c54cb21dbde3 (patch)
tree331a1876a7d431263f9627df69457ee2ad23cce0
parent4dbeb007d0d6350284c7b1edbf4d5b0030c67c66 (diff)
deps: @npmcli/arborist@4.1.0
PR-URL: https://github.com/npm/cli/pull/4116 Credit: @nlf Close: #4116 Reviewed-by: @wraithgar
-rw-r--r--node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js6
-rw-r--r--node_modules/@npmcli/arborist/lib/arborist/load-actual.js24
-rw-r--r--node_modules/@npmcli/arborist/lib/arborist/load-virtual.js1
-rw-r--r--node_modules/@npmcli/arborist/lib/edge.js41
-rw-r--r--node_modules/@npmcli/arborist/lib/node.js45
-rw-r--r--node_modules/@npmcli/arborist/lib/override-set.js123
-rw-r--r--node_modules/@npmcli/arborist/lib/place-dep.js1
-rw-r--r--node_modules/@npmcli/arborist/lib/printable.js13
-rw-r--r--node_modules/@npmcli/arborist/package.json7
-rw-r--r--package-lock.json14
-rw-r--r--package.json2
11 files changed, 258 insertions, 19 deletions
diff --git a/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js b/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
index aa37acfe5..899d92ca9 100644
--- a/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
+++ b/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js
@@ -379,6 +379,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
optional: false,
global: this[_global],
legacyPeerDeps: this.legacyPeerDeps,
+ loadOverrides: true,
})
if (root.isLink) {
root.target = new Node({
@@ -676,6 +677,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
// calls rather than walking over everything in the tree.
const set = this.idealTree.inventory
.filter(n => this[_shouldUpdateNode](n))
+ // XXX add any invalid edgesOut to the queue
for (const node of set) {
for (const edge of node.edgesIn) {
this.addTracker('idealTree', edge.from.name, edge.from.location)
@@ -772,7 +774,10 @@ This is a one-time fix-up, please be patient...
[_buildDeps] () {
process.emit('time', 'idealTree:buildDeps')
const tree = this.idealTree.target
+ tree.assertRootOverrides()
this[_depsQueue].push(tree)
+ // XXX also push anything that depends on a node with a name
+ // in the override list
this.log.silly('idealTree', 'buildDeps')
this.addTracker('idealTree', tree.name, '')
return this[_buildDepStep]()
@@ -1112,6 +1117,7 @@ This is a one-time fix-up, please be patient...
path: node.realpath,
sourceReference: node,
legacyPeerDeps: this.legacyPeerDeps,
+ overrides: node.overrides,
})
// also need to set up any targets from any link deps, so that
diff --git a/node_modules/@npmcli/arborist/lib/arborist/load-actual.js b/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
index a232bf32b..0d260858d 100644
--- a/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
+++ b/node_modules/@npmcli/arborist/lib/arborist/load-actual.js
@@ -127,6 +127,7 @@ module.exports = cls => class ActualLoader extends cls {
realpath: real,
pkg: {},
global,
+ loadOverrides: true,
})
return this[_loadActualActually]({ root, ignoreMissing, global })
}
@@ -135,8 +136,11 @@ module.exports = cls => class ActualLoader extends cls {
this[_actualTree] = await this[_loadFSNode]({
path: this.path,
real: await realpath(this.path, this[_rpcache], this[_stcache]),
+ loadOverrides: true,
})
+ this[_actualTree].assertRootOverrides()
+
// Note: hidden lockfile will be rejected if it's not the latest thing
// in the folder, or if any of the entries in the hidden lockfile are
// missing.
@@ -236,13 +240,26 @@ module.exports = cls => class ActualLoader extends cls {
this[_actualTree] = root
}
- [_loadFSNode] ({ path, parent, real, root }) {
+ [_loadFSNode] ({ path, parent, real, root, loadOverrides }) {
if (!real) {
return realpath(path, this[_rpcache], this[_stcache])
.then(
- real => this[_loadFSNode]({ path, parent, real, root }),
+ real => this[_loadFSNode]({
+ path,
+ parent,
+ real,
+ root,
+ loadOverrides,
+ }),
// if realpath fails, just provide a dummy error node
- error => new Node({ error, path, realpath: path, parent, root })
+ error => new Node({
+ error,
+ path,
+ realpath: path,
+ parent,
+ root,
+ loadOverrides,
+ })
)
}
@@ -271,6 +288,7 @@ module.exports = cls => class ActualLoader extends cls {
error,
parent,
root,
+ loadOverrides,
})
})
.then(node => {
diff --git a/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js b/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
index 7761380e9..4d65e3da6 100644
--- a/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
+++ b/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js
@@ -72,6 +72,7 @@ module.exports = cls => class VirtualLoader extends cls {
this[rootOptionProvided] = options.root
await this[loadFromShrinkwrap](s, root)
+ root.assertRootOverrides()
return treeCheck(this.virtualTree)
}
diff --git a/node_modules/@npmcli/arborist/lib/edge.js b/node_modules/@npmcli/arborist/lib/edge.js
index 1881001ef..87439e764 100644
--- a/node_modules/@npmcli/arborist/lib/edge.js
+++ b/node_modules/@npmcli/arborist/lib/edge.js
@@ -29,6 +29,7 @@ class ArboristEdge {}
const printableEdge = (edge) => {
const edgeFrom = edge.from && edge.from.location
const edgeTo = edge.to && edge.to.location
+ const override = edge.overrides && edge.overrides.value
return Object.assign(new ArboristEdge(), {
name: edge.name,
@@ -38,12 +39,13 @@ const printableEdge = (edge) => {
...(edgeTo ? { to: edgeTo } : {}),
...(edge.error ? { error: edge.error } : {}),
...(edge.peerConflicted ? { peerConflicted: true } : {}),
+ ...(override ? { overridden: override } : {}),
})
}
class Edge {
constructor (options) {
- const { type, name, spec, accept, from } = options
+ const { type, name, spec, accept, from, overrides } = options
if (typeof spec !== 'string') {
throw new TypeError('must provide string spec')
@@ -55,6 +57,10 @@ class Edge {
this[_spec] = spec
+ if (overrides !== undefined) {
+ this.overrides = overrides
+ }
+
if (accept !== undefined) {
if (typeof accept !== 'string') {
throw new TypeError('accept field must be a string if provided')
@@ -82,8 +88,11 @@ class Edge {
}
satisfiedBy (node) {
- return node.name === this.name &&
- depValid(node, this.spec, this.accept, this.from)
+ if (node.name !== this.name) {
+ return false
+ }
+
+ return depValid(node, this.spec, this.accept, this.from)
}
explain (seen = []) {
@@ -101,6 +110,10 @@ class Edge {
type: this.type,
name: this.name,
spec: this.spec,
+ ...(this.rawSpec !== this.spec ? {
+ rawSpec: this.rawSpec,
+ overridden: true,
+ } : {}),
...(bundled ? { bundled } : {}),
...(error ? { error } : {}),
...(from ? { from: from.explain(null, seen) } : {}),
@@ -143,7 +156,28 @@ class Edge {
return this[_name]
}
+ get rawSpec () {
+ return this[_spec]
+ }
+
get spec () {
+ if (this.overrides && this.overrides.value && this.overrides.name === this.name) {
+ if (this.overrides.value.startsWith('$')) {
+ const ref = this.overrides.value.slice(1)
+ const pkg = this.from.root.package
+ const overrideSpec = (pkg.devDependencies && pkg.devDependencies[ref]) ||
+ (pkg.optionalDependencies && pkg.optionalDependencies[ref]) ||
+ (pkg.dependencies && pkg.dependencies[ref]) ||
+ (pkg.peerDependencies && pkg.peerDependencies[ref])
+
+ if (overrideSpec) {
+ return overrideSpec
+ }
+
+ throw new Error(`Unable to resolve reference ${this.overrides.value}`)
+ }
+ return this.overrides.value
+ }
return this[_spec]
}
@@ -213,6 +247,7 @@ class Edge {
if (node.edgesOut.has(this.name)) {
node.edgesOut.get(this.name).detach()
}
+
node.addEdgeOut(this)
this.reload()
}
diff --git a/node_modules/@npmcli/arborist/lib/node.js b/node_modules/@npmcli/arborist/lib/node.js
index d311b6a83..45c288bcf 100644
--- a/node_modules/@npmcli/arborist/lib/node.js
+++ b/node_modules/@npmcli/arborist/lib/node.js
@@ -32,6 +32,7 @@ const semver = require('semver')
const nameFromFolder = require('@npmcli/name-from-folder')
const Edge = require('./edge.js')
const Inventory = require('./inventory.js')
+const OverrideSet = require('./override-set.js')
const { normalize } = require('read-package-json-fast')
const { getPaths: getBinPaths } = require('bin-links')
const npa = require('npm-package-arg')
@@ -88,6 +89,8 @@ class Node {
legacyPeerDeps = false,
linksIn,
hasShrinkwrap,
+ overrides,
+ loadOverrides = false,
extraneous = true,
dev = true,
optional = true,
@@ -190,6 +193,17 @@ class Node {
// because this.package is read when adding to inventory
this[_package] = pkg && typeof pkg === 'object' ? pkg : {}
+ if (overrides) {
+ this.overrides = overrides
+ } else if (loadOverrides) {
+ const overrides = this[_package].overrides || {}
+ if (Object.keys(overrides).length > 0) {
+ this.overrides = new OverrideSet({
+ overrides: this[_package].overrides,
+ })
+ }
+ }
+
// only relevant for the root and top nodes
this.meta = meta
@@ -963,6 +977,11 @@ class Node {
return false
}
+ // XXX need to check for two root nodes?
+ if (node.overrides !== this.overrides) {
+ return false
+ }
+
ignorePeers = new Set(ignorePeers)
// gather up all the deps of this node and that are only depended
@@ -1208,6 +1227,10 @@ class Node {
this[_changePath](newPath)
}
+ if (parent.overrides) {
+ this.overrides = parent.overrides.getNodeRule(this)
+ }
+
// clobbers anything at that path, resets all appropriate references
this.root = parent.root
}
@@ -1279,11 +1302,33 @@ class Node {
}
}
+ assertRootOverrides () {
+ if (!this.isProjectRoot || !this.overrides) {
+ return
+ }
+
+ for (const edge of this.edgesOut.values()) {
+ // if these differ an override has been applied, those are not allowed
+ // for top level dependencies so throw an error
+ if (edge.spec !== edge.rawSpec && !edge.spec.startsWith('$')) {
+ throw Object.assign(new Error(`Override for ${edge.name}@${edge.rawSpec} conflicts with direct dependency`), { code: 'EOVERRIDE' })
+ }
+ }
+ }
+
addEdgeOut (edge) {
+ if (this.overrides) {
+ edge.overrides = this.overrides.getEdgeRule(edge)
+ }
+
this.edgesOut.set(edge.name, edge)
}
addEdgeIn (edge) {
+ if (edge.overrides) {
+ this.overrides = edge.overrides
+ }
+
this.edgesIn.add(edge)
// try to get metadata from the yarn.lock file
diff --git a/node_modules/@npmcli/arborist/lib/override-set.js b/node_modules/@npmcli/arborist/lib/override-set.js
new file mode 100644
index 000000000..e2e04e03e
--- /dev/null
+++ b/node_modules/@npmcli/arborist/lib/override-set.js
@@ -0,0 +1,123 @@
+const npa = require('npm-package-arg')
+const semver = require('semver')
+
+class OverrideSet {
+ constructor ({ overrides, key, parent }) {
+ this.parent = parent
+ this.children = new Map()
+
+ if (typeof overrides === 'string') {
+ overrides = { '.': overrides }
+ }
+
+ // change a literal empty string to * so we can use truthiness checks on
+ // the value property later
+ if (overrides['.'] === '') {
+ overrides['.'] = '*'
+ }
+
+ if (parent) {
+ const spec = npa(key)
+ if (!spec.name) {
+ throw new Error(`Override without name: ${key}`)
+ }
+
+ this.name = spec.name
+ spec.name = ''
+ this.key = key
+ this.keySpec = spec.rawSpec === '' ? '' : spec.toString()
+ this.value = overrides['.'] || this.keySpec
+ }
+
+ for (const [key, childOverrides] of Object.entries(overrides)) {
+ if (key === '.') {
+ continue
+ }
+
+ const child = new OverrideSet({
+ parent: this,
+ key,
+ overrides: childOverrides,
+ })
+
+ this.children.set(child.key, child)
+ }
+ }
+
+ getEdgeRule (edge) {
+ for (const rule of this.ruleset.values()) {
+ if (rule.name !== edge.name) {
+ continue
+ }
+
+ if (rule.keySpec === '' ||
+ semver.intersects(edge.spec, rule.keySpec)) {
+ return rule
+ }
+ }
+
+ return this
+ }
+
+ getNodeRule (node) {
+ for (const rule of this.ruleset.values()) {
+ if (rule.name !== node.name) {
+ continue
+ }
+
+ if (rule.keySpec === '' ||
+ semver.satisfies(node.version, rule.keySpec) ||
+ semver.satisfies(node.version, rule.value)) {
+ return rule
+ }
+ }
+
+ return this
+ }
+
+ getMatchingRule (node) {
+ for (const rule of this.ruleset.values()) {
+ if (rule.name !== node.name) {
+ continue
+ }
+
+ if (rule.keySpec === '' ||
+ semver.satisfies(node.version, rule.keySpec) ||
+ semver.satisfies(node.version, rule.value)) {
+ return rule
+ }
+ }
+
+ return null
+ }
+
+ * ancestry () {
+ for (let ancestor = this; ancestor; ancestor = ancestor.parent) {
+ yield ancestor
+ }
+ }
+
+ get isRoot () {
+ return !this.parent
+ }
+
+ get ruleset () {
+ const ruleset = new Map()
+
+ for (const override of this.ancestry()) {
+ for (const kid of override.children.values()) {
+ if (!ruleset.has(kid.key)) {
+ ruleset.set(kid.key, kid)
+ }
+ }
+
+ if (!override.isRoot && !ruleset.has(override.key)) {
+ ruleset.set(override.key, override)
+ }
+ }
+
+ return ruleset
+ }
+}
+
+module.exports = OverrideSet
diff --git a/node_modules/@npmcli/arborist/lib/place-dep.js b/node_modules/@npmcli/arborist/lib/place-dep.js
index be735d5fc..c0cbe91fe 100644
--- a/node_modules/@npmcli/arborist/lib/place-dep.js
+++ b/node_modules/@npmcli/arborist/lib/place-dep.js
@@ -295,6 +295,7 @@ class PlaceDep {
integrity: dep.integrity,
legacyPeerDeps: this.legacyPeerDeps,
error: dep.errors[0],
+ ...(dep.overrides ? { overrides: dep.overrides } : {}),
...(dep.isLink ? { target: dep.target, realpath: dep.realpath } : {}),
})
diff --git a/node_modules/@npmcli/arborist/lib/printable.js b/node_modules/@npmcli/arborist/lib/printable.js
index 018e569b1..7c8d52a42 100644
--- a/node_modules/@npmcli/arborist/lib/printable.js
+++ b/node_modules/@npmcli/arborist/lib/printable.js
@@ -1,6 +1,5 @@
// helper function to output a clearer visualization
// of the current node and its descendents
-
const localeCompare = require('@isaacs/string-locale-compare')('en')
const util = require('util')
const relpath = require('./relpath.js')
@@ -65,6 +64,11 @@ class ArboristNode {
this.errors = tree.errors.map(treeError)
}
+ if (tree.overrides) {
+ this.overrides = new Map([...tree.overrides.ruleset.values()]
+ .map((override) => [override.key, override.value]))
+ }
+
// edgesOut sorted by name
if (tree.edgesOut.size) {
this.edgesOut = new Map([...tree.edgesOut.entries()]
@@ -126,7 +130,10 @@ class Edge {
constructor (edge) {
this.type = edge.type
this.name = edge.name
- this.spec = edge.spec || '*'
+ this.spec = edge.rawSpec || '*'
+ if (edge.rawSpec !== edge.spec) {
+ this.override = edge.spec
+ }
if (edge.error) {
this.error = edge.error
}
@@ -145,6 +152,8 @@ class EdgeOut extends Edge {
[util.inspect.custom] () {
return `{ ${this.type} ${this.name}@${this.spec}${
+ this.override ? ` overridden:${this.override}` : ''
+ }${
this.to ? ' -> ' + this.to : ''
}${
this.error ? ' ' + this.error : ''
diff --git a/node_modules/@npmcli/arborist/package.json b/node_modules/@npmcli/arborist/package.json
index 34d38572d..12fede685 100644
--- a/node_modules/@npmcli/arborist/package.json
+++ b/node_modules/@npmcli/arborist/package.json
@@ -1,6 +1,6 @@
{
"name": "@npmcli/arborist",
- "version": "4.0.5",
+ "version": "4.1.0",
"description": "Manage node_modules trees",
"dependencies": {
"@isaacs/string-locale-compare": "^1.1.0",
@@ -37,10 +37,11 @@
"walk-up-path": "^1.0.0"
},
"devDependencies": {
- "@npmcli/template-oss": "^2.3.0",
+ "@npmcli/template-oss": "^2.3.1",
"benchmark": "^2.1.4",
"chalk": "^4.1.0",
"minify-registry-metadata": "^2.1.0",
+ "nock": "^13.2.0",
"tap": "^15.1.2",
"tcompare": "^5.0.6"
},
@@ -93,7 +94,7 @@
"engines": {
"node": "^12.13.0 || ^14.15.0 || >=16"
},
- "templateVersion": "2.3.0",
+ "templateVersion": "2.3.1",
"eslintIgnore": [
"test/fixtures/",
"!test/fixtures/*.js"
diff --git a/package-lock.json b/package-lock.json
index b7fc90a9c..b6df88dfe 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -87,7 +87,7 @@
],
"dependencies": {
"@isaacs/string-locale-compare": "^1.1.0",
- "@npmcli/arborist": "^4.0.5",
+ "@npmcli/arborist": "^4.1.0",
"@npmcli/ci-detect": "^1.4.0",
"@npmcli/config": "^2.3.2",
"@npmcli/map-workspaces": "^2.0.0",
@@ -801,9 +801,9 @@
}
},
"node_modules/@npmcli/arborist": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-4.0.5.tgz",
- "integrity": "sha512-WR2cqxzjsvmHJ9sKCdqBYG/qeiAXB9ev1iq1W2Rry7LxeJ7eDtTr4mOWe/TBvp6xFzevGecQc2YEWwExTuLZLg==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-4.1.0.tgz",
+ "integrity": "sha512-bkaOqCuTUtpVOe1vaAP7TUihu64wIbnSDpsbqBJUsGFTLYXbjKwi6xj8Zx5cfHkM3nqyeEEbPYlGkt0TXjKrUg==",
"inBundle": true,
"dependencies": {
"@isaacs/string-locale-compare": "^1.1.0",
@@ -10664,9 +10664,9 @@
"dev": true
},
"@npmcli/arborist": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-4.0.5.tgz",
- "integrity": "sha512-WR2cqxzjsvmHJ9sKCdqBYG/qeiAXB9ev1iq1W2Rry7LxeJ7eDtTr4mOWe/TBvp6xFzevGecQc2YEWwExTuLZLg==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-4.1.0.tgz",
+ "integrity": "sha512-bkaOqCuTUtpVOe1vaAP7TUihu64wIbnSDpsbqBJUsGFTLYXbjKwi6xj8Zx5cfHkM3nqyeEEbPYlGkt0TXjKrUg==",
"requires": {
"@isaacs/string-locale-compare": "^1.1.0",
"@npmcli/installed-package-contents": "^1.0.7",
diff --git a/package.json b/package.json
index f9ba8cd3c..73199f179 100644
--- a/package.json
+++ b/package.json
@@ -55,7 +55,7 @@
},
"dependencies": {
"@isaacs/string-locale-compare": "^1.1.0",
- "@npmcli/arborist": "^4.0.5",
+ "@npmcli/arborist": "^4.1.0",
"@npmcli/ci-detect": "^1.4.0",
"@npmcli/config": "^2.3.2",
"@npmcli/map-workspaces": "^2.0.0",