diff options
Diffstat (limited to 'deps/npm/node_modules/npm-lifecycle/index.js')
-rw-r--r-- | deps/npm/node_modules/npm-lifecycle/index.js | 90 |
1 files changed, 58 insertions, 32 deletions
diff --git a/deps/npm/node_modules/npm-lifecycle/index.js b/deps/npm/node_modules/npm-lifecycle/index.js index 4eb83255a9..0972870b18 100644 --- a/deps/npm/node_modules/npm-lifecycle/index.js +++ b/deps/npm/node_modules/npm-lifecycle/index.js @@ -4,6 +4,9 @@ exports = module.exports = lifecycle exports.makeEnv = makeEnv exports._incorrectWorkingDirectory = _incorrectWorkingDirectory +// for testing +const platform = process.env.__TESTING_FAKE_PLATFORM__ || process.platform +const isWindows = platform === 'win32' const spawn = require('./lib/spawn') const path = require('path') const Stream = require('stream').Stream @@ -18,17 +21,28 @@ const resolveFrom = require('resolve-from') const DEFAULT_NODE_GYP_PATH = resolveFrom(__dirname, 'node-gyp/bin/node-gyp') const hookStatCache = new Map() -let PATH = 'PATH' - -// windows calls it's path 'Path' usually, but this is not guaranteed. -if (process.platform === 'win32') { - PATH = 'Path' - Object.keys(process.env).forEach(function (e) { - if (e.match(/^PATH$/i)) { - PATH = e - } - }) +let PATH = isWindows ? 'Path' : 'PATH' +exports._pathEnvName = PATH +const delimiter = path.delimiter + +// windows calls its path 'Path' usually, but this is not guaranteed. +// merge them all together in the order they appear in the object. +const mergePath = env => + Object.keys(env).filter(p => /^path$/i.test(p) && env[p]) + .map(p => env[p].split(delimiter)) + .reduce((set, p) => set.concat(p.filter(p => !set.includes(p))), []) + .join(delimiter) +exports._mergePath = mergePath + +const setPathEnv = (env, path) => { + // first ensure that the canonical value is set. + env[PATH] = path + // also set any other case values, because windows. + Object.keys(env) + .filter(p => p !== PATH && /^path$/i.test(p)) + .forEach(p => { env[p] = path }) } +exports._setPathEnv = setPathEnv function logid (pkg, stage) { return pkg._id + '~' + stage + ':' @@ -120,8 +134,10 @@ function lifecycle_ (pkg, stage, wd, opts, env, cb) { pathArr.push(path.dirname(process.execPath)) } - if (env[PATH]) pathArr.push(env[PATH]) - env[PATH] = pathArr.join(process.platform === 'win32' ? ';' : ':') + const existingPath = mergePath(env) + if (existingPath) pathArr.push(existingPath) + const envPath = pathArr.join(isWindows ? ';' : ':') + setPathEnv(env, envPath) var packageLifecycle = pkg.scripts && pkg.scripts.hasOwnProperty(stage) @@ -164,10 +180,9 @@ function shouldPrependCurrentNodeDirToPATH (opts) { var isDifferentNodeInPath - var isWindows = process.platform === 'win32' var foundExecPath try { - foundExecPath = which.sync(path.basename(process.execPath), {pathExt: isWindows ? ';' : ':'}) + foundExecPath = which.sync(path.basename(process.execPath), { pathExt: isWindows ? ';' : ':' }) // Apply `fs.realpath()` here to avoid false positives when `node` is a symlinked executable. isDifferentNodeInPath = fs.realpathSync(process.execPath).toUpperCase() !== fs.realpathSync(foundExecPath).toUpperCase() @@ -242,7 +257,7 @@ function runCmd (note, cmd, pkg, env, stage, wd, opts, cb) { } opts.log.verbose('lifecycle', logid(pkg, stage), 'unsafe-perm in lifecycle', unsafe) - if (process.platform === 'win32') { + if (isWindows) { unsafe = true } @@ -255,14 +270,8 @@ function runCmd (note, cmd, pkg, env, stage, wd, opts, cb) { } } -function runCmd_ (cmd, pkg, env, wd, opts, stage, unsafe, uid, gid, cb_) { - function cb (er) { - cb_.apply(null, arguments) - opts.log.resume() - process.nextTick(dequeue) - } - - var conf = { +const getSpawnArgs = ({ cmd, wd, opts, uid, gid, unsafe, env }) => { + const conf = { cwd: wd, env: env, stdio: opts.stdio || [ 0, 1, 2 ] @@ -273,24 +282,40 @@ function runCmd_ (cmd, pkg, env, wd, opts, stage, unsafe, uid, gid, cb_) { conf.gid = gid ^ 0 } - var sh = 'sh' - var shFlag = '-c' - - var customShell = opts.scriptShell + const customShell = opts.scriptShell + let sh = 'sh' + let shFlag = '-c' if (customShell) { sh = customShell - } else if (process.platform === 'win32') { + } else if (isWindows || opts._TESTING_FAKE_WINDOWS_) { sh = process.env.comspec || 'cmd' - shFlag = '/d /s /c' - conf.windowsVerbatimArguments = true + // '/d /s /c' is used only for cmd.exe. + if (/^(?:.*\\)?cmd(?:\.exe)?$/i.test(sh)) { + shFlag = '/d /s /c' + conf.windowsVerbatimArguments = true + } } + return [sh, [shFlag, cmd], conf] +} + +exports._getSpawnArgs = getSpawnArgs + +function runCmd_ (cmd, pkg, env, wd, opts, stage, unsafe, uid, gid, cb_) { + function cb (er) { + cb_.apply(null, arguments) + opts.log.resume() + process.nextTick(dequeue) + } + + const [sh, args, conf] = getSpawnArgs({ cmd, wd, opts, uid, gid, unsafe, env }) + opts.log.verbose('lifecycle', logid(pkg, stage), 'PATH:', env[PATH]) opts.log.verbose('lifecycle', logid(pkg, stage), 'CWD:', wd) - opts.log.silly('lifecycle', logid(pkg, stage), 'Args:', [shFlag, cmd]) + opts.log.silly('lifecycle', logid(pkg, stage), 'Args:', args) - var proc = spawn(sh, [shFlag, cmd], conf, opts.log) + var proc = spawn(sh, args, conf, opts.log) proc.on('error', procError) proc.on('close', function (code, signal) { @@ -333,6 +358,7 @@ function runCmd_ (cmd, pkg, env, wd, opts, stage, unsafe, uid, gid, cb_) { process.removeListener('SIGTERM', procKill) process.removeListener('SIGTERM', procInterupt) process.removeListener('SIGINT', procKill) + process.removeListener('SIGINT', procInterupt) return cb(er) } function procKill () { |