-
Notifications
You must be signed in to change notification settings - Fork 13
/
index.js
146 lines (135 loc) · 4.02 KB
/
index.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
145
146
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()
})
}