-
Notifications
You must be signed in to change notification settings - Fork 488
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for range and comparators comparison #187
Changes from 2 commits
a29e8db
b5504e7
57c77f3
0cb989f
4fa71d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ | |
.*.swp | ||
coverage/ | ||
.nyc_output/ | ||
.idea | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -704,6 +704,48 @@ Comparator.prototype.test = function(version) { | |
return cmp(version, this.operator, this.semver, this.loose); | ||
}; | ||
|
||
Comparator.prototype.intersects = function(comp, loose, platform) { | ||
if (!(comp instanceof Comparator)) { | ||
throw new TypeError('a Comparator is required'); | ||
} | ||
|
||
var rangeTmp; | ||
|
||
if (this.operator === '') { | ||
rangeTmp = new Range(comp.value, loose, platform); | ||
return satisfies(this.value, rangeTmp, loose, platform); | ||
} else if (comp.operator === '') { | ||
rangeTmp = new Range(this.value, loose, platform); | ||
return satisfies(comp.semver, rangeTmp, loose, platform); | ||
} | ||
|
||
var sameDirectionIncreasing = (this.operator === '>=' || this.operator === '>') && (comp.operator === '>=' || comp.operator === '>'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These really long lines are very hard to read. Can you please break this up into separate stanzas? There should be no lines longer than 80 chars under any circumstances. 70 is an even better limit. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
var sameDirectionDecreasing = (this.operator === '<=' || this.operator === '<') && (comp.operator === '<=' || comp.operator === '<'); | ||
var sameSemVer = this.semver.raw === comp.semver.raw; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think what you're after isn't
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, that fixes it. I'll include it in the merge, no worries. |
||
var differentDirectionsInclusive = (this.operator === '>=' || this.operator === '<=') && (comp.operator === '>=' || comp.operator === '<='); | ||
var oppositeDirectionsLessThan = cmp(this.semver, '<', comp.semver, loose) && | ||
((this.operator === '>=' || this.operator === '>') && (comp.operator === '<=' || comp.operator === '<')); | ||
var oppositeDirectionsGreaterThan = cmp(this.semver, '>', comp.semver, loose) && | ||
((this.operator === '<=' || this.operator === '<') && (comp.operator === '>=' || comp.operator === '>')); | ||
|
||
return sameDirectionIncreasing || sameDirectionDecreasing || (sameSemVer && differentDirectionsInclusive) || | ||
oppositeDirectionsLessThan || oppositeDirectionsGreaterThan; | ||
}; | ||
|
||
Comparator.prototype.satisfiesRange = function(range, loose, platform) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the "platform" variable being passed around here? It doesn't seem like it's ever used for anything. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ported this from the Ruby version and somehow did not notice platform did not exist here. |
||
if (!(range instanceof Range)) { | ||
throw new TypeError('a Range is required'); | ||
} | ||
|
||
var comp = this; | ||
|
||
return range.set.some(function(comparators) { | ||
return comparators.every(function(comparator) { | ||
return comp.intersects(comparator, loose, platform); | ||
}); | ||
}); | ||
}; | ||
|
||
|
||
exports.Range = Range; | ||
function Range(range, loose) { | ||
|
@@ -783,6 +825,18 @@ Range.prototype.parseRange = function(range) { | |
return set; | ||
}; | ||
|
||
Range.prototype.intersects = function(range, loose, platform) { | ||
if (!(range instanceof Range)) { | ||
throw new TypeError('a Range is required'); | ||
} | ||
|
||
return this.set.some(function(comparators) { | ||
return comparators.every(function(comparator) { | ||
return comparator.satisfiesRange(range, loose, platform); | ||
}); | ||
}); | ||
}; | ||
|
||
// Mostly just for testing and legacy API reasons | ||
exports.toComparators = toComparators; | ||
function toComparators(range, loose) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ var replaceStars = semver.replaceStars; | |
var toComparators = semver.toComparators; | ||
var SemVer = semver.SemVer; | ||
var Range = semver.Range; | ||
var Comparator = semver.Comparator; | ||
|
||
test('\ncomparison tests', function(t) { | ||
// [version1, version2] | ||
|
@@ -712,3 +713,107 @@ test('\nmin satisfying', function(t) { | |
}); | ||
t.end(); | ||
}); | ||
|
||
test('\nintersect comparators', function(t) { | ||
[ | ||
// One is a Version | ||
['1.3.0', '>=1.3.0', true], | ||
['1.3.0', '>1.3.0', false], | ||
['>=1.3.0', '1.3.0', true], | ||
['>1.3.0', '1.3.0', false], | ||
// Same direction increasing | ||
['>1.3.0', '>1.2.0', true], | ||
['>1.2.0', '>1.3.0', true], | ||
['>=1.2.0', '>1.3.0', true], | ||
['>1.2.0', '>=1.3.0', true], | ||
// Same direction decreasing | ||
['<1.3.0', '<1.2.0', true], | ||
['<1.2.0', '<1.3.0', true], | ||
['<=1.2.0', '<1.3.0', true], | ||
['<1.2.0', '<=1.3.0', true], | ||
// Different directions, same semver and inclusive operator | ||
['>=1.3.0', '<=1.3.0', true], | ||
['>=1.3.0', '>=1.3.0', true], | ||
['<=1.3.0', '<=1.3.0', true], | ||
['>1.3.0', '<=1.3.0', false], | ||
['>=1.3.0', '<1.3.0', false], | ||
// Opposite matching directions | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could instead be done in the iterator function, for every test, no? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not understanding exactly what you mean here. Can you extend a bit? Also, should I amend my previous commit or should I create new commits to fix the requested changes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean, line 752 asks if comparator1 intersects comparator2; could you also add an assertion after that asking if comparator2 intersects comparator1? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think amending and force pushing is always fine; unless one of this repo's collabs says different. |
||
['>1.0.0', '<2.0.0', true], | ||
['>=1.0.0', '<2.0.0', true], | ||
['>=1.0.0', '<=2.0.0', true], | ||
['>1.0.0', '<=2.0.0', true], | ||
['<=2.0.0', '>1.0.0', true], | ||
['<=1.0.0', '>=2.0.0', false] | ||
].forEach(function(v) { | ||
var comparator1 = new Comparator(v[0]); | ||
var comparator2 = new Comparator(v[1]); | ||
var expect = v[2]; | ||
|
||
var actual1 = comparator1.intersects(comparator2); | ||
var actual2 = comparator2.intersects(comparator1); | ||
t.equal(actual1, expect); | ||
t.equal(actual2, expect); | ||
}); | ||
t.end(); | ||
}); | ||
|
||
test('\nmissing comparator parameter in intersect comparators', function(t) { | ||
t.throws(function() { | ||
new Comparator('>1.0.0').intersects(); | ||
}, new TypeError('a Comparator is required'), | ||
'throws type error'); | ||
t.end(); | ||
}); | ||
|
||
test('\ncomparator satisfies range', function(t) { | ||
[ | ||
['1.3.0', '1.3.0 || <1.0.0 >2.0.0', true], | ||
['1.3.0', '<1.0.0 >2.0.0', false], | ||
['>=1.3.0', '<1.3.0', false], | ||
['<1.3.0', '>=1.3.0', false] | ||
].forEach(function(v) { | ||
var comparator = new Comparator(v[0]); | ||
var range = new Range(v[1]); | ||
var expect = v[2]; | ||
var actual = comparator.satisfiesRange(range); | ||
t.equal(actual, expect); | ||
}); | ||
t.end(); | ||
}); | ||
|
||
test('\nmissing range parameter in comparator satisfies range', function(t) { | ||
t.throws(function() { | ||
new Comparator('>1.0.0').satisfiesRange(); | ||
}, new TypeError('a Range is required'), | ||
'throws type error'); | ||
t.end(); | ||
}); | ||
|
||
test('\nranges intersect', function(t) { | ||
[ | ||
['1.3.0 || <1.0.0 >2.0.0', '1.3.0 || <1.0.0 >2.0.0', true], | ||
['<1.0.0 >2.0.0', '>0.0.0', true], | ||
['<1.0.0 >2.0.0', '>1.4.0 <1.6.0', false], | ||
['<1.0.0 >2.0.0', '>1.4.0 <1.6.0 || 2.0.0', false], | ||
['>1.0.0 <=2.0.0', '2.0.0', true], | ||
['<1.0.0 >=2.0.0', '2.1.0', false], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a test case for a single version returning true? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
['<1.0.0 >=2.0.0', '>1.4.0 <1.6.0 || 2.0.0', false] | ||
].forEach(function(v) { | ||
var range1 = new Range(v[0]); | ||
var range2 = new Range(v[1]); | ||
var expect = v[2]; | ||
var actual1 = range1.intersects(range2); | ||
var actual2 = range2.intersects(range1); | ||
t.equal(actual1, expect); | ||
t.equal(actual2, expect); | ||
}); | ||
t.end(); | ||
}); | ||
|
||
test('\nmissing range parameter in range intersect', function(t) { | ||
t.throws(function() { | ||
new Range('1.0.0').intersects(); | ||
}, new TypeError('a Range is required'), | ||
'throws type error'); | ||
t.end(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally this belongs in a global git config, rather than polluting specific git repos with IDE-specific knowledge (nbd tho)