Skip to content

Commit 4d676e3

Browse files
nlffritzy
authored andcommitted
fix(arborist): when reloading an edge, also refresh overrides
this fixes some scenarios where overrides were not being properly applied, especially those where a node_modules or package-lock.json already exists
1 parent 0c76487 commit 4d676e3

File tree

4 files changed

+101
-25
lines changed

4 files changed

+101
-25
lines changed

workspaces/arborist/lib/edge.js

+5
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,11 @@ class Edge {
215215

216216
reload (hard = false) {
217217
this[_explanation] = null
218+
if (this[_from].overrides) {
219+
this.overrides = this[_from].overrides.getEdgeRule(this)
220+
} else {
221+
delete this.overrides
222+
}
218223
const newTo = this[_from].resolve(this.name)
219224
if (newTo !== this[_to]) {
220225
if (this[_to]) {

workspaces/arborist/lib/node.js

+3
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,9 @@ class Node {
792792
target.root = root
793793
}
794794

795+
if (!this.overrides && this.parent && this.parent.overrides) {
796+
this.overrides = this.parent.overrides.getNodeRule(this)
797+
}
795798
// tree should always be valid upon root setter completion.
796799
treeCheck(this)
797800
treeCheck(root)

workspaces/arborist/test/edge.js

+37-25
Original file line numberDiff line numberDiff line change
@@ -244,16 +244,19 @@ t.not(new Edge({
244244
}).satisfiedBy(b), 'b does not satisfy edge for c')
245245
reset(a)
246246

247+
const overrideSet = new OverrideSet({
248+
overrides: {
249+
c: '2.x',
250+
},
251+
})
252+
253+
a.overrides = overrideSet
247254
t.matchSnapshot(new Edge({
248255
from: a,
249256
type: 'prod',
250257
name: 'c',
251258
spec: '1.x',
252-
overrides: new OverrideSet({
253-
overrides: {
254-
c: '2.x',
255-
},
256-
}).getEdgeRule({ name: 'c', spec: '1.x' }),
259+
overrides: overrideSet.getEdgeRule({ name: 'c', spec: '1.x' }),
257260
}).toJSON(), 'printableEdge shows overrides')
258261
reset(a)
259262

@@ -262,11 +265,7 @@ const overriddenExplanation = new Edge({
262265
type: 'prod',
263266
name: 'c',
264267
spec: '1.x',
265-
overrides: new OverrideSet({
266-
overrides: {
267-
c: '2.x',
268-
},
269-
}).getEdgeRule({ name: 'c', spec: '1.x' }),
268+
overrides: overrideSet.getEdgeRule({ name: 'c', spec: '1.x' }),
270269
}).explain()
271270
t.equal(overriddenExplanation.rawSpec, '1.x', 'rawSpec has original spec')
272271
t.equal(overriddenExplanation.spec, '2.x', 'spec has override spec')
@@ -278,38 +277,49 @@ t.ok(new Edge({
278277
type: 'prod',
279278
name: 'c',
280279
spec: '1.x',
281-
overrides: new OverrideSet({
282-
overrides: {
283-
c: '2.x',
284-
},
285-
}).getEdgeRule({ name: 'c', spec: '1.x' }),
280+
overrides: overrideSet.getEdgeRule({ name: 'c', spec: '1.x' }),
286281
}).satisfiedBy(c), 'c@2 satisfies spec:1.x, override:2.x')
287282
reset(a)
288283

284+
const overrideSetB = new OverrideSet({
285+
overrides: {
286+
b: '1.x',
287+
},
288+
})
289+
a.overrides = overrideSetB
289290
t.matchSnapshot(new Edge({
290291
from: a,
291292
type: 'prod',
292293
name: 'c',
293294
spec: '2.x',
294-
overrides: new OverrideSet({
295-
overrides: {
296-
b: '1.x',
297-
},
298-
}).getEdgeRule({ name: 'c', spec: '2.x' }),
295+
overrides: overrideSetB.getEdgeRule({ name: 'c', spec: '2.x' }),
299296
}).toJSON(), 'printableEdge does not show non-applicable override')
300297

301298
t.ok(new Edge({
302299
from: a,
303300
type: 'prod',
304301
name: 'c',
305302
spec: '2.x',
306-
overrides: new OverrideSet({
307-
overrides: {
308-
b: '1.x',
309-
},
310-
}).getEdgeRule({ name: 'c', spec: '2.x' }),
303+
overrides: overrideSetB.getEdgeRule({ name: 'c', spec: '2.x' }),
311304
}).satisfiedBy(c), 'c@2 satisfies spec:1.x, no matching override')
312305
reset(a)
306+
delete a.overrides
307+
308+
const overrideEdge = new Edge({
309+
from: a,
310+
type: 'prod',
311+
name: 'c',
312+
spec: '2.x',
313+
})
314+
t.notOk(overrideEdge.overrides, 'edge has no overrides')
315+
a.overrides = new OverrideSet({ overrides: { b: '1.x' } })
316+
t.notOk(overrideEdge.overrides, 'edge has no overrides')
317+
overrideEdge.reload()
318+
t.ok(overrideEdge.overrides, 'edge has overrides after reload')
319+
delete a.overrides
320+
overrideEdge.reload()
321+
t.notOk(overrideEdge.overrides, 'edge has no overrides after reload')
322+
reset(a)
313323

314324
const referenceTop = {
315325
name: 'referenceTop',
@@ -494,6 +504,7 @@ const overrides = new OverrideSet({
494504
c: '1.x',
495505
},
496506
})
507+
a.overrides = overrides
497508
const overriddenEdge = new Edge({
498509
from: a,
499510
type: 'prod',
@@ -504,6 +515,7 @@ const overriddenEdge = new Edge({
504515
t.equal(overriddenEdge.spec, '1.x', 'override spec takes priority')
505516
t.equal(overriddenEdge.rawSpec, '2.x', 'rawSpec holds original spec')
506517
reset(a)
518+
delete a.overrides
507519

508520
const old = new Edge({
509521
from: a,

workspaces/arborist/test/node.js

+56
Original file line numberDiff line numberDiff line change
@@ -2781,6 +2781,62 @@ t.test('overrides', (t) => {
27812781
t.end()
27822782
})
27832783

2784+
t.test('setting root replaces overrides', async (t) => {
2785+
const root = new Node({
2786+
path: '/some/path',
2787+
loadOverrides: true,
2788+
pkg: {
2789+
name: 'root',
2790+
version: '1.0.0',
2791+
dependencies: {
2792+
foo: '^1.0.0',
2793+
},
2794+
overrides: {
2795+
bar: '^2.0.0',
2796+
},
2797+
},
2798+
})
2799+
2800+
const foo = new Node({
2801+
path: '/some/path/node_modules/foo',
2802+
pkg: {
2803+
name: 'foo',
2804+
version: '1.0.0',
2805+
dependencies: {
2806+
bar: '^1.0.0',
2807+
},
2808+
},
2809+
})
2810+
2811+
const bar = new Node({
2812+
path: '/some/path/node_modules/bar',
2813+
pkg: {
2814+
name: 'bar',
2815+
version: '2.0.0',
2816+
},
2817+
})
2818+
2819+
t.ok(root.overrides, 'root has overrides')
2820+
t.notOk(foo.overrides, 'foo does not have overrides')
2821+
t.notOk(bar.overrides, 'bar does not have overrides')
2822+
t.notOk(root.edgesOut.get('foo').valid, 'foo edge is not valid')
2823+
t.notOk(foo.edgesOut.get('bar').valid, 'bar edge is not valid')
2824+
2825+
// we add bar to the root first, this is deliberate so that we don't have a simple
2826+
// linear inheritance. we'll add foo later and make sure that both edges and nodes
2827+
// become valid after that
2828+
2829+
bar.root = root
2830+
t.ok(bar.overrides, 'bar now has overrides')
2831+
t.notOk(foo.edgesOut.get('bar').valid, 'bar edge is not valid yet')
2832+
2833+
foo.root = root
2834+
t.ok(foo.overrides, 'foo now has overrides')
2835+
t.ok(root.edgesOut.get('foo').valid, 'foo edge is now valid')
2836+
t.ok(bar.overrides, 'bar still has overrides')
2837+
t.ok(foo.edgesOut.get('bar').valid, 'bar edge is now valid')
2838+
})
2839+
27842840
t.test('canReplaceWith requires the same overrides', async (t) => {
27852841
const original = new Node({
27862842
loadOverrides: true,

0 commit comments

Comments
 (0)