-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathconvert-range.js
144 lines (128 loc) · 4.51 KB
/
convert-range.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
const nodeSemver = require('semver');
const { Semver, SemverRange } = require('./sver');
module.exports = function nodeRangeToSemverRange (range) {
let parsed = nodeSemver.validRange(range);
// tag version
if (!parsed)
return new SemverRange(range);
if (parsed === '*')
return new SemverRange(parsed);
try {
let semverRange = new SemverRange(range);
if (!semverRange.version.tag)
return semverRange;
}
catch (e) {
if (e.code !== 'ENOTSEMVER')
throw e;
}
let outRange;
for (let union of parsed.split('||')) {
// compute the intersection into a lowest upper bound and a highest lower bound
let upperBound, lowerBound, upperEq, lowerEq;
for (let intersection of union.split(' ')) {
let lt = intersection[0] === '<';
let gt = intersection[0] === '>';
if (!lt && !gt) {
upperBound = intersection;
upperEq = true;
break;
}
let eq = intersection[1] === '=';
if (!gt) {
let version = new Semver(intersection.substr(1 + eq));
if (!upperBound || upperBound.gt(version)) {
upperBound = version;
upperEq = eq;
}
}
else if (!lt) {
let eq = intersection[1] === '=';
let version = new Semver(intersection.substr(1 + eq));
if (!lowerBound || lowerBound.lt(version)) {
lowerBound = version;
lowerEq = eq;
}
}
}
// no upper bound -> wildcard
if (!upperBound) {
outRange = new SemverRange('*');
continue;
}
// if the lower bound is greater than the upper bound then just return the lower bound exactly
if (lowerBound && upperBound && lowerBound.gt(upperBound)) {
let curRange = new SemverRange(lowerBound.toString());
// the largest or highest union range wins
if (!outRange || !outRange.contains(curRange) && (curRange.gt(outRange) || curRange.contains(outRange)))
outRange = curRange;
continue;
}
// determine the largest semver range satisfying the upper bound
let upperRange;
if (upperBound) {
// if the upper bound has an equality then we return it directly
if (upperEq) {
let curRange = new SemverRange(upperBound.toString());
// the largest or highest union range wins
if (!outRange || !outRange.contains(curRange) && (curRange.gt(outRange) || curRange.contains(outRange)))
outRange = curRange;
continue;
}
let major = 0, minor = 0, patch = 0, rangeType = '';
// if an exact prerelease range, match the lower bound as a range
if (upperBound.pre && lowerBound.major === upperBound.major && lowerBound.minor === upperBound.minor && lowerBound.patch === upperBound.patch) {
outRange = new SemverRange('~' + lowerBound.toString());
continue;
}
// <2.0.0 -> ^1.0.0
else if (upperBound.patch === 0) {
if (upperBound.minor === 0) {
if (upperBound.major > 0) {
major = upperBound.major - 1;
rangeType = '^';
}
}
// <1.2.0 -> ~1.1.0
else {
major = upperBound.major;
minor = upperBound.minor - 1;
rangeType = '~';
}
}
// <1.2.3 -> ~1.2.0
else {
major = upperBound.major;
minor = upperBound.minor;
patch = 0;
rangeType = '~';
}
if (major === 0 && rangeType === '^')
upperRange = new SemverRange('0');
else
upperRange = new SemverRange(rangeType + major + '.' + minor + '.' + patch);
}
if (!lowerBound) {
outRange = upperRange;
continue;
}
// determine the lower range semver range
let lowerRange;
if (!lowerEq) {
if (lowerBound.pre)
lowerRange = new SemverRange('^^' + lowerBound.major + '.' + lowerBound.minor + '.' + lowerBound.patch + '-' + [...lowerBound.pre, 1].join('.'));
else
lowerRange = new SemverRange('^^' + lowerBound.major + '.' + lowerBound.minor + '.' + (lowerBound.patch + 1));
}
else {
lowerRange = new SemverRange('^^' + lowerBound.toString());
}
// we then intersect the upper semver range with the lower semver range
// if the intersection is empty, we return the upper range only
let curRange = upperRange ? lowerRange.intersect(upperRange) || upperRange : lowerRange;
// the largest or highest union range wins
if (!outRange || !outRange.contains(curRange) && (curRange.gt(outRange) || curRange.contains(outRange)))
outRange = curRange;
}
return outRange;
}