mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
4.0 KiB
146 lines
4.0 KiB
var fs = require("fs")
|
|
var path = require("path")
|
|
var log = require("npmlog")
|
|
var semver = require("semver")
|
|
|
|
exports.checkEngine = checkEngine
|
|
function checkEngine (target, npmVer, nodeVer, force, strict, cb) {
|
|
var nodev = force ? null : nodeVer
|
|
, strict = strict || target.engineStrict
|
|
, eng = target.engines
|
|
if (!eng) return cb()
|
|
if (nodev && eng.node && !semver.satisfies(nodev, eng.node)
|
|
|| eng.npm && !semver.satisfies(npmVer, eng.npm)) {
|
|
|
|
if (strict) {
|
|
var er = new Error("Unsupported")
|
|
er.code = "ENOTSUP"
|
|
er.required = eng
|
|
er.pkgid = target._id
|
|
return cb(er)
|
|
} else {
|
|
log.warn( "engine", "%s: wanted: %j (current: %j)"
|
|
, target._id, eng, {node: nodev, npm: npmVer} )
|
|
}
|
|
}
|
|
return cb()
|
|
}
|
|
|
|
exports.checkPlatform = checkPlatform
|
|
function checkPlatform (target, force, cb) {
|
|
var platform = process.platform
|
|
, arch = process.arch
|
|
, osOk = true
|
|
, cpuOk = true
|
|
|
|
if (force) {
|
|
return cb()
|
|
}
|
|
|
|
if (target.os) {
|
|
osOk = checkList(platform, target.os)
|
|
}
|
|
if (target.cpu) {
|
|
cpuOk = checkList(arch, target.cpu)
|
|
}
|
|
if (!osOk || !cpuOk) {
|
|
var er = new Error("Unsupported")
|
|
er.code = "EBADPLATFORM"
|
|
er.os = target.os || ['any']
|
|
er.cpu = target.cpu || ['any']
|
|
er.pkgid = target._id
|
|
return cb(er)
|
|
}
|
|
return cb()
|
|
}
|
|
|
|
function checkList (value, list) {
|
|
var tmp
|
|
, match = false
|
|
, blc = 0
|
|
if (typeof list === "string") {
|
|
list = [list]
|
|
}
|
|
if (list.length === 1 && list[0] === "any") {
|
|
return true
|
|
}
|
|
for (var i = 0; i < list.length; ++i) {
|
|
tmp = list[i]
|
|
if (tmp[0] === '!') {
|
|
tmp = tmp.slice(1)
|
|
if (tmp === value) {
|
|
return false
|
|
}
|
|
++blc
|
|
} else {
|
|
match = match || tmp === value
|
|
}
|
|
}
|
|
return match || blc === list.length
|
|
}
|
|
|
|
exports.checkCycle = checkCycle
|
|
function checkCycle (target, ancestors, cb) {
|
|
// there are some very rare and pathological edge-cases where
|
|
// a cycle can cause npm to try to install a never-ending tree
|
|
// of stuff.
|
|
// Simplest:
|
|
//
|
|
// A -> B -> A' -> B' -> A -> B -> A' -> B' -> A -> ...
|
|
//
|
|
// Solution: Simply flat-out refuse to install any name@version
|
|
// that is already in the prototype tree of the ancestors object.
|
|
// A more correct, but more complex, solution would be to symlink
|
|
// the deeper thing into the new location.
|
|
// Will do that if anyone whines about this irl.
|
|
//
|
|
// Note: `npm install foo` inside of the `foo` package will abort
|
|
// earlier if `--force` is not set. However, if it IS set, then
|
|
// we need to still fail here, but just skip the first level. Of
|
|
// course, it'll still fail eventually if it's a true cycle, and
|
|
// leave things in an undefined state, but that's what is to be
|
|
// expected when `--force` is used. That is why getPrototypeOf
|
|
// is used *twice* here: to skip the first level of repetition.
|
|
|
|
var p = Object.getPrototypeOf(Object.getPrototypeOf(ancestors))
|
|
, name = target.name
|
|
, version = target.version
|
|
while (p && p !== Object.prototype && p[name] !== version) {
|
|
p = Object.getPrototypeOf(p)
|
|
}
|
|
if (p[name] !== version) return cb()
|
|
|
|
var er = new Error("Unresolvable cycle detected")
|
|
var tree = [target._id, JSON.parse(JSON.stringify(ancestors))]
|
|
, t = Object.getPrototypeOf(ancestors)
|
|
while (t && t !== Object.prototype) {
|
|
if (t === p) t.THIS_IS_P = true
|
|
tree.push(JSON.parse(JSON.stringify(t)))
|
|
t = Object.getPrototypeOf(t)
|
|
}
|
|
log.verbose("unresolvable dependency tree", tree)
|
|
er.pkgid = target._id
|
|
er.code = "ECYCLE"
|
|
return cb(er)
|
|
}
|
|
|
|
exports.checkGit = checkGit
|
|
function checkGit (folder, cb) {
|
|
// if it's a git repo then don't touch it!
|
|
fs.lstat(folder, function (er, s) {
|
|
if (er || !s.isDirectory()) return cb()
|
|
else checkGit_(folder, cb)
|
|
})
|
|
}
|
|
|
|
function checkGit_ (folder, cb) {
|
|
fs.stat(path.resolve(folder, ".git"), function (er, s) {
|
|
if (!er && s.isDirectory()) {
|
|
var e = new Error("Appears to be a git repo or submodule.")
|
|
e.path = folder
|
|
e.code = "EISGIT"
|
|
return cb(e)
|
|
}
|
|
cb()
|
|
})
|
|
}
|
|
|