]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/lib/utils/lifecycle.js
Adding integrated tile server
[simantics/district.git] / org.simantics.maps.server / node / node-v4.8.0-win-x64 / node_modules / npm / lib / utils / lifecycle.js
1 exports = module.exports = lifecycle
2 exports.cmd = cmd
3 exports.makeEnv = makeEnv
4
5 var log = require("npmlog")
6 var spawn = require("./spawn")
7 var npm = require("../npm.js")
8 var path = require("path")
9 var fs = require("graceful-fs")
10 var chain = require("slide").chain
11 var Stream = require("stream").Stream
12 var PATH = "PATH"
13 var uidNumber = require("uid-number")
14 var umask = require("./umask")
15
16 // windows calls it's path "Path" usually, but this is not guaranteed.
17 if (process.platform === "win32") {
18   PATH = "Path"
19   Object.keys(process.env).forEach(function (e) {
20     if (e.match(/^PATH$/i)) {
21       PATH = e
22     }
23   })
24 }
25
26 function lifecycle (pkg, stage, wd, unsafe, failOk, cb) {
27   if (typeof cb !== "function") cb = failOk, failOk = false
28   if (typeof cb !== "function") cb = unsafe, unsafe = false
29   if (typeof cb !== "function") cb = wd, wd = null
30
31   while (pkg && pkg._data) pkg = pkg._data
32   if (!pkg) return cb(new Error("Invalid package data"))
33
34   log.info(stage, pkg._id)
35   if (!pkg.scripts || npm.config.get('ignore-scripts')) pkg.scripts = {}
36
37   validWd(wd || path.resolve(npm.dir, pkg.name), function (er, wd) {
38     if (er) return cb(er)
39
40     unsafe = unsafe || npm.config.get("unsafe-perm")
41
42     if ((wd.indexOf(npm.dir) !== 0 ||
43           wd.indexOf(pkg.name) !== wd.length - pkg.name.length) &&
44         !unsafe && pkg.scripts[stage]) {
45       log.warn( "cannot run in wd", "%s %s (wd=%s)"
46               , pkg._id, pkg.scripts[stage], wd)
47       return cb()
48     }
49
50     // set the env variables, then run scripts as a child process.
51     var env = makeEnv(pkg)
52     env.npm_lifecycle_event = stage
53     env.npm_node_execpath = env.NODE = env.NODE || process.execPath
54     env.npm_execpath = require.main.filename
55
56     // "nobody" typically doesn't have permission to write to /tmp
57     // even if it's never used, sh freaks out.
58     if (!npm.config.get("unsafe-perm")) env.TMPDIR = wd
59
60     lifecycle_(pkg, stage, wd, env, unsafe, failOk, cb)
61   })
62 }
63
64 function checkForLink (pkg, cb) {
65   var f = path.join(npm.dir, pkg.name)
66   fs.lstat(f, function (er, s) {
67     cb(null, !(er || !s.isSymbolicLink()))
68   })
69 }
70
71 function lifecycle_ (pkg, stage, wd, env, unsafe, failOk, cb) {
72   var pathArr = []
73     , p = wd.split("node_modules")
74     , acc = path.resolve(p.shift())
75
76   p.forEach(function (pp) {
77     pathArr.unshift(path.join(acc, "node_modules", ".bin"))
78     acc = path.join(acc, "node_modules", pp)
79   })
80   pathArr.unshift(path.join(acc, "node_modules", ".bin"))
81
82   // we also unshift the bundled node-gyp-bin folder so that
83   // the bundled one will be used for installing things.
84   pathArr.unshift(path.join(__dirname, "..", "..", "bin", "node-gyp-bin"))
85
86   // prefer current node interpreter in child scripts
87   pathArr.push(path.dirname(process.execPath))
88
89   if (env[PATH]) pathArr.push(env[PATH])
90   env[PATH] = pathArr.join(process.platform === "win32" ? ";" : ":")
91
92   var packageLifecycle = pkg.scripts && pkg.scripts.hasOwnProperty(stage)
93
94   if (packageLifecycle) {
95     // define this here so it's available to all scripts.
96     env.npm_lifecycle_script = pkg.scripts[stage]
97   }
98
99   function done (er) {
100     if (er) {
101       if (npm.config.get("force")) {
102         log.info("forced, continuing", er)
103         er = null
104       } else if (failOk) {
105         log.warn("continuing anyway", er.message)
106         er = null
107       }
108     }
109     cb(er)
110   }
111
112   chain
113     ( [ packageLifecycle && [runPackageLifecycle, pkg, env, wd, unsafe]
114       , [runHookLifecycle, pkg, env, wd, unsafe] ]
115     , done )
116 }
117
118 function validWd (d, cb) {
119   fs.stat(d, function (er, st) {
120     if (er || !st.isDirectory()) {
121       var p = path.dirname(d)
122       if (p === d) {
123         return cb(new Error("Could not find suitable wd"))
124       }
125       return validWd(p, cb)
126     }
127     return cb(null, d)
128   })
129 }
130
131 function runPackageLifecycle (pkg, env, wd, unsafe, cb) {
132   // run package lifecycle scripts in the package root, or the nearest parent.
133   var stage = env.npm_lifecycle_event
134     , cmd = env.npm_lifecycle_script
135
136   var note = "\n> " + pkg._id + " " + stage + " " + wd
137            + "\n> " + cmd + "\n"
138   runCmd(note, cmd, pkg, env, stage, wd, unsafe, cb)
139 }
140
141
142 var running = false
143 var queue = []
144 function dequeue() {
145   running = false
146   if (queue.length) {
147     var r = queue.shift()
148     runCmd.apply(null, r)
149   }
150 }
151
152 function runCmd (note, cmd, pkg, env, stage, wd, unsafe, cb) {
153   if (running) {
154     queue.push([note, cmd, pkg, env, stage, wd, unsafe, cb])
155     return
156   }
157
158   running = true
159   log.pause()
160   var user = unsafe ? null : npm.config.get("user")
161     , group = unsafe ? null : npm.config.get("group")
162
163   if (log.level !== 'silent') {
164     if (npm.spinner.int) {
165       npm.config.get("logstream").write("\r \r")
166     }
167     console.log(note)
168   }
169   log.verbose("unsafe-perm in lifecycle", unsafe)
170
171   if (process.platform === "win32") {
172     unsafe = true
173   }
174
175   if (unsafe) {
176     runCmd_(cmd, pkg, env, wd, stage, unsafe, 0, 0, cb)
177   } else {
178     uidNumber(user, group, function (er, uid, gid) {
179       runCmd_(cmd, pkg, env, wd, stage, unsafe, uid, gid, cb)
180     })
181   }
182 }
183
184 function runCmd_ (cmd, pkg, env, wd, stage, unsafe, uid, gid, cb_) {
185
186   function cb (er) {
187     cb_.apply(null, arguments)
188     log.resume()
189     process.nextTick(dequeue)
190   }
191
192   var conf = { cwd: wd
193              , env: env
194              , stdio: [ 0, 1, 2 ]
195              }
196
197   if (!unsafe) {
198     conf.uid = uid ^ 0
199     conf.gid = gid ^ 0
200   }
201
202   var sh = 'sh'
203   var shFlag = '-c'
204
205   if (process.platform === 'win32') {
206     sh = process.env.comspec || 'cmd'
207     shFlag = '/d /s /c'
208     conf.windowsVerbatimArguments = true
209   }
210
211   var proc = spawn(sh, [shFlag, cmd], conf)
212   proc.on("error", procError)
213   proc.on("close", function (code, signal) {
214     if (signal) {
215       process.kill(process.pid, signal);
216     } else if (code) {
217       var er = new Error("Exit status " + code)
218     }
219     procError(er)
220   })
221
222   function procError (er) {
223     if (er && !npm.ROLLBACK) {
224       log.info(pkg._id, "Failed to exec "+stage+" script")
225       er.message = pkg._id + " "
226                  + stage + ": `" + cmd +"`\n"
227                  + er.message
228       if (er.code !== "EPERM") {
229         er.code = "ELIFECYCLE"
230       }
231       er.pkgid = pkg._id
232       er.stage = stage
233       er.script = cmd
234       er.pkgname = pkg.name
235       return cb(er)
236     } else if (er) {
237       log.error(pkg._id+"."+stage, er)
238       log.error(pkg._id+"."+stage, "continuing anyway")
239       return cb()
240     }
241     cb(er)
242   }
243 }
244
245
246 function runHookLifecycle (pkg, env, wd, unsafe, cb) {
247   // check for a hook script, run if present.
248   var stage = env.npm_lifecycle_event
249     , hook = path.join(npm.dir, ".hooks", stage)
250     , user = unsafe ? null : npm.config.get("user")
251     , group = unsafe ? null : npm.config.get("group")
252     , cmd = hook
253
254   fs.stat(hook, function (er) {
255     if (er) return cb()
256     var note = "\n> " + pkg._id + " " + stage + " " + wd
257              + "\n> " + cmd
258     runCmd(note, hook, pkg, env, stage, wd, unsafe, cb)
259   })
260 }
261
262 function makeEnv (data, prefix, env) {
263   prefix = prefix || "npm_package_"
264   if (!env) {
265     env = {}
266     for (var i in process.env) if (!i.match(/^npm_/)) {
267       env[i] = process.env[i]
268     }
269
270     // npat asks for tap output
271     if (npm.config.get("npat")) env.TAP = 1
272
273     // express and others respect the NODE_ENV value.
274     if (npm.config.get("production")) env.NODE_ENV = "production"
275
276   } else if (!data.hasOwnProperty("_lifecycleEnv")) {
277     Object.defineProperty(data, "_lifecycleEnv",
278       { value : env
279       , enumerable : false
280       })
281   }
282
283   for (var i in data) if (i.charAt(0) !== "_") {
284     var envKey = (prefix+i).replace(/[^a-zA-Z0-9_]/g, '_')
285     if (i === "readme") {
286       continue
287     }
288     if (data[i] && typeof(data[i]) === "object") {
289       try {
290         // quick and dirty detection for cyclical structures
291         JSON.stringify(data[i])
292         makeEnv(data[i], envKey+"_", env)
293       } catch (ex) {
294         // usually these are package objects.
295         // just get the path and basic details.
296         var d = data[i]
297         makeEnv( { name: d.name, version: d.version, path:d.path }
298                , envKey+"_", env)
299       }
300     } else {
301       env[envKey] = String(data[i])
302       env[envKey] = -1 !== env[envKey].indexOf("\n")
303                   ? JSON.stringify(env[envKey])
304                   : env[envKey]
305     }
306
307   }
308
309   if (prefix !== "npm_package_") return env
310
311   prefix = "npm_config_"
312   var pkgConfig = {}
313     , keys = npm.config.keys
314     , pkgVerConfig = {}
315     , namePref = data.name + ":"
316     , verPref = data.name + "@" + data.version + ":"
317
318   keys.forEach(function (i) {
319     // in some rare cases (e.g. working with nerf darts), there are segmented
320     // "private" (underscore-prefixed) config names -- don't export
321     if (i.charAt(0) === '_' && i.indexOf('_' + namePref) !== 0 || i.match(/:_/)) {
322       return
323     }
324     var value = npm.config.get(i)
325     if (value instanceof Stream || Array.isArray(value)) return
326     if (i.match(/umask/)) value = umask.toString(value)
327     if (!value) value = ""
328     else if (typeof value === "number") value = "" + value
329     else if (typeof value !== "string") value = JSON.stringify(value)
330
331     value = -1 !== value.indexOf("\n")
332           ? JSON.stringify(value)
333           : value
334     i = i.replace(/^_+/, "")
335     if (i.indexOf(namePref) === 0) {
336       var k = i.substr(namePref.length).replace(/[^a-zA-Z0-9_]/g, "_")
337       pkgConfig[ k ] = value
338     } else if (i.indexOf(verPref) === 0) {
339       var k = i.substr(verPref.length).replace(/[^a-zA-Z0-9_]/g, "_")
340       pkgVerConfig[ k ] = value
341     }
342     var envKey = (prefix+i).replace(/[^a-zA-Z0-9_]/g, "_")
343     env[envKey] = value
344   })
345
346   prefix = "npm_package_config_"
347   ;[pkgConfig, pkgVerConfig].forEach(function (conf) {
348     for (var i in conf) {
349       var envKey = (prefix+i)
350       env[envKey] = conf[i]
351     }
352   })
353
354   return env
355 }
356
357 function cmd (stage) {
358   function CMD (args, cb) {
359     npm.commands["run-script"]([stage].concat(args), cb)
360   }
361   CMD.usage = "npm "+stage+" [-- <args>]"
362   var installedShallow = require("./completion/installed-shallow.js")
363   CMD.completion = function (opts, cb) {
364     installedShallow(opts, function (d) {
365       return d.scripts && d.scripts[stage]
366     }, cb)
367   }
368   return CMD
369 }