Commit 12020b35 authored by zeke's avatar zeke

use semver.io for great success

parent cdedbf03
#!/usr/bin/env bash
# fail fast
set -e
# Uncomment the line below to enable debugging
# set -x
download_and_install_node() {
version="$1"
node_url="http://s3pository.heroku.com/node/v$version/node-v$version-linux-x64.tar.gz"
curl $node_url -s -o - | tar xzf - -C $build_dir
mkdir -p $build_dir/vendor
# Remove node in case we're overwriting a previously-downloaded version
rm -rf $build_dir/vendor/node
mv $build_dir/node-v$version-linux-x64 $build_dir/vendor/node
chmod +x $build_dir/vendor/node/bin/*
PATH=$PATH:$build_dir/vendor/node/bin
}
query_stable_version() {
curl -s http://nodejs.org/dist/ \
| egrep -o '[0-9]+\.[0-9]*[02468]\.[0-9]+' \
| sort -u -k 1,1n -k 2,2n -k 3,3n -t . \
| tail -n1
}
query_latest_version() {
curl -s http://nodejs.org/dist/ \
| egrep -o '[0-9]+\.[0-9]+\.[0-9]+' \
| sort -u -k 1,1n -k 2,2n -k 3,3n -t . \
| tail -n1
}
query_all_versions() {
curl -s http://nodejs.org/dist/ \
| egrep -o '[0-9]+\.[0-9]+\.[0-9]+' \
| sort -u -k 1,1n -k 2,2n -k 3,3n -t .
}
error() {
echo " ! $*" >&2
exit 1
......@@ -49,6 +7,13 @@ status() {
echo "-----> $*"
}
protip() {
echo
echo "PRO TIP: $*" | indent
echo "See https://devcenter.heroku.com/articles/nodejs-support"
echo
}
# sed -l basically makes sed replace and buffer through stdin to stdout
# so you get updates while the command runs and dont wait for the end
# e.g. npm install | indent
......@@ -60,6 +25,6 @@ indent() {
esac
}
function cat_npm_debug_log() {
cat_npm_debug_log() {
test -f $build_dir/npm-debug.log && cat $build_dir/npm-debug.log
}
#!/usr/bin/env bash
# fail fast
set -e
# enable debugging
# set -x
# Configure directories
build_dir=$1
cache_basedir=$2
bp_dir=$(cd $(dirname $0); cd ..; pwd)
# Load some convenience functions like status() echo(), indent
source $bp_dir/bin/common.sh
# Output npm debug info on error
trap cat_npm_debug_log ERR
# Is a node version specified in package.json?
semver_range=$(cat $build_dir/package.json | $bp_dir/vendor/json engines.node)
# Look in package.json's engines.node field for a semver range
semver_range=$(cat $build_dir/package.json | $bp_dir/vendor/jq -r .engines.node)
# Recommend using semver ranges in a safe manner
if [ "$semver_range" == "null" ]; then
protip "Specify a node version in package.json"
semver_range=""
elif [ "$semver_range" == "*" ]; then
protip "Don't use semver ranges like *"
elif [ ${semver_range:0:1} == ">" ]; then
protip "Don't use semver ranges starting with >"
fi
# Resolve node version using a service
node_version=$(curl --silent https://node-semver-service.heroku.com/${semver_range})
# Resolve node version using semver.io
semver_url=http://semver.io/node/$semver_range
node_version=$(curl --silent $semver_url)
# Warn if engines.node is unspecified
if ! test $semver_range; then
echo
echo "WARNING: No node version specified in package.json, see:" | indent
echo "https://devcenter.heroku.com/articles/nodejs-support#versions" | indent
echo
status "Defaulting to latest stable node, v$node_version"
if [ "$semver_range" == "" ]; then
status "Defaulting to latest stable node: $node_version"
else
status "Resolved node version for $semver_range is $node_version"
fi
# TODO: Warn if engines.node is "*" or ">foo"
# Download and install node
# Download node from Heroku's S3 mirror of nodejs.org/dist
status "Downloading and installing node v$node_version"
download_and_install_node $node_version
node_url="http://s3pository.heroku.com/node/v$node_version/node-v$node_version-linux-x64.tar.gz"
curl $node_url -s -o - | tar xzf - -C $build_dir
# Move node into ./vendor and make it executable
mkdir -p $build_dir/vendor
mv $build_dir/node-v$node_version-linux-x64 $build_dir/vendor/node
chmod +x $build_dir/vendor/node/bin/*
PATH=$PATH:$build_dir/vendor/node/bin
# Run subsequent node/npm commands from the build path
cd $build_dir
......@@ -37,7 +58,7 @@ cd $build_dir
package_checksum=$(cat $build_dir/package.json | md5sum | awk '{print $1}')
cache_dir="$cache_basedir/$package_checksum"
# Restore from cache package.json hasn't changed
# Restore from cache if package.json hasn't changed
if test -d $cache_dir; then
status "package.json unchanged since last build"
status "Restoring node_modules from cache"
......@@ -54,7 +75,7 @@ else
status "Caching node_modules for future builds"
rm -rf $cache_dir
mkdir -p $cache_dir
mkdir -p $cache_dir/vendor
# mkdir -p $cache_dir/vendor
test -d $build_dir/node_modules && cp -r $build_dir/node_modules $cache_dir/
# cp -r $build_dir/vendor/node $cache_dir/vendor/
fi
......
......@@ -2,7 +2,7 @@
# See CONTRIBUTING.md for info on running these tests.
testDetectWithPackageJson() {
detect "package-json-stable-version"
detect "stable-node"
assertCaptured "Node.js"
assertCapturedSuccess
}
......@@ -12,44 +12,59 @@ testDetectWithoutPackageJson() {
assertCapturedError 1 ""
}
testPackageJsonWithoutVersion() {
compile "package-json-noversion"
assertCaptured "WARNING: No node version specified"
testNoVersion() {
compile "no-version"
assertCaptured "PRO TIP: Specify a node version in package.json"
assertCaptured "Defaulting to latest stable node"
assertCapturedSuccess
}
testPackageJsonWithStableVersion() {
compile "package-json-stable-version"
assertNotCaptured "WARNING: No node version specified"
assertCaptured "satisfies engines.node"
assertCapturedSuccess
}
testDangerousRangeStar() {
compile "dangerous-range-star"
assertCaptured "PRO TIP: Don't use semver ranges like *"
testPackageJsonWithUnstableVersion() {
compile "package-json-unstable-version"
assertCaptured "Downloading and installing node v0.11"
assertCapturedSuccess
}
testPackageJsonWithInvalidVersion() {
compile "package-json-invalidversion"
assertCapturedError 1 "not found among available versions"
testDangerousRangeGreaterThan() {
compile "dangerous-range-greater-than"
assertCaptured "PRO TIP: Don't use semver ranges starting with >"
assertCaptured "Resolved node version for >"
assertCapturedSuccess
}
testProfileCreated() {
compile "package-json-stable-version"
assertCaptured "Building runtime environment"
assertFile "export PATH=\"\$HOME/vendor/node/bin:$HOME/bin:\$HOME/node_modules/.bin:\$PATH\"" ".profile.d/nodejs.sh"
testStableVersion() {
compile "stable-node"
assertNotCaptured "PRO TIP"
assertCaptured "Resolved node version"
assertCapturedSuccess
}
testNodeModulesCached() {
cache=$(mktmpdir)
compile "node-modules-caching" $cache
assertCaptured "Caching node"
assertEquals "1" "$(ls -1 $cache/0.10.18 | wc -l)"
}
# testUnstableVersion() {
# compile "unstable-version"
# assertCaptured "Resolved node version for >0.11.0 is 0.11"
# assertCapturedSuccess
# }
# testInvalidVersion() {
# compile "invalid-node-version"
# assertCapturedError 1 "not found among available versions"
# }
# testProfileCreated() {
# compile "stable-node"
# assertCaptured "Building runtime environment"
# assertFile "export PATH=\"\$HOME/vendor/node/bin:$HOME/bin:\$HOME/node_modules/.bin:\$PATH\"" ".profile.d/nodejs.sh"
# assertCapturedSuccess
# }
# testNodeModulesCached() {
# cache=$(mktmpdir)
# compile "caching" $cache
# assertCaptured "Caching node"
# assertEquals "1" "$(ls -1 $cache/0.10.18 | wc -l)"
# }
# Pending
......
......@@ -7,6 +7,6 @@
"url" : "http://github.com/example/example.git"
},
"engines": {
"node": ">0.10.0"
"node": ">0.4"
}
}
{
"name": "node-buildpack-test-app",
"version": "0.0.1",
"description": "node buildpack integration test app",
"repository" : {
"type" : "git",
"url" : "http://github.com/example/example.git"
},
"engines": {
"node": "*"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
{
"name": "node-buildpack-test-app",
"version": "0.0.1",
"description": "node buildpack integration test app",
"repository" : {
"type" : "git",
"url" : "http://github.com/example/example.git"
},
"engines": {
"node": "~0.10.0"
}
}
A fake README, to keep npm from polluting stderr.
\ No newline at end of file
File added
This diff is collapsed.
Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
semver(1) -- The semantic versioner for npm
===========================================
## Usage
$ npm install semver
semver.valid('1.2.3') // true
semver.valid('a.b.c') // false
semver.clean(' =v1.2.3 ') // '1.2.3'
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
semver.gt('1.2.3', '9.8.7') // false
semver.lt('1.2.3', '9.8.7') // true
As a command-line utility:
$ semver -h
Usage: semver -v <version> [-r <range>]
Test if version(s) satisfy the supplied range(s),
and sort them.
Multiple versions or ranges may be supplied.
Program exits successfully if any valid version satisfies
all supplied ranges, and prints all satisfying versions.
If no versions are valid, or ranges are not satisfied,
then exits failure.
Versions are printed in ascending order, so supplying
multiple versions to the utility will just sort them.
## Versions
A version is the following things, in this order:
* a number (Major)
* a period
* a number (minor)
* a period
* a number (patch)
* OPTIONAL: a hyphen, followed by a number (build)
* OPTIONAL: a collection of pretty much any non-whitespace characters
(tag)
A leading `"="` or `"v"` character is stripped off and ignored.
## Comparisons
The ordering of versions is done using the following algorithm, given
two versions and asked to find the greater of the two:
* If the majors are numerically different, then take the one
with a bigger major number. `2.3.4 > 1.3.4`
* If the minors are numerically different, then take the one
with the bigger minor number. `2.3.4 > 2.2.4`
* If the patches are numerically different, then take the one with the
bigger patch number. `2.3.4 > 2.3.3`
* If only one of them has a build number, then take the one with the
build number. `2.3.4-0 > 2.3.4`
* If they both have build numbers, and the build numbers are numerically
different, then take the one with the bigger build number.
`2.3.4-10 > 2.3.4-9`
* If only one of them has a tag, then take the one without the tag.
`2.3.4 > 2.3.4-beta`
* If they both have tags, then take the one with the lexicographically
larger tag. `2.3.4-beta > 2.3.4-alpha`
* At this point, they're equal.
## Ranges
The following range styles are supported:
* `>1.2.3` Greater than a specific version.
* `<1.2.3` Less than
* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`
* `~1.2.3` := `>=1.2.3 <1.3.0`
* `~1.2` := `>=1.2.0 <2.0.0`
* `~1` := `>=1.0.0 <2.0.0`
* `1.2.x` := `>=1.2.0 <1.3.0`
* `1.x` := `>=1.0.0 <2.0.0`
Ranges can be joined with either a space (which implies "and") or a
`||` (which implies "or").
## Functions
* valid(v): Return the parsed version, or null if it's not valid.
* inc(v, release): Return the version incremented by the release type
(major, minor, patch, or build), or null if it's not valid.
### Comparison
* gt(v1, v2): `v1 > v2`
* gte(v1, v2): `v1 >= v2`
* lt(v1, v2): `v1 < v2`
* lte(v1, v2): `v1 <= v2`
* eq(v1, v2): `v1 == v2` This is true if they're logically equivalent,
even if they're not the exact same string. You already know how to
compare strings.
* neq(v1, v2): `v1 != v2` The opposite of eq.
* cmp(v1, comparator, v2): Pass in a comparison string, and it'll call
the corresponding function above. `"==="` and `"!=="` do simple
string comparison, but are included for completeness. Throws if an
invalid comparison string is provided.
* compare(v1, v2): Return 0 if v1 == v2, or 1 if v1 is greater, or -1 if
v2 is greater. Sorts in ascending order if passed to Array.sort().
* rcompare(v1, v2): The reverse of compare. Sorts an array of versions
in descending order when passed to Array.sort().
### Ranges
* validRange(range): Return the valid range or null if it's not valid
* satisfies(version, range): Return true if the version satisfies the
range.
* maxSatisfying(versions, range): Return the highest version in the list
that satisfies the range, or null if none of them do.
#!/usr/bin/env node
// Standalone semver comparison program.
// Exits successfully and prints matching version(s) if
// any supplied version is valid and passes all tests.
var argv = process.argv.slice(2)
, versions = []
, range = []
, gt = []
, lt = []
, eq = []
, semver = require("../semver")
main()
function main () {
if (!argv.length) return help()
while (argv.length) {
var a
switch (a = argv.shift()) {
case "-v": case "--version":
versions.push(argv.shift())
break
case "-r": case "--range":
range.push(argv.shift())
break
case "-h": case "--help": case "-?":
return help()
default:
versions.push(a)
break
}
}
versions = versions.filter(semver.valid)
for (var i = 0, l = range.length; i < l ; i ++) {
versions = versions.filter(function (v) {
return semver.satisfies(v, range[i])
})
if (!versions.length) return fail()
}
return success(versions)
}
function fail () { process.exit(1) }
function success () {
versions.sort(semver.compare)
.map(semver.clean)
.forEach(function (v,i,_) { console.log(v) })
}
function help () {
console.log(["Usage: semver -v <version> [-r <range>]"
,"Test if version(s) satisfy the supplied range(s),"
,"and sort them."
,""
,"Multiple versions or ranges may be supplied."
,""
,"Program exits successfully if any valid version satisfies"
,"all supplied ranges, and prints all satisfying versions."
,""
,"If no versions are valid, or ranges are not satisfied,"
,"then exits failure."
,""
,"Versions are printed in ascending order, so supplying"
,"multiple versions to the utility will just sort them."
].join("\n"))
}
{ "name" : "semver"
, "version" : "1.0.12"
, "description" : "The semantic version parser used by npm."
, "main" : "semver.js"
, "scripts" : { "test" : "tap test.js" }
, "devDependencies": { "tap" : "0.x >=0.0.4" }
, "license" :
{ "type" : "MIT"
, "url" : "https://github.com/isaacs/semver/raw/master/LICENSE" }
, "repository" : "git://github.com/isaacs/node-semver.git"
, "bin" : { "semver" : "./bin/semver" } }
;(function (exports) { // nothing in here is node-specific.
// See http://semver.org/
// This implementation is a *hair* less strict in that it allows
// v1.2.3 things, and also tags that don't begin with a char.
var semver = "\\s*[v=]*\\s*([0-9]+)" // major
+ "\\.([0-9]+)" // minor
+ "\\.([0-9]+)" // patch
+ "(-[0-9]+-?)?" // build
+ "([a-zA-Z-][a-zA-Z0-9-\.:]*)?" // tag
, exprComparator = "^((<|>)?=?)\s*("+semver+")$|^$"
, xRangePlain = "[v=]*([0-9]+|x|X|\\*)"
+ "(?:\\.([0-9]+|x|X|\\*)"
+ "(?:\\.([0-9]+|x|X|\\*)"
+ "([a-zA-Z-][a-zA-Z0-9-\.:]*)?)?)?"
, xRange = "((?:<|>)?=?)?\\s*" + xRangePlain
, exprSpermy = "(?:~>?)"+xRange
, expressions = exports.expressions =
{ parse : new RegExp("^\\s*"+semver+"\\s*$")
, parsePackage : new RegExp("^\\s*([^\/]+)[-@](" +semver+")\\s*$")
, parseRange : new RegExp(
"^\\s*(" + semver + ")\\s+-\\s+(" + semver + ")\\s*$")
, validComparator : new RegExp("^"+exprComparator+"$")
, parseXRange : new RegExp("^"+xRange+"$")
, parseSpermy : new RegExp("^"+exprSpermy+"$")
}
Object.getOwnPropertyNames(expressions).forEach(function (i) {
exports[i] = function (str) {
return ("" + (str || "")).match(expressions[i])
}
})
exports.rangeReplace = ">=$1 <=$7"
exports.clean = clean
exports.compare = compare
exports.satisfies = satisfies
exports.gt = gt
exports.gte = gte
exports.lt = lt
exports.lte = lte
exports.eq = eq
exports.neq = neq
exports.cmp = cmp
exports.inc = inc
exports.valid = valid
exports.validPackage = validPackage
exports.validRange = validRange
exports.maxSatisfying = maxSatisfying
exports.replaceStars = replaceStars
exports.toComparators = toComparators
function stringify (version) {
var v = version
return [v[1]||'', v[2]||'', v[3]||''].join(".") + (v[4]||'') + (v[5]||'')
}
function clean (version) {
version = exports.parse(version)
if (!version) return version
return stringify(version)
}
function valid (version) {
if (typeof version !== "string") return null
return exports.parse(version) && version.trim().replace(/^[v=]+/, '')
}
function validPackage (version) {
if (typeof version !== "string") return null
return version.match(expressions.parsePackage) && version.trim()
}
// range can be one of:
// "1.0.3 - 2.0.0" range, inclusive, like ">=1.0.3 <=2.0.0"
// ">1.0.2" like 1.0.3 - 9999.9999.9999
// ">=1.0.2" like 1.0.2 - 9999.9999.9999
// "<2.0.0" like 0.0.0 - 1.9999.9999
// ">1.0.2 <2.0.0" like 1.0.3 - 1.9999.9999
var starExpression = /(<|>)?=?\s*\*/g
, starReplace = ""
, compTrimExpression = new RegExp("((<|>)?=?)\\s*("
+semver+"|"+xRangePlain+")", "g")
, compTrimReplace = "$1$3"
function toComparators (range) {
var ret = (range || "").trim()
.replace(expressions.parseRange, exports.rangeReplace)
.replace(compTrimExpression, compTrimReplace)
.split(/\s+/)
.join(" ")
.split("||")
.map(function (orchunk) {
return orchunk
.split(" ")
.map(replaceXRanges)
.map(replaceSpermies)
.map(replaceStars)
.join(" ").trim()
})
.map(function (orchunk) {
return orchunk
.trim()
.split(/\s+/)
.filter(function (c) { return c.match(expressions.validComparator) })
})
.filter(function (c) { return c.length })
return ret
}
function replaceStars (stars) {
return stars.trim().replace(starExpression, starReplace)
}
// "2.x","2.x.x" --> ">=2.0.0- <2.1.0-"
// "2.3.x" --> ">=2.3.0- <2.4.0-"
function replaceXRanges (ranges) {
return ranges.split(/\s+/)
.map(replaceXRange)
.join(" ")
}
function replaceXRange (version) {
return version.trim().replace(expressions.parseXRange,
function (v, gtlt, M, m, p, t) {
var anyX = !M || M.toLowerCase() === "x" || M === "*"
|| !m || m.toLowerCase() === "x" || m === "*"
|| !p || p.toLowerCase() === "x" || p === "*"
, ret = v
if (gtlt && anyX) {
// just replace x'es with zeroes
;(!M || M === "*" || M.toLowerCase() === "x") && (M = 0)
;(!m || m === "*" || m.toLowerCase() === "x") && (m = 0)
;(!p || p === "*" || p.toLowerCase() === "x") && (p = 0)
ret = gtlt + M+"."+m+"."+p+"-"
} else if (!M || M === "*" || M.toLowerCase() === "x") {
ret = "*" // allow any
} else if (!m || m === "*" || m.toLowerCase() === "x") {
// append "-" onto the version, otherwise
// "1.x.x" matches "2.0.0beta", since the tag
// *lowers* the version value
ret = ">="+M+".0.0- <"+(+M+1)+".0.0-"
} else if (!p || p === "*" || p.toLowerCase() === "x") {
ret = ">="+M+"."+m+".0- <"+M+"."+(+m+1)+".0-"
}
//console.error("parseXRange", [].slice.call(arguments), ret)
return ret
})
}
// ~, ~> --> * (any, kinda silly)
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0
// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0
// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0
function replaceSpermies (version) {
return version.trim().replace(expressions.parseSpermy,
function (v, gtlt, M, m, p, t) {
if (gtlt) throw new Error(
"Using '"+gtlt+"' with ~ makes no sense. Don't do it.")
if (!M || M.toLowerCase() === "x") {
return ""
}
// ~1 == >=1.0.0- <2.0.0-
if (!m || m.toLowerCase() === "x") {
return ">="+M+".0.0- <"+(+M+1)+".0.0-"
}
// ~1.2 == >=1.2.0- <1.3.0-
if (!p || p.toLowerCase() === "x") {
return ">="+M+"."+m+".0- <"+M+"."+(+m+1)+".0-"
}
// ~1.2.3 == >=1.2.3- <1.3.0-
t = t || "-"
return ">="+M+"."+m+"."+p+t+" <"+M+"."+(+m+1)+".0-"
})
}
function validRange (range) {
range = replaceStars(range)
var c = toComparators(range)
return (c.length === 0)
? null
: c.map(function (c) { return c.join(" ") }).join("||")
}
// returns the highest satisfying version in the list, or undefined
function maxSatisfying (versions, range) {
return versions
.filter(function (v) { return satisfies(v, range) })
.sort(compare)
.pop()
}
function satisfies (version, range) {
version = valid(version)
if (!version) return false
range = toComparators(range)
for (var i = 0, l = range.length ; i < l ; i ++) {
var ok = false
for (var j = 0, ll = range[i].length ; j < ll ; j ++) {
var r = range[i][j]
, gtlt = r.charAt(0) === ">" ? gt
: r.charAt(0) === "<" ? lt
: false
, eq = r.charAt(!!gtlt) === "="
, sub = (!!eq) + (!!gtlt)
if (!gtlt) eq = true
r = r.substr(sub)
r = (r === "") ? r : valid(r)
ok = (r === "") || (eq && r === version) || (gtlt && gtlt(version, r))
if (!ok) break
}
if (ok) return true
}
return false
}
// return v1 > v2 ? 1 : -1
function compare (v1, v2) {
var g = gt(v1, v2)
return g === null ? 0 : g ? 1 : -1
}
function rcompare (v1, v2) {
return compare(v2, v1)
}
function lt (v1, v2) { return gt(v2, v1) }
function gte (v1, v2) { return !lt(v1, v2) }
function lte (v1, v2) { return !gt(v1, v2) }
function eq (v1, v2) { return gt(v1, v2) === null }
function neq (v1, v2) { return gt(v1, v2) !== null }
function cmp (v1, c, v2) {
switch (c) {
case ">": return gt(v1, v2)
case "<": return lt(v1, v2)
case ">=": return gte(v1, v2)
case "<=": return lte(v1, v2)
case "==": return eq(v1, v2)
case "!=": return neq(v1, v2)
case "===": return v1 === v2
case "!==": return v1 !== v2
default: throw new Error("Y U NO USE VALID COMPARATOR!? "+c)
}
}
// return v1 > v2
function num (v) {
return v === undefined ? -1 : parseInt((v||"0").replace(/[^0-9]+/g, ''), 10)
}
function gt (v1, v2) {
v1 = exports.parse(v1)
v2 = exports.parse(v2)
if (!v1 || !v2) return false
for (var i = 1; i < 5; i ++) {
v1[i] = num(v1[i])
v2[i] = num(v2[i])
if (v1[i] > v2[i]) return true
else if (v1[i] !== v2[i]) return false
}
// no tag is > than any tag, or use lexicographical order.
var tag1 = v1[5] || ""
, tag2 = v2[5] || ""
// kludge: null means they were equal. falsey, and detectable.
// embarrassingly overclever, though, I know.
return tag1 === tag2 ? null
: !tag1 ? true
: !tag2 ? false
: tag1 > tag2
}
function inc (version, release) {
version = exports.parse(version)
if (!version) return null
var parsedIndexLookup =
{ 'major': 1
, 'minor': 2
, 'patch': 3
, 'build': 4 }
var incIndex = parsedIndexLookup[release]
if (incIndex === undefined) return null
var current = num(version[incIndex])
version[incIndex] = current === -1 ? 1 : current + 1
for (var i = incIndex + 1; i < 5; i ++) {
if (num(version[i]) !== -1) version[i] = "0"
}
if (version[4]) version[4] = "-" + version[4]
version[5] = ""
return stringify(version)
}
})(typeof exports === "object" ? exports : semver = {})
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment