2 var path = require("path")
3 var log = require("npmlog")
4 var semver = require("semver")
6 exports.checkEngine = checkEngine
7 function checkEngine (target, npmVer, nodeVer, force, strict, cb) {
8 var nodev = force ? null : nodeVer
9 , strict = strict || target.engineStrict
10 , eng = target.engines
12 if (nodev && eng.node && !semver.satisfies(nodev, eng.node)
13 || eng.npm && !semver.satisfies(npmVer, eng.npm)) {
16 var er = new Error("Unsupported")
22 log.warn( "engine", "%s: wanted: %j (current: %j)"
23 , target._id, eng, {node: nodev, npm: npmVer} )
29 exports.checkPlatform = checkPlatform
30 function checkPlatform (target, force, cb) {
31 var platform = process.platform
41 osOk = checkList(platform, target.os)
44 cpuOk = checkList(arch, target.cpu)
46 if (!osOk || !cpuOk) {
47 var er = new Error("Unsupported")
48 er.code = "EBADPLATFORM"
49 er.os = target.os || ['any']
50 er.cpu = target.cpu || ['any']
57 function checkList (value, list) {
61 if (typeof list === "string") {
64 if (list.length === 1 && list[0] === "any") {
67 for (var i = 0; i < list.length; ++i) {
76 match = match || tmp === value
79 return match || blc === list.length
82 exports.checkCycle = checkCycle
83 function checkCycle (target, ancestors, cb) {
84 // there are some very rare and pathological edge-cases where
85 // a cycle can cause npm to try to install a never-ending tree
89 // A -> B -> A' -> B' -> A -> B -> A' -> B' -> A -> ...
91 // Solution: Simply flat-out refuse to install any name@version
92 // that is already in the prototype tree of the ancestors object.
93 // A more correct, but more complex, solution would be to symlink
94 // the deeper thing into the new location.
95 // Will do that if anyone whines about this irl.
97 // Note: `npm install foo` inside of the `foo` package will abort
98 // earlier if `--force` is not set. However, if it IS set, then
99 // we need to still fail here, but just skip the first level. Of
100 // course, it'll still fail eventually if it's a true cycle, and
101 // leave things in an undefined state, but that's what is to be
102 // expected when `--force` is used. That is why getPrototypeOf
103 // is used *twice* here: to skip the first level of repetition.
105 var p = Object.getPrototypeOf(Object.getPrototypeOf(ancestors))
107 , version = target.version
108 while (p && p !== Object.prototype && p[name] !== version) {
109 p = Object.getPrototypeOf(p)
111 if (p[name] !== version) return cb()
113 var er = new Error("Unresolvable cycle detected")
114 var tree = [target._id, JSON.parse(JSON.stringify(ancestors))]
115 , t = Object.getPrototypeOf(ancestors)
116 while (t && t !== Object.prototype) {
117 if (t === p) t.THIS_IS_P = true
118 tree.push(JSON.parse(JSON.stringify(t)))
119 t = Object.getPrototypeOf(t)
121 log.verbose("unresolvable dependency tree", tree)
122 er.pkgid = target._id
127 exports.checkGit = checkGit
128 function checkGit (folder, cb) {
129 // if it's a git repo then don't touch it!
130 fs.lstat(folder, function (er, s) {
131 if (er || !s.isDirectory()) return cb()
132 else checkGit_(folder, cb)
136 function checkGit_ (folder, cb) {
137 fs.stat(path.resolve(folder, ".git"), function (er, s) {
138 if (!er && s.isDirectory()) {
139 var e = new Error("Appears to be a git repo or submodule.")