Skip to content

Commit

Permalink
new v4 range prerelease behavior
Browse files Browse the repository at this point in the history
Simplify range expansions to remove -0 everywhere.

Only allow -prerelease versions that have a -prerelease tag on a version
in the range with the same exact X.Y.Z tuple.
  • Loading branch information
isaacs committed Sep 11, 2014
1 parent 6a2198c commit 2331a9e
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 152 deletions.
121 changes: 69 additions & 52 deletions semver.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,6 @@ src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
'(?:(' + src[PRERELEASELOOSE] + ')' +
')?)?)?';

// >=2.x, for example, means >=2.0.0-0
// <1.x would be the same as "<1.0.0-0", though.
var XRANGE = R++;
src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$';
var XRANGELOOSE = R++;
Expand Down Expand Up @@ -416,8 +414,8 @@ SemVer.prototype.inc = function(release) {
this.patch++;
this.prerelease = [];
break;
// This probably shouldn't be used publically.
// 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction.
// This probably shouldn't be used publicly.
// 1.0.0 "pre" would become 1.0.0 which is the wrong direction.
case 'pre':
if (this.prerelease.length === 0)
this.prerelease = [0];
Expand Down Expand Up @@ -578,6 +576,8 @@ function Comparator(comp, loose) {
this.value = '';
else
this.value = this.operator + this.semver.version;

debug('comp', this);
}

var ANY = {};
Expand All @@ -595,21 +595,8 @@ Comparator.prototype.parse = function(comp) {
// if it literally is just '>' or '' then allow anything.
if (!m[2])
this.semver = ANY;
else {
else
this.semver = new SemVer(m[2], this.loose);

// <1.2.3-rc DOES allow 1.2.3-beta (has prerelease)
// >=1.2.3 DOES NOT allow 1.2.3-beta
// <=1.2.3 DOES allow 1.2.3-beta
// However, <1.2.3 does NOT allow 1.2.3-beta,
// even though `1.2.3-beta < 1.2.3`
// The assumption is that the 1.2.3 version has something you
// *don't* want, so we push the prerelease down to the minimum.
if (this.operator === '<' && !this.semver.prerelease.length) {
this.semver.prerelease = ['0'];
this.semver.format();
}
}
};

Comparator.prototype.inspect = function() {
Expand All @@ -622,8 +609,14 @@ Comparator.prototype.toString = function() {

Comparator.prototype.test = function(version) {
debug('Comparator.test', version, this.loose);
return (this.semver === ANY) ? true :
cmp(version, this.operator, this.semver, this.loose);

if (this.semver === ANY)
return true;

if (typeof version === 'string')
version = new SemVer(version, this.loose);

return cmp(version, this.operator, this.semver, this.loose);
};


Expand Down Expand Up @@ -760,20 +753,20 @@ function replaceTilde(comp, loose) {
if (isX(M))
ret = '';
else if (isX(m))
ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0';
ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
else if (isX(p))
// ~1.2 == >=1.2.0- <1.3.0-
ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0';
ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
else if (pr) {
debug('replaceTilde pr', pr);
if (pr.charAt(0) !== '-')
pr = '-' + pr;
ret = '>=' + M + '.' + m + '.' + p + pr +
' <' + M + '.' + (+m + 1) + '.0-0';
' <' + M + '.' + (+m + 1) + '.0';
} else
// ~1.2.3 == >=1.2.3-0 <1.3.0-0
ret = '>=' + M + '.' + m + '.' + p + '-0' +
' <' + M + '.' + (+m + 1) + '.0-0';
// ~1.2.3 == >=1.2.3 <1.3.0
ret = '>=' + M + '.' + m + '.' + p +
' <' + M + '.' + (+m + 1) + '.0';

debug('tilde return', ret);
return ret;
Expand All @@ -793,6 +786,7 @@ function replaceCarets(comp, loose) {
}

function replaceCaret(comp, loose) {
debug('caret', comp, loose);
var r = loose ? re[CARETLOOSE] : re[CARET];
return comp.replace(r, function(_, M, m, p, pr) {
debug('caret', comp, _, M, m, p, pr);
Expand All @@ -801,12 +795,12 @@ function replaceCaret(comp, loose) {
if (isX(M))
ret = '';
else if (isX(m))
ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0';
ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
else if (isX(p)) {
if (M === '0')
ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0';
ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
else
ret = '>=' + M + '.' + m + '.0-0 <' + (+M + 1) + '.0.0-0';
ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0';
} else if (pr) {
debug('replaceCaret pr', pr);
if (pr.charAt(0) !== '-')
Expand All @@ -816,20 +810,21 @@ function replaceCaret(comp, loose) {
ret = '=' + M + '.' + m + '.' + p + pr;
else
ret = '>=' + M + '.' + m + '.' + p + pr +
' <' + M + '.' + (+m + 1) + '.0-0';
' <' + M + '.' + (+m + 1) + '.0';
} else
ret = '>=' + M + '.' + m + '.' + p + pr +
' <' + (+M + 1) + '.0.0-0';
' <' + (+M + 1) + '.0.0';
} else {
debug('no pr');
if (M === '0') {
if (m === '0')
ret = '=' + M + '.' + m + '.' + p;
else
ret = '>=' + M + '.' + m + '.' + p + '-0' +
' <' + M + '.' + (+m + 1) + '.0-0';
ret = '>=' + M + '.' + m + '.' + p +
' <' + M + '.' + (+m + 1) + '.0';
} else
ret = '>=' + M + '.' + m + '.' + p + '-0' +
' <' + (+M + 1) + '.0.0-0';
ret = '>=' + M + '.' + m + '.' + p +
' <' + (+M + 1) + '.0.0';
}

debug('caret return', ret);
Expand Down Expand Up @@ -858,7 +853,7 @@ function replaceXRange(comp, loose) {
gtlt = '';

if (gtlt && anyX) {
// replace X with 0, and then append the -0 min-prerelease
// replace X with 0
if (xM)
M = 0;
if (xm)
Expand All @@ -867,9 +862,9 @@ function replaceXRange(comp, loose) {
p = 0;

if (gtlt === '>') {
// >1 => >=2.0.0-0
// >1.2 => >=1.3.0-0
// >1.2.3 => >= 1.2.4-0
// >1 => >=2.0.0
// >1.2 => >=1.3.0
// >1.2.3 => >= 1.2.4
gtlt = '>=';
if (xM) {
// no change
Expand All @@ -884,17 +879,14 @@ function replaceXRange(comp, loose) {
}


ret = gtlt + M + '.' + m + '.' + p + '-0';
ret = gtlt + M + '.' + m + '.' + p;
} else if (xM) {
// allow any
ret = '*';
} else if (xm) {
// append '-0' onto the version, otherwise
// '1.x.x' matches '2.0.0-beta', since the tag
// *lowers* the version value
ret = '>=' + M + '.0.0-0 <' + (+M + 1) + '.0.0-0';
ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0';
} else if (xp) {
ret = '>=' + M + '.' + m + '.0-0 <' + M + '.' + (+m + 1) + '.0-0';
ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0';
}

debug('xRange return', ret);
Expand All @@ -913,28 +905,28 @@ function replaceStars(comp, loose) {

// This function is passed to string.replace(re[HYPHENRANGE])
// M, m, patch, prerelease, build
// 1.2 - 3.4.5 => >=1.2.0-0 <=3.4.5
// 1.2.3 - 3.4 => >=1.2.0-0 <3.5.0-0 Any 3.4.x will do
// 1.2 - 3.4 => >=1.2.0-0 <3.5.0-0
// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do
// 1.2 - 3.4 => >=1.2.0 <3.5.0
function hyphenReplace($0,
from, fM, fm, fp, fpr, fb,
to, tM, tm, tp, tpr, tb) {

if (isX(fM))
from = '';
else if (isX(fm))
from = '>=' + fM + '.0.0-0';
from = '>=' + fM + '.0.0';
else if (isX(fp))
from = '>=' + fM + '.' + fm + '.0-0';
from = '>=' + fM + '.' + fm + '.0';
else
from = '>=' + from;

if (isX(tM))
to = '';
else if (isX(tm))
to = '<' + (+tM + 1) + '.0.0-0';
to = '<' + (+tM + 1) + '.0.0';
else if (isX(tp))
to = '<' + tM + '.' + (+tm + 1) + '.0-0';
to = '<' + tM + '.' + (+tm + 1) + '.0';
else if (tpr)
to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr;
else
Expand Down Expand Up @@ -964,6 +956,31 @@ function testSet(set, version) {
if (!set[i].test(version))
return false;
}

if (version.prerelease.length) {
// Find the set of versions that are allowed to have prereleases
// For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0
// That should allow `1.2.3-pr.2` to pass.
// However, `1.2.4-alpha.notready` should NOT be allowed,
// even though it's within the range set by the comparators.
for (var i = 0; i < set.length; i++) {
debug(set[i].semver);
if (set[i].semver === ANY)
return true;

if (set[i].semver.prerelease.length > 0) {
var allowed = set[i].semver;
if (allowed.major === version.major &&
allowed.minor === version.minor &&
allowed.patch === version.patch)
return true;
}
}

// Version has a -pre, but it's not one of the ones we like.
return false;
}

return true;
}

Expand Down
2 changes: 1 addition & 1 deletion test/gtr.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ test('\ngtr tests', function(t) {
['~v0.5.4-pre', '0.6.1-pre'],
['=0.7.x', '0.8.0'],
['=0.7.x', '0.8.0-asdf'],
['<=0.7.x', '0.7.0'],
['<0.7.x', '0.7.0'],
['~1.2.2', '1.3.0'],
['1.0.0 - 2.0.0', '2.2.3'],
['1.0.0', '1.0.1'],
Expand Down
Loading

0 comments on commit 2331a9e

Please sign in to comment.