Skip to content

Commit 940723d

Browse files
authored
fix: intersects with v0.0.0 and v0.0.0-0 (#538)
1 parent aa516b5 commit 940723d

File tree

5 files changed

+74
-56
lines changed

5 files changed

+74
-56
lines changed

classes/comparator.js

+37-26
Original file line numberDiff line numberDiff line change
@@ -90,32 +90,43 @@ class Comparator {
9090
return new Range(this.value, options).test(comp.semver)
9191
}
9292

93-
const sameDirectionIncreasing =
94-
(this.operator === '>=' || this.operator === '>') &&
95-
(comp.operator === '>=' || comp.operator === '>')
96-
const sameDirectionDecreasing =
97-
(this.operator === '<=' || this.operator === '<') &&
98-
(comp.operator === '<=' || comp.operator === '<')
99-
const sameSemVer = this.semver.version === comp.semver.version
100-
const differentDirectionsInclusive =
101-
(this.operator === '>=' || this.operator === '<=') &&
102-
(comp.operator === '>=' || comp.operator === '<=')
103-
const oppositeDirectionsLessThan =
104-
cmp(this.semver, '<', comp.semver, options) &&
105-
(this.operator === '>=' || this.operator === '>') &&
106-
(comp.operator === '<=' || comp.operator === '<')
107-
const oppositeDirectionsGreaterThan =
108-
cmp(this.semver, '>', comp.semver, options) &&
109-
(this.operator === '<=' || this.operator === '<') &&
110-
(comp.operator === '>=' || comp.operator === '>')
111-
112-
return (
113-
sameDirectionIncreasing ||
114-
sameDirectionDecreasing ||
115-
(sameSemVer && differentDirectionsInclusive) ||
116-
oppositeDirectionsLessThan ||
117-
oppositeDirectionsGreaterThan
118-
)
93+
options = parseOptions(options)
94+
95+
// Special cases where nothing can possibly be lower
96+
if (options.includePrerelease &&
97+
(this.value === '<0.0.0-0' || comp.value === '<0.0.0-0')) {
98+
return false
99+
}
100+
if (!options.includePrerelease &&
101+
(this.value.startsWith('<0.0.0') || comp.value.startsWith('<0.0.0'))) {
102+
return false
103+
}
104+
105+
// Same direction increasing (> or >=)
106+
if (this.operator.startsWith('>') && comp.operator.startsWith('>')) {
107+
return true
108+
}
109+
// Same direction decreasing (< or <=)
110+
if (this.operator.startsWith('<') && comp.operator.startsWith('<')) {
111+
return true
112+
}
113+
// same SemVer and both sides are inclusive (<= or >=)
114+
if (
115+
(this.semver.version === comp.semver.version) &&
116+
this.operator.includes('=') && comp.operator.includes('=')) {
117+
return true
118+
}
119+
// opposite directions less than
120+
if (cmp(this.semver, '<', comp.semver, options) &&
121+
this.operator.startsWith('>') && comp.operator.startsWith('<')) {
122+
return true
123+
}
124+
// opposite directions greater than
125+
if (cmp(this.semver, '>', comp.semver, options) &&
126+
this.operator.startsWith('<') && comp.operator.startsWith('>')) {
127+
return true
128+
}
129+
return false
119130
}
120131
}
121132

ranges/intersects.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ const Range = require('../classes/range')
22
const intersects = (r1, r2, options) => {
33
r1 = new Range(r1, options)
44
r2 = new Range(r2, options)
5-
return r1.intersects(r2)
5+
return r1.intersects(r2, options)
66
}
77
module.exports = intersects

test/classes/comparator.js

+12-11
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,18 @@ test('tostrings', (t) => {
2222

2323
test('intersect comparators', (t) => {
2424
t.plan(comparatorIntersection.length)
25-
comparatorIntersection.forEach(([c0, c1, expect]) => t.test(`${c0} ${c1} ${expect}`, t => {
26-
const comp0 = new Comparator(c0)
27-
const comp1 = new Comparator(c1)
28-
29-
t.equal(comp0.intersects(comp1, false), expect,
30-
`${c0} intersects ${c1}`)
31-
32-
t.equal(comp1.intersects(comp0, { loose: false }), expect,
33-
`${c1} intersects ${c0}`)
34-
t.end()
35-
}))
25+
comparatorIntersection.forEach(([c0, c1, expect, includePrerelease]) =>
26+
t.test(`${c0} ${c1} ${expect}`, t => {
27+
const comp0 = new Comparator(c0)
28+
const comp1 = new Comparator(c1)
29+
30+
t.equal(comp0.intersects(comp1, { includePrerelease }), expect,
31+
`${c0} intersects ${c1}`)
32+
33+
t.equal(comp1.intersects(comp0, { includePrerelease }), expect,
34+
`${c1} intersects ${c0}`)
35+
t.end()
36+
}))
3637
})
3738

3839
test('intersect demands another comparator', t => {

test/fixtures/comparator-intersection.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// c0, c1, expected intersection
1+
// c0, c1, expected intersection, includePrerelease
22
module.exports = [
33
// One is a Version
44
['1.3.0', '>=1.3.0', true],
@@ -33,4 +33,10 @@ module.exports = [
3333
['', '', true],
3434
['', '>1.0.0', true],
3535
['<=2.0.0', '', true],
36+
['<0.0.0', '<0.1.0', false],
37+
['<0.1.0', '<0.0.0', false],
38+
['<0.0.0-0', '<0.1.0', false],
39+
['<0.1.0', '<0.0.0-0', false],
40+
['<0.0.0-0', '<0.1.0', false, true],
41+
['<0.1.0', '<0.0.0-0', false, true],
3642
]

test/ranges/intersects.js

+17-17
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,24 @@ const rangeIntersection = require('../fixtures/range-intersection.js')
77

88
test('intersect comparators', t => {
99
t.plan(comparatorIntersection.length)
10-
comparatorIntersection.forEach(([c0, c1, expect]) => t.test(`${c0} ${c1} ${expect}`, t => {
11-
const comp0 = new Comparator(c0)
12-
const comp1 = new Comparator(c1)
10+
comparatorIntersection.forEach(([c0, c1, expect, includePrerelease]) =>
11+
t.test(`${c0} ${c1} ${expect}`, t => {
12+
const opts = { loose: false, includePrerelease }
13+
const comp0 = new Comparator(c0)
14+
const comp1 = new Comparator(c1)
1315

14-
t.equal(intersects(comp0, comp1), expect, `${c0} intersects ${c1} objects`)
15-
t.equal(intersects(comp1, comp0), expect, `${c1} intersects ${c0} objects`)
16-
t.equal(intersects(comp0, comp1, true), expect,
17-
`${c0} intersects ${c1} loose, objects`)
18-
t.equal(intersects(comp1, comp0, true), expect,
19-
`${c1} intersects ${c0} loose, objects`)
20-
t.equal(intersects(c0, c1), expect, `${c0} intersects ${c1}`)
21-
t.equal(intersects(c1, c0), expect, `${c1} intersects ${c0}`)
22-
t.equal(intersects(c0, c1, true), expect,
23-
`${c0} intersects ${c1} loose`)
24-
t.equal(intersects(c1, c0, true), expect,
25-
`${c1} intersects ${c0} loose`)
26-
t.end()
27-
}))
16+
t.equal(intersects(comp0, comp1, opts), expect, `${c0} intersects ${c1} objects`)
17+
t.equal(intersects(comp1, comp0, opts), expect, `${c1} intersects ${c0} objects`)
18+
t.equal(intersects(c0, c1, opts), expect, `${c0} intersects ${c1}`)
19+
t.equal(intersects(c1, c0, opts), expect, `${c1} intersects ${c0}`)
20+
21+
opts.loose = true
22+
t.equal(intersects(comp0, comp1, opts), expect, `${c0} intersects ${c1} loose, objects`)
23+
t.equal(intersects(comp1, comp0, opts), expect, `${c1} intersects ${c0} loose, objects`)
24+
t.equal(intersects(c0, c1, opts), expect, `${c0} intersects ${c1} loose`)
25+
t.equal(intersects(c1, c0, opts), expect, `${c1} intersects ${c0} loose`)
26+
t.end()
27+
}))
2828
})
2929

3030
test('ranges intersect', (t) => {

0 commit comments

Comments
 (0)