diff --git a/workspaces/arborist/lib/edge.js b/workspaces/arborist/lib/edge.js index cc9698ad6cae7..2a8b520509b01 100644 --- a/workspaces/arborist/lib/edge.js +++ b/workspaces/arborist/lib/edge.js @@ -258,7 +258,7 @@ class Edge { const newTo = this.#from.resolve(this.#name) if (newTo !== this.#to) { if (this.#to) { - this.#to.edgesIn.delete(this) + this.#to.deleteEdgeIn(this) } this.#to = newTo this.#error = null @@ -273,7 +273,7 @@ class Edge { detach () { this.#explanation = null if (this.#to) { - this.#to.edgesIn.delete(this) + this.#to.deleteEdgeIn(this) } this.#from.edgesOut.delete(this.#name) this.#to = null diff --git a/workspaces/arborist/lib/node.js b/workspaces/arborist/lib/node.js index bdc021b7c12a9..d6702bffab388 100644 --- a/workspaces/arborist/lib/node.js +++ b/workspaces/arborist/lib/node.js @@ -1344,9 +1344,100 @@ class Node { this.edgesOut.set(edge.name, edge) } - addEdgeIn (edge) { + recalculateOutEdgesOverrides () { + // For each edge out propogate the new overrides through. + for (const [, edge] of this.edgesOut) { + edge.reload(true) + if (edge.to) { + edge.to.updateNodeOverrideSet(edge.overrides) + } + } + } + + findSpecificOverrideSet (first, second) { + for (let overrideSet = second; overrideSet; overrideSet = overrideSet.parent) { + if (overrideSet.isEqual(first)) { + return second + } + } + for (let overrideSet = first; overrideSet; overrideSet = overrideSet.parent) { + if (overrideSet.isEqual(second)) { + return first + } + } + console.log('Conflicting override sets') + } + + updateNodeOverrideSetDueToEdgeRemoval (otherOverrideSet) { + // If this edge's overrides isn't equal to this node's overrides, then removing it won't change newOverrideSet later. + if (!this.overrides || !this.overrides.isEqual(otherOverrideSet)) { + return false + } + let newOverrideSet + for (const edge of this.edgesIn) { + if (newOverrideSet) { + newOverrideSet = this.findSpecificOverrideSet(edge.overrides, newOverrideSet) + } else { + newOverrideSet = edge.overrides + } + } + if (this.overrides.isEqual(newOverrideSet)) { + return false + } + this.overrides = newOverrideSet + if (this.overrides) { + // Optimization: if there's any override set at all, then no non-extraneous node has an empty override set. So if we temporarily have no + // override set (for example, we removed all the edges in), there's no use updating all the edges out right now. Let's just wait until + // we have an actual override set later. + this.recalculateOutEdgesOverrides() + } + return true + } + + // This logic isn't perfect either. When we have two edges in that have different override sets, then we have to decide which set is correct. + // This function assumes the more specific override set is applicable, so if we have dependencies A->B->C and A->C + // and an override set that specifies what happens for C under A->B, this will work even if the new A->C edge comes along and tries to change + // the override set. + // The strictly correct logic is not to allow two edges with different overrides to point to the same node, because even if this node can satisfy + // both, one of its dependencies might need to be different depending on the edge leading to it. + // However, this might cause a lot of duplication, because the conflict in the dependencies might never actually happen. + updateNodeOverrideSet (otherOverrideSet) { + if (!this.overrides) { + // Assuming there are any overrides at all, the overrides field is never undefined for any node at the end state of the tree. + // So if the new edge's overrides is undefined it will be updated later. So we can wait with updating the node's overrides field. + if (!otherOverrideSet) { + return false + } + this.overrides = otherOverrideSet + this.recalculateOutEdgesOverrides() + return true + } + if (this.overrides.isEqual(otherOverrideSet)) { + return false + } + const newOverrideSet = this.findSpecificOverrideSet(this.overrides, otherOverrideSet) + if (newOverrideSet) { + if (!this.overrides.isEqual(newOverrideSet)) { + this.overrides = newOverrideSet + this.recalculateOutEdgesOverrides() + return true + } + return false + } + // This is an error condition. We can only get here if the new override set is in conflict with the existing. + } + + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) if (edge.overrides) { - this.overrides = edge.overrides + this.updateNodeOverrideSetDueToEdgeRemoval(edge.overrides) + } + } + + addEdgeIn (edge) { + // We need to handle the case where the new edge in has an overrides field which is different from the current value. + if (!this.overrides || !this.overrides.isEqual(edge.overrides)) { + this.updateNodeOverrideSet(edge.overrides) } this.edgesIn.add(edge) diff --git a/workspaces/arborist/lib/override-set.js b/workspaces/arborist/lib/override-set.js index bfc5a5d7906ee..a03ed5133aa59 100644 --- a/workspaces/arborist/lib/override-set.js +++ b/workspaces/arborist/lib/override-set.js @@ -44,6 +44,43 @@ class OverrideSet { } } + childrenAreEqual (other) { + if (this.children.size !== other.children.size) { + return false + } + for (const [key] of this.children) { + if (!other.children.has(key)) { + return false + } + if (this.children.get(key).value !== other.children.get(key).value) { + return false + } + if (!this.children.get(key).childrenAreEqual(other.children.get(key))) { + return false + } + } + return true + } + + isEqual (other) { + if (this === other) { + return true + } + if (!other) { + return false + } + if (this.key !== other.key || this.value !== other.value) { + return false + } + if (!this.childrenAreEqual(other)) { + return false + } + if (!this.parent) { + return !other.parent + } + return this.parent.isEqual(other.parent) + } + getEdgeRule (edge) { for (const rule of this.ruleset.values()) { if (rule.name !== edge.name) { diff --git a/workspaces/arborist/tap-snapshots/test/edge.js.test.cjs b/workspaces/arborist/tap-snapshots/test/edge.js.test.cjs index 17dc0b0c9fb0b..7b28779165d56 100644 --- a/workspaces/arborist/tap-snapshots/test/edge.js.test.cjs +++ b/workspaces/arborist/tap-snapshots/test/edge.js.test.cjs @@ -52,6 +52,7 @@ Edge { "from": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "b" => Edge { @@ -69,6 +70,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -91,6 +93,7 @@ Edge { "root": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -122,6 +125,7 @@ Edge { "to": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set { Edge { "peerConflicted": false, @@ -139,6 +143,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -173,6 +178,7 @@ Edge { "from": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "b" => Edge { @@ -190,6 +196,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -212,6 +219,7 @@ Edge { "root": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -243,6 +251,7 @@ Edge { "to": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set { Edge { "peerConflicted": false, @@ -260,6 +269,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -294,6 +304,7 @@ Edge { "from": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -334,6 +345,7 @@ Edge { "from": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "aa" => Edge { @@ -351,6 +363,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "b" => Edge { @@ -368,6 +381,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -390,6 +404,7 @@ Edge { "root": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -424,6 +439,7 @@ Edge { "to": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set { Edge { "peerConflicted": false, @@ -441,6 +457,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "b" => Edge { @@ -458,6 +475,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -480,6 +498,7 @@ Edge { "root": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -516,6 +535,7 @@ Edge { "from": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "aa" => Edge { @@ -533,6 +553,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -576,6 +597,7 @@ Edge { "from": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "aa" => Edge { @@ -593,6 +615,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set { Edge { "peerConflicted": false, @@ -610,6 +633,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -645,6 +669,7 @@ Edge { "to": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set { Edge { "peerConflicted": false, @@ -662,6 +687,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "b" => Edge { @@ -679,6 +705,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -701,6 +728,7 @@ Edge { "root": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -737,6 +765,7 @@ Edge { "from": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "a" => Edge { @@ -766,6 +795,7 @@ Edge { "to": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set { Edge { "peerConflicted": false, @@ -783,6 +813,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "a" => Edge { @@ -805,6 +836,7 @@ Edge { "root": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "a" => Edge { @@ -838,6 +870,7 @@ Edge { "from": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "aa" => Edge { @@ -855,6 +888,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -877,6 +911,7 @@ Edge { "root": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -908,6 +943,7 @@ Edge { "to": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set { Edge { "peerConflicted": false, @@ -925,6 +961,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "aa" => Edge { @@ -942,6 +979,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -964,6 +1002,7 @@ Edge { "root": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -1000,6 +1039,7 @@ Edge { "from": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "b" => Edge { @@ -1017,6 +1057,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -1039,6 +1080,7 @@ Edge { "root": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { @@ -1070,6 +1112,7 @@ Edge { "to": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set { Edge { "peerConflicted": false, @@ -1087,6 +1130,7 @@ Edge { "parent": Object { "addEdgeIn": Function addEdgeIn(edge), "addEdgeOut": Function addEdgeOut(edge), + "deleteEdgeIn": Function deleteEdgeIn(edge), "edgesIn": Set {}, "edgesOut": Map { "missing" => Edge { diff --git a/workspaces/arborist/test/edge.js b/workspaces/arborist/test/edge.js index ab08357ece359..9a2e5791b4de1 100644 --- a/workspaces/arborist/test/edge.js +++ b/workspaces/arborist/test/edge.js @@ -57,6 +57,9 @@ const top = { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } const a = { @@ -81,6 +84,9 @@ const a = { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } const b = { @@ -104,6 +110,9 @@ const b = { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } const bb = { @@ -127,6 +136,9 @@ const bb = { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } const aa = { @@ -150,6 +162,9 @@ const aa = { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } const c = { @@ -173,6 +188,9 @@ const c = { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } t.matchSnapshot(new Edge({ @@ -364,6 +382,9 @@ const referenceTop = { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, overrides: new OverrideSet({ overrides: { referenceGrandchild: '$referenceChild', @@ -403,6 +424,9 @@ const referenceChild = { this.overrides = edge.overrides this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } new Edge({ @@ -442,6 +466,9 @@ const referenceGrandchild = { this.overrides = edge.overrides this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } const referenceGrandchildEdge = new Edge({ @@ -490,6 +517,9 @@ const badOverride = { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, overrides: new OverrideSet({ overrides: { b: '1.x', @@ -775,6 +805,9 @@ const bundleChild = { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } const bundleParent = { @@ -797,6 +830,9 @@ const bundleParent = { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } const bundledEdge = new Edge({ @@ -858,6 +894,9 @@ t.test('override references find the correct root', (t) => { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } const foo = { @@ -885,6 +924,9 @@ t.test('override references find the correct root', (t) => { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } foo.overrides = overrides.getNodeRule(foo) @@ -915,6 +957,9 @@ t.test('override references find the correct root', (t) => { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } bar.overrides = foo.overrides.getNodeRule(bar) @@ -946,6 +991,9 @@ t.test('override references find the correct root', (t) => { addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } virtualBar.overrides = overrides @@ -999,6 +1047,9 @@ t.test('shrinkwrapped and bundled deps are not overridden and remain valid', (t) addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } const foo = { @@ -1029,6 +1080,9 @@ t.test('shrinkwrapped and bundled deps are not overridden and remain valid', (t) addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } foo.overrides = overrides.getNodeRule(foo) @@ -1058,6 +1112,9 @@ t.test('shrinkwrapped and bundled deps are not overridden and remain valid', (t) addEdgeIn (edge) { this.edgesIn.add(edge) }, + deleteEdgeIn (edge) { + this.edgesIn.delete(edge) + }, } bar.overrides = foo.overrides.getNodeRule(bar) @@ -1072,3 +1129,69 @@ t.test('shrinkwrapped and bundled deps are not overridden and remain valid', (t) t.ok(edge.valid, 'edge is valid') t.end() }) + +t.test('overrideset comparison logic', (t) => { + const overrides1 = new OverrideSet({ + overrides: { + bar: '^2.0.0', + }, + }) + + const overrides2 = new OverrideSet({ + overrides: { + bar: '^2.0.0', + }, + }) + + const overrides3 = new OverrideSet({ + overrides: { + foo: '^2.0.0', + }, + }) + + const overrides4 = new OverrideSet({ + overrides: { + foo: '^1.0.0', + }, + }) + + const overrides5 = new OverrideSet({ + overrides: { + bar: '^2.0.0', + foo: '^2.0.0', + }, + }) + + const overrides6 = new OverrideSet({ + overrides: { + }, + }) + + const overrides7 = new OverrideSet({ + overrides: { + bar: { + '.': '^2.0.0', + baz: '1.2.3', + }, + }, + }) + + t.ok(overrides1.isEqual(overrides1), 'overridesets are equal') + t.ok(overrides1.isEqual(overrides2), 'overridesets are equal') + t.ok(!overrides1.isEqual(overrides3), 'overridesets are different') + t.ok(!overrides1.isEqual(overrides5), 'overridesets are different') + t.ok(!overrides1.isEqual(overrides6), 'overridesets are different') + t.ok(!overrides1.isEqual(overrides7), 'overridesets are different') + t.ok(!overrides3.isEqual(overrides1), 'overridesets are different') + t.ok(!overrides3.isEqual(overrides4), 'overridesets are different') + t.ok(!overrides3.isEqual(overrides5), 'overridesets are different') + t.ok(!overrides4.isEqual(overrides5), 'overridesets are different') + t.ok(!overrides5.isEqual(overrides1), 'overridesets are different') + t.ok(!overrides5.isEqual(overrides3), 'overridesets are different') + t.ok(!overrides5.isEqual(overrides6), 'overridesets are different') + t.ok(!overrides6.isEqual(overrides1), 'overridesets are different') + t.ok(!overrides6.isEqual(overrides3), 'overridesets are different') + t.ok(overrides6.isEqual(overrides6), 'overridesets are equal') + t.ok(!overrides7.isEqual(overrides1), 'overridesets are different') + t.end() +})