Skip to content

Commit

Permalink
Add support for range and comparators comparison
Browse files Browse the repository at this point in the history
* Check if two ranges intersect
* Check if one comparator satisfies a range
* Check if two comparators intersect
  • Loading branch information
rtfpessoa authored and isaacs committed Jul 24, 2017
1 parent caeeac4 commit 67c9ed7
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -2,3 +2,4 @@
.*.swp
coverage/
.nyc_output/
.idea
50 changes: 50 additions & 0 deletions semver.js
Expand Up @@ -793,6 +793,56 @@ function toComparators(range, loose) {
});
}

exports.comparatorsIntersect = comparatorsIntersect;
function comparatorsIntersect(compA, compB, loose, platform) {
compA = new Comparator(compA, loose);
compB = new Comparator(compB, loose);

if (compA.operator === '') {
var rangeB = new Range(compB.value, loose, platform);
return satisfies(compA.value, rangeB, loose, platform);
} else if (compB.operator === '') {
var rangeA = new Range(compA.value, loose, platform);
return satisfies(compB.semver, rangeA, loose, platform);
}
// Same direction increasing
return ((compA.operator === '>=' || compA.operator === '>') && (compB.operator === '>=' || compB.operator === '>')) ||
// Same direction decreasing
((compA.operator === '<=' || compA.operator === '<') && (compB.operator === '<=' || compB.operator === '<')) ||
// Different directions, same semver and inclusive operator
(compA.semver.raw === compB.semver.raw &&
(compA.operator === '>=' || compA.operator === '<=') && (compB.operator === '>=' || compB.operator === '<=')) ||
// Opposite matching directions
(cmp(compA.semver, '<', compB.semver, loose) &&
((compA.operator === '>=' || compA.operator === '>') && (compB.operator === '<=' || compB.operator === '<'))) ||
(cmp(compA.semver, '>', compB.semver, loose) &&
((compA.operator === '<=' || compA.operator === '<') && (compB.operator === '>=' || compB.operator === '>')));
}

exports.comparatorSatisfiesRange = comparatorSatisfiesRange;
function comparatorSatisfiesRange(comp, range, loose, platform) {
comp = new Comparator(comp, loose);
range = new Range(range, loose, platform);

return range.set.some(function(comparators) {
return comparators.every(function(comparator) {
return comparatorsIntersect(comparator, comp, loose, platform);
});
});
}

exports.rangesIntersect = rangesIntersect;
function rangesIntersect(rangeA, rangeB, loose, platform) {
rangeA = new Range(rangeA, loose, platform);
rangeB = new Range(rangeB, loose, platform);

return rangeA.set.some(function(comparators) {
return comparators.every(function(comparator) {
return comparatorSatisfiesRange(comparator, rangeB, loose, platform);
});
});
}

// comprised of xranges, tildes, stars, and gtlt's at this point.
// already replaced the hyphen ranges
// turn into a set of JUST comparators.
Expand Down
74 changes: 74 additions & 0 deletions test/index.js
Expand Up @@ -712,3 +712,77 @@ 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
['>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 = v[0];
var comparator2 = v[1];
var expect = v[2];
var actual = semver.comparatorsIntersect(comparator1, comparator2);
t.equal(actual, expect);
});
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 = v[0];
var range = v[1];
var expect = v[2];
var actual = semver.comparatorSatisfiesRange(comparator, range);
t.equal(actual, expect);
});
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.1.0', false],
['<1.0.0 >=2.0.0', '>1.4.0 <1.6.0 || 2.0.0', false]
].forEach(function(v) {
var range1 = v[0];
var range2 = v[1];
var expect = v[2];
var actual = semver.rangesIntersect(range1, range2);
t.equal(actual, expect);
});
t.end();
});

0 comments on commit 67c9ed7

Please sign in to comment.