Skip to content

Commit 67c9ed7

Browse files
rtfpessoaisaacs
authored andcommitted
Add support for range and comparators comparison
* Check if two ranges intersect * Check if one comparator satisfies a range * Check if two comparators intersect
1 parent caeeac4 commit 67c9ed7

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
.*.swp
33
coverage/
44
.nyc_output/
5+
.idea

Diff for: semver.js

+50
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,56 @@ function toComparators(range, loose) {
793793
});
794794
}
795795

796+
exports.comparatorsIntersect = comparatorsIntersect;
797+
function comparatorsIntersect(compA, compB, loose, platform) {
798+
compA = new Comparator(compA, loose);
799+
compB = new Comparator(compB, loose);
800+
801+
if (compA.operator === '') {
802+
var rangeB = new Range(compB.value, loose, platform);
803+
return satisfies(compA.value, rangeB, loose, platform);
804+
} else if (compB.operator === '') {
805+
var rangeA = new Range(compA.value, loose, platform);
806+
return satisfies(compB.semver, rangeA, loose, platform);
807+
}
808+
// Same direction increasing
809+
return ((compA.operator === '>=' || compA.operator === '>') && (compB.operator === '>=' || compB.operator === '>')) ||
810+
// Same direction decreasing
811+
((compA.operator === '<=' || compA.operator === '<') && (compB.operator === '<=' || compB.operator === '<')) ||
812+
// Different directions, same semver and inclusive operator
813+
(compA.semver.raw === compB.semver.raw &&
814+
(compA.operator === '>=' || compA.operator === '<=') && (compB.operator === '>=' || compB.operator === '<=')) ||
815+
// Opposite matching directions
816+
(cmp(compA.semver, '<', compB.semver, loose) &&
817+
((compA.operator === '>=' || compA.operator === '>') && (compB.operator === '<=' || compB.operator === '<'))) ||
818+
(cmp(compA.semver, '>', compB.semver, loose) &&
819+
((compA.operator === '<=' || compA.operator === '<') && (compB.operator === '>=' || compB.operator === '>')));
820+
}
821+
822+
exports.comparatorSatisfiesRange = comparatorSatisfiesRange;
823+
function comparatorSatisfiesRange(comp, range, loose, platform) {
824+
comp = new Comparator(comp, loose);
825+
range = new Range(range, loose, platform);
826+
827+
return range.set.some(function(comparators) {
828+
return comparators.every(function(comparator) {
829+
return comparatorsIntersect(comparator, comp, loose, platform);
830+
});
831+
});
832+
}
833+
834+
exports.rangesIntersect = rangesIntersect;
835+
function rangesIntersect(rangeA, rangeB, loose, platform) {
836+
rangeA = new Range(rangeA, loose, platform);
837+
rangeB = new Range(rangeB, loose, platform);
838+
839+
return rangeA.set.some(function(comparators) {
840+
return comparators.every(function(comparator) {
841+
return comparatorSatisfiesRange(comparator, rangeB, loose, platform);
842+
});
843+
});
844+
}
845+
796846
// comprised of xranges, tildes, stars, and gtlt's at this point.
797847
// already replaced the hyphen ranges
798848
// turn into a set of JUST comparators.

Diff for: test/index.js

+74
Original file line numberDiff line numberDiff line change
@@ -712,3 +712,77 @@ test('\nmin satisfying', function(t) {
712712
});
713713
t.end();
714714
});
715+
716+
test('\nintersect comparators', function(t) {
717+
[
718+
// One is a Version
719+
['1.3.0', '>=1.3.0', true],
720+
['1.3.0', '>1.3.0', false],
721+
['>=1.3.0', '1.3.0', true],
722+
['>1.3.0', '1.3.0', false],
723+
// Same direction increasing
724+
['>1.3.0', '>1.2.0', true],
725+
['>1.2.0', '>1.3.0', true],
726+
['>=1.2.0', '>1.3.0', true],
727+
['>1.2.0', '>=1.3.0', true],
728+
// Same direction decreasing
729+
['<1.3.0', '<1.2.0', true],
730+
['<1.2.0', '<1.3.0', true],
731+
['<=1.2.0', '<1.3.0', true],
732+
['<1.2.0', '<=1.3.0', true],
733+
// Different directions, same semver and inclusive operator
734+
['>=1.3.0', '<=1.3.0', true],
735+
['>=1.3.0', '>=1.3.0', true],
736+
['<=1.3.0', '<=1.3.0', true],
737+
['>1.3.0', '<=1.3.0', false],
738+
['>=1.3.0', '<1.3.0', false],
739+
// Opposite matching directions
740+
['>1.0.0', '<2.0.0', true],
741+
['>=1.0.0', '<2.0.0', true],
742+
['>=1.0.0', '<=2.0.0', true],
743+
['>1.0.0', '<=2.0.0', true],
744+
['<=2.0.0', '>1.0.0', true],
745+
['<=1.0.0', '>=2.0.0', false]
746+
].forEach(function(v) {
747+
var comparator1 = v[0];
748+
var comparator2 = v[1];
749+
var expect = v[2];
750+
var actual = semver.comparatorsIntersect(comparator1, comparator2);
751+
t.equal(actual, expect);
752+
});
753+
t.end();
754+
});
755+
756+
test('\ncomparator satisfies range', function(t) {
757+
[
758+
['1.3.0', '1.3.0 || <1.0.0 >2.0.0', true],
759+
['1.3.0', '<1.0.0 >2.0.0', false],
760+
['>=1.3.0', '<1.3.0', false],
761+
['<1.3.0', '>=1.3.0', false]
762+
].forEach(function(v) {
763+
var comparator = v[0];
764+
var range = v[1];
765+
var expect = v[2];
766+
var actual = semver.comparatorSatisfiesRange(comparator, range);
767+
t.equal(actual, expect);
768+
});
769+
t.end();
770+
});
771+
772+
test('\nranges intersect', function(t) {
773+
[
774+
['1.3.0 || <1.0.0 >2.0.0', '1.3.0 || <1.0.0 >2.0.0', true],
775+
['<1.0.0 >2.0.0', '>0.0.0', true],
776+
['<1.0.0 >2.0.0', '>1.4.0 <1.6.0', false],
777+
['<1.0.0 >2.0.0', '>1.4.0 <1.6.0 || 2.0.0', false],
778+
['<1.0.0 >=2.0.0', '2.1.0', false],
779+
['<1.0.0 >=2.0.0', '>1.4.0 <1.6.0 || 2.0.0', false]
780+
].forEach(function(v) {
781+
var range1 = v[0];
782+
var range2 = v[1];
783+
var expect = v[2];
784+
var actual = semver.rangesIntersect(range1, range2);
785+
t.equal(actual, expect);
786+
});
787+
t.end();
788+
});

0 commit comments

Comments
 (0)