From 865070cff95a7de2d566428e3197601ee3a40ad6 Mon Sep 17 00:00:00 2001 From: Alon Navon Date: Thu, 23 Nov 2023 22:13:41 +0200 Subject: [PATCH 01/10] Settle overrides conflicts between edges, and propagate changes to the edges out --- workspaces/arborist/lib/edge.js | 4 +- workspaces/arborist/lib/node.js | 90 ++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 4 deletions(-) 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..975bcbad60861 100644 --- a/workspaces/arborist/lib/node.js +++ b/workspaces/arborist/lib/node.js @@ -1344,9 +1344,95 @@ class Node { this.edgesOut.set(edge.name, edge) } - addEdgeIn (edge) { + recalculateOutEdgesOverrides () { + // For each edge out propogate the new overrides through. + for (const edgePair of this.edgesOut) { + const edge = edgePair[1] + edge.reload(true) + if (edge.to) { + edge.to.updateNodeOverrideSet(edge.overrides) + } + } + } + + findSpecificOverrideSet (first, second) { + for (let overrideSet = second; overrideSet; overrideSet = overrideSet.parent) { + if (overrideSet == first) { + return second + } + } + for (let overrideSet = first; overrideSet; overrideSet = overrideSet.parent) { + if (overrideSet == second) { + return first + } + } + return undefined + } + + 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 != otherOverrideSet) { + return false + } + let newOverrideSet + for (const edge of this.edgesIn) { + if (newOverrideSet) { + newOverrideSet = this.findSpecificOverrideSet() + } else { + newOverrideSet = edge.overrides + } + } + if (this.overrides == newOverrideSet) { + return false + } + this.overrides = newOverrideSet + 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 == otherOverrideSet) { + return false + } + if (!this.overrides) { + this.overrides = otherOverrideSet + this.recalculateOutEdgesOverrides() + return true + } + let newOverrideSet = this.findSpecificOverrideSet(this.overrides, otherOverrideSet) + if (!newOverrideSet) { + // There are conflicting relevant override sets here. We should keep the remaining override set and mark the incoming edge as invalid somehow. + console.log("Overrides are in conflict.") + } else { + if (this.overrides != newOverrideSet) { + this.overrides = newOverrideSet + this.recalculateOutEdgesOverrides() + return true + } + return false + } + } + + 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. + // 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 (edge.overrides && this.overrides != edge.overrides) { + this.updateNodeOverrideSet(edge.overrides) } this.edgesIn.add(edge) From cd2019675427dd8d8cb5ffac1033447d014d141b Mon Sep 17 00:00:00 2001 From: Alon Navon Date: Sun, 26 Nov 2023 14:25:46 +0200 Subject: [PATCH 02/10] cleanup --- workspaces/arborist/lib/node.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/workspaces/arborist/lib/node.js b/workspaces/arborist/lib/node.js index 975bcbad60861..cffd9ed91b379 100644 --- a/workspaces/arborist/lib/node.js +++ b/workspaces/arborist/lib/node.js @@ -1346,8 +1346,7 @@ class Node { recalculateOutEdgesOverrides () { // For each edge out propogate the new overrides through. - for (const edgePair of this.edgesOut) { - const edge = edgePair[1] + for (const [, edge] of this.edgesOut) { edge.reload(true) if (edge.to) { edge.to.updateNodeOverrideSet(edge.overrides) @@ -1366,7 +1365,6 @@ class Node { return first } } - return undefined } updateNodeOverrideSetDueToEdgeRemoval (otherOverrideSet) { @@ -1409,7 +1407,7 @@ class Node { let newOverrideSet = this.findSpecificOverrideSet(this.overrides, otherOverrideSet) if (!newOverrideSet) { // There are conflicting relevant override sets here. We should keep the remaining override set and mark the incoming edge as invalid somehow. - console.log("Overrides are in conflict.") + throw Object.assign(new Error(`Two conflicting override sets for ${this.name}`), { code: 'EOVERRIDE' }) } else { if (this.overrides != newOverrideSet) { this.overrides = newOverrideSet From 0cad4e093ed917dada991eee21c02ae7809bc22b Mon Sep 17 00:00:00 2001 From: Alon Navon Date: Sun, 26 Nov 2023 15:35:55 +0200 Subject: [PATCH 03/10] Optimization --- workspaces/arborist/lib/node.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/workspaces/arborist/lib/node.js b/workspaces/arborist/lib/node.js index cffd9ed91b379..148a0f8aa8c91 100644 --- a/workspaces/arborist/lib/node.js +++ b/workspaces/arborist/lib/node.js @@ -1365,6 +1365,7 @@ class Node { return first } } + console.log("Conflicting override sets") } updateNodeOverrideSetDueToEdgeRemoval (otherOverrideSet) { @@ -1375,7 +1376,7 @@ class Node { let newOverrideSet for (const edge of this.edgesIn) { if (newOverrideSet) { - newOverrideSet = this.findSpecificOverrideSet() + newOverrideSet = this.findSpecificOverrideSet(edge.overrides, newOverrideSet) } else { newOverrideSet = edge.overrides } @@ -1384,7 +1385,12 @@ class Node { return false } this.overrides = newOverrideSet - this.recalculateOutEdgesOverrides() + 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 } @@ -1406,8 +1412,8 @@ class Node { } let newOverrideSet = this.findSpecificOverrideSet(this.overrides, otherOverrideSet) if (!newOverrideSet) { - // There are conflicting relevant override sets here. We should keep the remaining override set and mark the incoming edge as invalid somehow. - throw Object.assign(new Error(`Two conflicting override sets for ${this.name}`), { code: 'EOVERRIDE' }) + // This is an error condition. We can only get here if the new override set is in conflict with the existing. + return false } else { if (this.overrides != newOverrideSet) { this.overrides = newOverrideSet From 6b276f3292ce0731e46e5af1b5d9eda3ed424edb Mon Sep 17 00:00:00 2001 From: Alon Navon Date: Tue, 28 Nov 2023 19:34:12 +0200 Subject: [PATCH 04/10] Fix override sets comparisons --- workspaces/arborist/lib/node.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/workspaces/arborist/lib/node.js b/workspaces/arborist/lib/node.js index 148a0f8aa8c91..54895fead4637 100644 --- a/workspaces/arborist/lib/node.js +++ b/workspaces/arborist/lib/node.js @@ -1356,12 +1356,12 @@ class Node { findSpecificOverrideSet (first, second) { for (let overrideSet = second; overrideSet; overrideSet = overrideSet.parent) { - if (overrideSet == first) { + if (overrideSet.isEqual(first)) { return second } } for (let overrideSet = first; overrideSet; overrideSet = overrideSet.parent) { - if (overrideSet == second) { + if (overrideSet.isEqual(second)) { return first } } @@ -1370,7 +1370,7 @@ class Node { 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 != otherOverrideSet) { + if (!this.overrides.isEqual(otherOverrideSet)) { return false } let newOverrideSet @@ -1381,7 +1381,7 @@ class Node { newOverrideSet = edge.overrides } } - if (this.overrides == newOverrideSet) { + if (this.overrides.isEqual(newOverrideSet)) { return false } this.overrides = newOverrideSet @@ -1402,7 +1402,7 @@ class Node { // 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 == otherOverrideSet) { + if (this.overrides.isEqual(otherOverrideSet)) { return false } if (!this.overrides) { @@ -1415,7 +1415,7 @@ class Node { // This is an error condition. We can only get here if the new override set is in conflict with the existing. return false } else { - if (this.overrides != newOverrideSet) { + if (!this.overrides.isEqual(newOverrideSet)) { this.overrides = newOverrideSet this.recalculateOutEdgesOverrides() return true @@ -1435,7 +1435,7 @@ class Node { // We need to handle the case where the new edge in has an overrides field which is different from the current value. // 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 (edge.overrides && this.overrides != edge.overrides) { + if (edge.overrides && !this.overrides.isEqual(edge.overrides)) { this.updateNodeOverrideSet(edge.overrides) } From fff30728d47a845647cb8541187e9ed41d1cbb4a Mon Sep 17 00:00:00 2001 From: Alon Navon Date: Tue, 28 Nov 2023 19:35:29 +0200 Subject: [PATCH 05/10] Add comparator --- workspaces/arborist/lib/override-set.js | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/workspaces/arborist/lib/override-set.js b/workspaces/arborist/lib/override-set.js index bfc5a5d7906ee..b9f9b95293c8e 100644 --- a/workspaces/arborist/lib/override-set.js +++ b/workspaces/arborist/lib/override-set.js @@ -44,6 +44,34 @@ 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[key].value === other.children[key].value) { + return false + } + if (!this.children[key].childrenAreEqual(other.children[key])) { + return false + } + } + return true + } + + isEqual (other) { + if (this === other) { + return true + } + if (this.key !== other.key || this.value !== other.value || !this.childrenAreEqual(other) || !this.parent.isEqual(other.parent)) { + return false + } + return true + } + getEdgeRule (edge) { for (const rule of this.ruleset.values()) { if (rule.name !== edge.name) { From e97176ea3b0ee9bbaacf05c549706005b0289f96 Mon Sep 17 00:00:00 2001 From: Alon Navon Date: Tue, 28 Nov 2023 19:45:18 +0200 Subject: [PATCH 06/10] Check for undefined --- workspaces/arborist/lib/node.js | 13 ++++++++----- workspaces/arborist/lib/override-set.js | 3 +++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/workspaces/arborist/lib/node.js b/workspaces/arborist/lib/node.js index 54895fead4637..e5cdf2044ea4a 100644 --- a/workspaces/arborist/lib/node.js +++ b/workspaces/arborist/lib/node.js @@ -1370,7 +1370,7 @@ class Node { 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.isEqual(otherOverrideSet)) { + if (!this.overrides || !this.overrides.isEqual(otherOverrideSet)) { return false } let newOverrideSet @@ -1402,13 +1402,16 @@ class Node { // 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.isEqual(otherOverrideSet)) { - return false - } if (!this.overrides) { + if (!otherOverrideSet) { + return false + } this.overrides = otherOverrideSet this.recalculateOutEdgesOverrides() - return true + return true + } + if (this.overrides.isEqual(otherOverrideSet)) { + return false } let newOverrideSet = this.findSpecificOverrideSet(this.overrides, otherOverrideSet) if (!newOverrideSet) { diff --git a/workspaces/arborist/lib/override-set.js b/workspaces/arborist/lib/override-set.js index b9f9b95293c8e..c6069db9b46e0 100644 --- a/workspaces/arborist/lib/override-set.js +++ b/workspaces/arborist/lib/override-set.js @@ -66,6 +66,9 @@ class OverrideSet { if (this === other) { return true } + if (!other) { + return false + } if (this.key !== other.key || this.value !== other.value || !this.childrenAreEqual(other) || !this.parent.isEqual(other.parent)) { return false } From 19155ed020f5c93a13a29ee4704709b65589cfc9 Mon Sep 17 00:00:00 2001 From: Alon Navon Date: Tue, 28 Nov 2023 19:49:40 +0200 Subject: [PATCH 07/10] Another place --- workspaces/arborist/lib/node.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspaces/arborist/lib/node.js b/workspaces/arborist/lib/node.js index e5cdf2044ea4a..967a244b14c56 100644 --- a/workspaces/arborist/lib/node.js +++ b/workspaces/arborist/lib/node.js @@ -1438,7 +1438,7 @@ class Node { // We need to handle the case where the new edge in has an overrides field which is different from the current value. // 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 (edge.overrides && !this.overrides.isEqual(edge.overrides)) { + if (edge.overrides && (!this.overrides || !this.overrides.isEqual(edge.overrides))) { this.updateNodeOverrideSet(edge.overrides) } From dedbccf213d44cca4bab0378651aeede16d7e49d Mon Sep 17 00:00:00 2001 From: Alon Navon Date: Tue, 28 Nov 2023 20:13:09 +0200 Subject: [PATCH 08/10] Fix --- workspaces/arborist/lib/override-set.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/workspaces/arborist/lib/override-set.js b/workspaces/arborist/lib/override-set.js index c6069db9b46e0..dcb928b60b216 100644 --- a/workspaces/arborist/lib/override-set.js +++ b/workspaces/arborist/lib/override-set.js @@ -52,10 +52,10 @@ class OverrideSet { if (!other.children.has(key)) { return false } - if (!this.children[key].value === other.children[key].value) { + if (!this.children.get(key).value === other.children.get(key).value) { return false } - if (!this.children[key].childrenAreEqual(other.children[key])) { + if (!this.children.get(key).childrenAreEqual(other.children.get(key))) { return false } } @@ -69,10 +69,16 @@ class OverrideSet { if (!other) { return false } - if (this.key !== other.key || this.value !== other.value || !this.childrenAreEqual(other) || !this.parent.isEqual(other.parent)) { + if (this.key !== other.key || this.value !== other.value) { return false } - return true + if (!this.childrenAreEqual(other)) { + return false + } + if (!this.parent) { + return !other.parent + } + return this.parent.isEqual(other.parent) } getEdgeRule (edge) { From 4a837861b0fd29b27502cfee2cf9dd72148e71c4 Mon Sep 17 00:00:00 2001 From: Alon Navon Date: Wed, 6 Dec 2023 15:48:51 +0200 Subject: [PATCH 09/10] Lint fixes --- workspaces/arborist/lib/node.js | 8 ++++---- workspaces/arborist/lib/override-set.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/workspaces/arborist/lib/node.js b/workspaces/arborist/lib/node.js index 967a244b14c56..0533c852a67da 100644 --- a/workspaces/arborist/lib/node.js +++ b/workspaces/arborist/lib/node.js @@ -1365,7 +1365,7 @@ class Node { return first } } - console.log("Conflicting override sets") + console.log('Conflicting override sets') } updateNodeOverrideSetDueToEdgeRemoval (otherOverrideSet) { @@ -1408,12 +1408,12 @@ class Node { } this.overrides = otherOverrideSet this.recalculateOutEdgesOverrides() - return true + return true } if (this.overrides.isEqual(otherOverrideSet)) { return false } - let newOverrideSet = this.findSpecificOverrideSet(this.overrides, otherOverrideSet) + const newOverrideSet = this.findSpecificOverrideSet(this.overrides, otherOverrideSet) if (!newOverrideSet) { // This is an error condition. We can only get here if the new override set is in conflict with the existing. return false @@ -1426,7 +1426,7 @@ class Node { return false } } - + deleteEdgeIn (edge) { this.edgesIn.delete(edge) if (edge.overrides) { diff --git a/workspaces/arborist/lib/override-set.js b/workspaces/arborist/lib/override-set.js index dcb928b60b216..988a65d9e6bf8 100644 --- a/workspaces/arborist/lib/override-set.js +++ b/workspaces/arborist/lib/override-set.js @@ -48,7 +48,7 @@ class OverrideSet { if (this.children.size !== other.children.size) { return false } - for (const [key, ] of this.children) { + for (const [key,] of this.children) { if (!other.children.has(key)) { return false } From 7ee2f2e668bd327ba39fcc61bf90ba07f7dae9cf Mon Sep 17 00:00:00 2001 From: Alon Navon Date: Wed, 6 Dec 2023 19:21:28 +0200 Subject: [PATCH 10/10] Added tests --- workspaces/arborist/lib/node.js | 12 +- workspaces/arborist/lib/override-set.js | 4 +- .../tap-snapshots/test/edge.js.test.cjs | 44 +++++++ workspaces/arborist/test/edge.js | 123 ++++++++++++++++++ 4 files changed, 174 insertions(+), 9 deletions(-) diff --git a/workspaces/arborist/lib/node.js b/workspaces/arborist/lib/node.js index 0533c852a67da..d6702bffab388 100644 --- a/workspaces/arborist/lib/node.js +++ b/workspaces/arborist/lib/node.js @@ -1403,6 +1403,8 @@ class Node { // 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 } @@ -1414,10 +1416,7 @@ class Node { return false } const newOverrideSet = this.findSpecificOverrideSet(this.overrides, otherOverrideSet) - if (!newOverrideSet) { - // This is an error condition. We can only get here if the new override set is in conflict with the existing. - return false - } else { + if (newOverrideSet) { if (!this.overrides.isEqual(newOverrideSet)) { this.overrides = newOverrideSet this.recalculateOutEdgesOverrides() @@ -1425,6 +1424,7 @@ class Node { } 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) { @@ -1436,9 +1436,7 @@ class Node { addEdgeIn (edge) { // We need to handle the case where the new edge in has an overrides field which is different from the current value. - // 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 (edge.overrides && (!this.overrides || !this.overrides.isEqual(edge.overrides))) { + if (!this.overrides || !this.overrides.isEqual(edge.overrides)) { this.updateNodeOverrideSet(edge.overrides) } diff --git a/workspaces/arborist/lib/override-set.js b/workspaces/arborist/lib/override-set.js index 988a65d9e6bf8..a03ed5133aa59 100644 --- a/workspaces/arborist/lib/override-set.js +++ b/workspaces/arborist/lib/override-set.js @@ -48,11 +48,11 @@ class OverrideSet { if (this.children.size !== other.children.size) { return false } - for (const [key,] of this.children) { + for (const [key] of this.children) { if (!other.children.has(key)) { return false } - if (!this.children.get(key).value === other.children.get(key).value) { + if (this.children.get(key).value !== other.children.get(key).value) { return false } if (!this.children.get(key).childrenAreEqual(other.children.get(key))) { 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() +})