Skip to content

Instantly share code, notes, and snippets.

@jonvuri
Last active February 25, 2017 16:09
Show Gist options
  • Save jonvuri/f047455934cbb820d74752ca9e9e0f78 to your computer and use it in GitHub Desktop.
Save jonvuri/f047455934cbb820d74752ca9e9e0f78 to your computer and use it in GitHub Desktop.
{ Error: spawn flow ENOENT
at exports._errnoException (util.js:1026:11)
at Process.ChildProcess._handle.onexit (internal/child_process.js:193:32)
at onErrorNT (internal/child_process.js:359:16)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
code: 'ENOENT',
errno: 'ENOENT',
syscall: 'spawn flow',
path: 'flow',
spawnargs: [ 'version', '--json' ],
cmd: 'flow version --json' }
bject {maxBuffer: 104857600, cwd: "C:\dev\new-dubtrack", env: Object}
cwd
:
"C:\dev\new-dubtrack"
env
:
Object
ALLUSERSPROFILE
:
"C:\ProgramData"
APPDATA
:
"C:\Users\jraja\AppData\Roaming"
ATOM_HOME
:
"C:\Users\jraja\.atom"
ChocolateyInstall
:
"C:\ProgramData\chocolatey"
ChocolateyLastPathUpdate
:
"Thu Sep 22 09:30:14 2016"
ComSpec
:
"C:\WINDOWS\system32\cmd.exe"
CommonProgramFiles
:
"C:\Program Files (x86)\Common Files"
CommonProgramFiles(x86)
:
"C:\Program Files (x86)\Common Files"
CommonProgramW6432
:
"C:\Program Files\Common Files"
FPS_BROWSER_APP_PROFILE_STRING
:
"Internet Explorer"
FPS_BROWSER_USER_PROFILE_STRING
:
"Default"
HOMEDRIVE
:
"C:"
HOMEPATH
:
"\Users\jraja"
LOCALAPPDATA
:
"C:\Users\jraja\AppData\Local"
NODE_ENV
:
"production"
NODE_PATH
:
"C:\Users\jraja\AppData\Local\atom\app-1.14.3\resources\app.asar\exports"
NSS_DEFAULT_DB_TYPE
:
"sql"
NUMBER_OF_PROCESSORS
:
"8"
OS
:
"Windows_NT"
PATHEXT
:
".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC"
PROCESSOR_ARCHITECTURE
:
"x86"
PROCESSOR_ARCHITEW6432
:
"AMD64"
PROCESSOR_IDENTIFIER
:
"Intel64 Family 6 Model 94 Stepping 3, GenuineIntel"
PROCESSOR_LEVEL
:
"6"
PROCESSOR_REVISION
:
"5e03"
PSModulePath
:
"C:\Program Files\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules"
PUBLIC
:
"C:\Users\Public"
Path
:
"C:\Program Files (x86)\Razer Chroma SDK\bin;C:\Program Files\Razer Chroma SDK\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Users\jraja\AppData\Local\Microsoft\WindowsApps;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\ProgramData\chocolatey\bin;C:\Program Files\Perforce\DVCS\;C:\Program Files\Git\cmd;C:\Program Files\nodejs\;C:\Users\jraja\AppData\Local\Microsoft\WindowsApps;C:\Users\jraja\AppData\Local\atom\bin;C:\Users\jraja\AppData\Roaming\npm;C:\Program Files (x86)\Microsoft VS Code\bin"
ProgramData
:
"C:\ProgramData"
ProgramFiles
:
"C:\Program Files (x86)"
ProgramFiles(x86)
:
"C:\Program Files (x86)"
ProgramW6432
:
"C:\Program Files"
SESSIONNAME
:
"Console"
SystemDrive
:
"C:"
SystemRoot
:
"C:\WINDOWS"
TEMP
:
"C:\Users\jraja\AppData\Local\Temp"
TMP
:
"C:\Users\jraja\AppData\Local\Temp"
USERNAME
:
"jraja"
USERPROFILE
:
"C:\Users\jraja"
windir
:
"C:\WINDOWS"
__proto__
:
Object
maxBuffer
:
104857600
const _process2 = _child_process.default.execFile('flow',
// Node embeds various properties like code/errno in the Error object.
(err, /* Error */stdoutBuf, stderrBuf) => {
const error = _util.inspect(err, {customInspect: false, colors: true, depth: null})
console.log( 'flow solo run', error, stdoutBuf.toString('utf8'), stderrBuf.toString('utf8') )
})
flow solo run { Error: spawn flow ENOENT
at exports._errnoException (util.js:1026:11)
at Process.ChildProcess._handle.onexit (internal/child_process.js:193:32)
at onErrorNT (internal/child_process.js:359:16)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
code: 'ENOENT',
errno: 'ENOENT',
syscall: 'spawn flow',
path: 'flow',
spawnargs: [],
cmd: 'flow' }
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.psTree = exports.getChildrenOfProcess = exports.getOriginalEnvironment = exports.checkOutput = exports.killUnixProcessTree = exports.ProcessExitError = exports.ProcessSystemError = exports.loggedCalls = undefined;
var _asyncToGenerator = _interopRequireDefault(require('async-to-generator'));
let _killProcess = (() => {
var _ref = (0, _asyncToGenerator.default)(function* (childProcess, killTree) {
childProcess.wasKilled = true;
if (!killTree) {
childProcess.kill();
return;
}
if (/^win/.test(process.platform)) {
yield killWindowsProcessTree(childProcess.pid);
} else {
yield killUnixProcessTree(childProcess);
}
});
return function _killProcess(_x, _x2) {
return _ref.apply(this, arguments);
};
})();
let killUnixProcessTree = exports.killUnixProcessTree = (() => {
var _ref2 = (0, _asyncToGenerator.default)(function* (childProcess) {
const descendants = yield getDescendantsOfProcess(childProcess.pid);
// Kill the processes, starting with those of greatest depth.
for (const info of descendants.reverse()) {
killPid(info.pid);
}
});
return function killUnixProcessTree(_x3) {
return _ref2.apply(this, arguments);
};
})();
/**
* Simple wrapper around asyncExecute that throws if the exitCode is non-zero.
*/
let checkOutput = exports.checkOutput = (() => {
var _ref3 = (0, _asyncToGenerator.default)(function* (command, args, options = {}) {
const result = yield asyncExecute((_nuclideUri || _load_nuclideUri()).default.expandHomeDir(command), args, options);
if (result.exitCode !== 0) {
const reason = result.exitCode != null ? `exitCode: ${result.exitCode}` : `error: ${(0, (_string || _load_string()).maybeToString)(result.errorMessage)}`;
throw new Error(`asyncExecute "${command}" failed with ${reason}, ` + `stderr: ${result.stderr}, stdout: ${result.stdout}.`);
}
return result;
});
return function checkOutput(_x4, _x5) {
return _ref3.apply(this, arguments);
};
})();
/**
* Run a command, accumulate the output. Errors are surfaced as stream errors and unsubscribing will
* kill the process.
*/
let getOriginalEnvironment = exports.getOriginalEnvironment = (() => {
var _ref4 = (0, _asyncToGenerator.default)(function* () {
yield loadedShellPromise;
if (cachedOriginalEnvironment != null) {
return cachedOriginalEnvironment;
}
const { NUCLIDE_ORIGINAL_ENV } = process.env;
if (NUCLIDE_ORIGINAL_ENV != null && NUCLIDE_ORIGINAL_ENV.trim() !== '') {
const envString = new Buffer(NUCLIDE_ORIGINAL_ENV, 'base64').toString();
cachedOriginalEnvironment = {};
for (const envVar of envString.split('\0')) {
// envVar should look like A=value_of_A
const equalIndex = envVar.indexOf('=');
if (equalIndex !== -1) {
cachedOriginalEnvironment[envVar.substring(0, equalIndex)] = envVar.substring(equalIndex + 1);
}
}
} else {
cachedOriginalEnvironment = process.env;
}
return cachedOriginalEnvironment;
});
return function getOriginalEnvironment() {
return _ref4.apply(this, arguments);
};
})();
// Returns a string suitable for including in displayed error messages.
let getChildrenOfProcess = exports.getChildrenOfProcess = (() => {
var _ref5 = (0, _asyncToGenerator.default)(function* (processId) {
const processes = yield psTree();
return processes.filter(function (processInfo) {
return processInfo.parentPid === processId;
});
});
return function getChildrenOfProcess(_x6) {
return _ref5.apply(this, arguments);
};
})();
/**
* Get a list of descendants, sorted by increasing depth (including the one with the provided pid).
*/
let getDescendantsOfProcess = (() => {
var _ref6 = (0, _asyncToGenerator.default)(function* (pid) {
const processes = yield psTree();
let rootProcessInfo;
const pidToChildren = new (_collection || _load_collection()).MultiMap();
processes.forEach(function (info) {
if (info.pid === pid) {
rootProcessInfo = info;
}
pidToChildren.add(info.parentPid, info);
});
const descendants = rootProcessInfo == null ? [] : [rootProcessInfo];
// Walk through the array, adding the children of the current element to the end. This
// breadth-first traversal means that the elements will be sorted by depth.
for (let i = 0; i < descendants.length; i++) {
const info = descendants[i];
const children = pidToChildren.get(info.pid);
descendants.push(...Array.from(children));
}
return descendants;
});
return function getDescendantsOfProcess(_x7) {
return _ref6.apply(this, arguments);
};
})();
let psTree = exports.psTree = (() => {
var _ref7 = (0, _asyncToGenerator.default)(function* () {
let psPromise;
const isWindows = isWindowsPlatform();
if (isWindows) {
// See also: https://github.com/nodejs/node-v0.x-archive/issues/2318
psPromise = checkOutput('wmic.exe', ['PROCESS', 'GET', 'ParentProcessId,ProcessId,Name']);
} else {
psPromise = checkOutput('ps', ['-A', '-o', 'ppid,pid,comm']);
}
const { stdout } = yield psPromise;
return parsePsOutput(stdout);
});
return function psTree() {
return _ref7.apply(this, arguments);
};
})();
exports.safeSpawn = safeSpawn;
exports.safeFork = safeFork;
exports.createArgsForScriptCommand = createArgsForScriptCommand;
exports.scriptSafeSpawn = scriptSafeSpawn;
exports.scriptSafeSpawnAndObserveOutput = scriptSafeSpawnAndObserveOutput;
exports.killProcess = killProcess;
exports.killPid = killPid;
exports.createProcessStream = createProcessStream;
exports.observeProcessExit = observeProcessExit;
exports.getOutputStream = getOutputStream;
exports.observeProcess = observeProcess;
exports.observeProcessRaw = observeProcessRaw;
exports.asyncExecute = asyncExecute;
exports.runCommand = runCommand;
exports.loadedShellEnvironment = loadedShellEnvironment;
exports.exitEventToMessage = exitEventToMessage;
exports.parsePsOutput = parsePsOutput;
var _child_process = _interopRequireDefault(require('child_process'));
var _collection;
function _load_collection() {
return _collection = require('./collection');
}
var _nuclideUri;
function _load_nuclideUri() {
return _nuclideUri = _interopRequireDefault(require('./nuclideUri'));
}
var _observable;
function _load_observable() {
return _observable = require('./observable');
}
var _stream;
function _load_stream() {
return _stream = require('./stream');
}
var _string;
function _load_string() {
return _string = require('./string');
}
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');
var _shellQuote;
function _load_shellQuote() {
return _shellQuote = require('shell-quote');
}
var _performanceNow;
function _load_performanceNow() {
return _performanceNow = _interopRequireDefault(require('./performanceNow'));
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Node crashes if we allow buffers that are too large.
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
*/
const DEFAULT_MAX_BUFFER = 100 * 1024 * 1024;
const MAX_LOGGED_CALLS = 100;
const PREVERVED_HISTORY_CALLS = 50;
const loggedCalls = exports.loggedCalls = [];
function logCall(duration, command, args) {
// Trim the history once in a while, to avoid doing expensive array
// manipulation all the time after we reached the end of the history
if (loggedCalls.length > MAX_LOGGED_CALLS) {
loggedCalls.splice(0, loggedCalls.length - PREVERVED_HISTORY_CALLS, { time: new Date(), duration: 0, command: '... history stripped ...' });
}
loggedCalls.push({
duration,
command: [command, ...args].join(' '),
time: new Date()
});
}
class ProcessSystemError extends Error {
constructor(opts) {
super(`"${opts.command}" failed with code ${opts.code}`);
this.name = 'ProcessSystemError';
this.command = opts.command;
this.args = opts.args;
this.options = opts.options;
this.code = opts.code;
this.originalError = opts.originalError;
}
}
exports.ProcessSystemError = ProcessSystemError;
class ProcessExitError extends Error {
constructor(opts) {
super(`"${opts.command}" failed with ${exitEventToMessage(opts.exitMessage)}\n\n${opts.stderr}`);
this.name = 'ProcessExitError';
this.command = opts.command;
this.args = opts.args;
this.options = opts.options;
this.exitMessage = opts.exitMessage;
this.code = opts.exitMessage.exitCode;
this.stdout = opts.stdout;
this.stderr = opts.stderr;
}
}
exports.ProcessExitError = ProcessExitError;
const STREAM_NAMES = ['stdin', 'stdout', 'stderr'];
function logError(...args) {
// Can't use nuclide-logging here to not cause cycle dependency.
// eslint-disable-next-line no-console
console.error(...args);
}
function log(...args) {
// Can't use nuclide-logging here to not cause cycle dependency.
// eslint-disable-next-line no-console
console.log(...args);
}
function monitorStreamErrors(process, command, args, options) {
STREAM_NAMES.forEach(streamName => {
// $FlowIssue
const stream = process[streamName];
if (stream == null) {
return;
}
stream.on('error', error => {
// This can happen without the full execution of the command to fail,
// but we want to learn about it.
logError(`stream error on stream ${streamName} with command:`, command, args, options, 'error:', error);
});
});
}
/**
* Basically like spawn/fork, except it handles and logs errors instead of
* crashing the process. This is much lower-level than asyncExecute. Unless
* you have a specific reason you should use asyncExecute instead.
*/
function safeSpawn(command, args = [], options = {}) {
return _makeChildProcess('spawn', command, args, options);
}
function safeFork(command, args = [], options = {}) {
return _makeChildProcess('fork', command, args, options);
}
/**
* Helper type/function to create child_process by spawning/forking the process.
*/
function _makeChildProcess(type = 'spawn', command, args = [], options = {}) {
const now = (0, (_performanceNow || _load_performanceNow()).default)();
const child = _child_process.default[type]((_nuclideUri || _load_nuclideUri()).default.expandHomeDir(command), args, prepareProcessOptions(options));
monitorStreamErrors(child, command, args, options);
child.on('error', error => {
logError('error with command:', command, args, options, 'error:', error);
});
if (!options || !options.dontLogInNuclide) {
child.on('close', () => {
logCall(Math.round((0, (_performanceNow || _load_performanceNow()).default)() - now), command, args);
});
}
writeToStdin(child, options);
return child;
}
/**
* Takes the command and args that you would normally pass to `spawn()` and returns `newArgs` such
* that you should call it with `spawn('script', newArgs)` to run the original command/args pair
* under `script`.
*/
function createArgsForScriptCommand(command, args = []) {
if (process.platform === 'darwin') {
// On OS X, script takes the program to run and its arguments as varargs at the end.
return ['-q', '/dev/null', command].concat(args);
} else {
// On Linux, script takes the command to run as the -c parameter.
const allArgs = [command].concat(args);
return ['-q', '/dev/null', '-c', (0, (_shellQuote || _load_shellQuote()).quote)(allArgs)];
}
}
/**
* Basically like safeSpawn, but runs the command with the `script` command.
* `script` ensures terminal-like environment and commands we run give colored output.
*/
function scriptSafeSpawn(command, args = [], options = {}) {
const newArgs = createArgsForScriptCommand(command, args);
return safeSpawn('script', newArgs, options);
}
/**
* Wraps scriptSafeSpawn with an Observable that lets you listen to the stdout and
* stderr of the spawned process.
*/
function scriptSafeSpawnAndObserveOutput(command, args = [], options = {}, killTreeOnComplete = false) {
return _rxjsBundlesRxMinJs.Observable.create(observer => {
let childProcess = scriptSafeSpawn(command, args, options);
childProcess.stdout.on('data', data => {
observer.next({ stdout: data.toString() });
});
let stderr = '';
childProcess.stderr.on('data', data => {
stderr += data;
observer.next({ stderr: data.toString() });
});
childProcess.on('exit', exitCode => {
if (exitCode !== 0) {
observer.error(stderr);
} else {
observer.complete();
}
childProcess = null;
});
return () => {
if (childProcess) {
killProcess(childProcess, killTreeOnComplete);
}
};
});
}
/**
* Creates an observable with the following properties:
*
* 1. It contains a process that's created using the provided factory when you subscribe.
* 2. It doesn't complete until the process exits (or errors).
* 3. The process is killed when you unsubscribe.
*
* This means that a single observable instance can be used to spawn multiple processes. Indeed, if
* you subscribe multiple times, multiple processes *will* be spawned.
*
* IMPORTANT: The exit event does NOT mean that all stdout and stderr events have been received.
*/
function _createProcessStream(createProcess, throwOnError, killTreeOnComplete) {
return _rxjsBundlesRxMinJs.Observable.defer(() => {
const process = createProcess();
let finished = false;
// If the process returned by `createProcess()` was not created by it (or at least in the same
// tick), it's possible that its error event has already been dispatched. This is a bug that
// needs to be fixed in the caller. Generally, that would just mean refactoring your code to
// create the process in the function you pass. If for some reason, this is absolutely not
// possible, you need to make sure that the process is passed here immediately after it's
// created (i.e. before an ENOENT error event would be dispatched). Don't refactor your code to
// avoid this function; you'll have the same bug, you just won't be notified! XD
if (!(process.exitCode == null && !process.killed)) {
throw new Error('Process already exited. (This indicates a race condition in Nuclide.)');
}
const errors = _rxjsBundlesRxMinJs.Observable.fromEvent(process, 'error');
const exit = observeProcessExitMessage(process);
return _rxjsBundlesRxMinJs.Observable.of(process)
// Don't complete until we say so!
.merge(_rxjsBundlesRxMinJs.Observable.never())
// Get the errors.
.takeUntil(throwOnError ? errors.flatMap(_rxjsBundlesRxMinJs.Observable.throw) : errors).takeUntil(exit).do({
error: () => {
finished = true;
},
complete: () => {
finished = true;
}
}).finally(() => {
if (!process.wasKilled && !finished) {
killProcess(process, killTreeOnComplete);
}
});
});
}
function killProcess(childProcess, killTree) {
log(`Ending process stream. Killing process ${childProcess.pid}`);
_killProcess(childProcess, killTree).then(() => {}, error => {
logError(`Killing process ${childProcess.pid} failed`, error);
});
}
function killWindowsProcessTree(pid) {
return new Promise((resolve, reject) => {
_child_process.default.exec(`taskkill /pid ${pid} /T /F`, error => {
if (error == null) {
reject(error);
} else {
resolve();
}
});
});
}
function killPid(pid) {
try {
process.kill(pid);
} catch (err) {
if (err.code !== 'ESRCH') {
throw err;
}
}
}
function createProcessStream(createProcess, killTreeOnComplete = false) {
return _createProcessStream(createProcess, true, killTreeOnComplete);
}
function observeProcessExitMessage(process) {
return _rxjsBundlesRxMinJs.Observable.fromEvent(process, 'exit', (exitCode, signal) => ({ kind: 'exit', exitCode, signal }))
// An exit signal from SIGUSR1 doesn't actually exit the process, so skip that.
.filter(message => message.signal !== 'SIGUSR1').take(1);
}
/**
* Observe the stdout, stderr and exit code of a process.
* stdout and stderr are split by newlines.
*/
function observeProcessExit(createProcess, killTreeOnComplete = false) {
return _createProcessStream(createProcess, false, killTreeOnComplete).flatMap(observeProcessExitMessage);
}
function getOutputStream(process, killTreeOnComplete = false, splitByLines = true) {
const chunk = splitByLines ? (_observable || _load_observable()).splitStream : x => x;
return _rxjsBundlesRxMinJs.Observable.defer(() => {
// We need to start listening for the exit event immediately, but defer emitting it until the
// (buffered) output streams end.
const exit = observeProcessExit(() => process, killTreeOnComplete).publishReplay();
const exitSub = exit.connect();
const error = _rxjsBundlesRxMinJs.Observable.fromEvent(process, 'error').map(errorObj => ({ kind: 'error', error: errorObj }));
// It's possible for stdout and stderr to remain open (even indefinitely) after the exit event.
// This utility, however, treats the exit event as stream-ending, which helps us to avoid easy
// bugs. We give a short (100ms) timeout for the stdout and stderr streams to close.
const close = exit.delay(100);
const stdout = chunk((0, (_stream || _load_stream()).observeStream)(process.stdout).takeUntil(close)).map(data => ({ kind: 'stdout', data }));
const stderr = chunk((0, (_stream || _load_stream()).observeStream)(process.stderr).takeUntil(close)).map(data => ({ kind: 'stderr', data }));
return (0, (_observable || _load_observable()).takeWhileInclusive)(_rxjsBundlesRxMinJs.Observable.merge(_rxjsBundlesRxMinJs.Observable.merge(stdout, stderr).concat(exit), error), event => event.kind !== 'error' && event.kind !== 'exit').finally(() => {
exitSub.unsubscribe();
});
});
}
/**
* Observe the stdout, stderr and exit code of a process.
*/
function observeProcess(createProcess, killTreeOnComplete = false) {
return _createProcessStream(createProcess, false, killTreeOnComplete).flatMap(getOutputStream);
}
/**
* Observe the stdout, stderr and exit code of a process.
*/
function observeProcessRaw(createProcess, killTreeOnComplete = false) {
return _createProcessStream(createProcess, false, killTreeOnComplete).flatMap(process => getOutputStream(process, false, false));
}
let FB_INCLUDE_PATHS;
try {
// $FlowFB
FB_INCLUDE_PATHS = require('./fb-config').FB_INCLUDE_PATHS;
} catch (error) {
FB_INCLUDE_PATHS = [];
}
let DEFAULT_PATH_INCLUDE = [...FB_INCLUDE_PATHS, '/usr/local/bin'];
function prepareProcessOptions(options) {
return Object.assign({}, options, {
env: preparePathEnvironment(options.env)
});
}
function preparePathEnvironment(env) {
const originalEnv = Object.assign({}, process.env, env);
if (isWindowsPlatform()) {
return originalEnv;
}
const existingPath = originalEnv.PATH || '';
return Object.assign({}, originalEnv, {
PATH: (_nuclideUri || _load_nuclideUri()).default.joinPathList([existingPath, ...DEFAULT_PATH_INCLUDE])
});
}
/**
* Returns a promise that resolves to the result of executing a process.
*
* @param command The command to execute.
* @param args The arguments to pass to the command.
* @param options Options for changing how to run the command.
* Supports the options listed here: http://nodejs.org/api/child_process.html
* in addition to the custom options listed in AsyncExecuteOptions.
*/
function asyncExecute(command, args, options = {}) {
const now = (0, (_performanceNow || _load_performanceNow()).default)();
return new Promise((resolve, reject) => {
const process = _child_process.default.execFile((_nuclideUri || _load_nuclideUri()).default.expandHomeDir(command), args, prepareProcessOptions(Object.assign({
maxBuffer: DEFAULT_MAX_BUFFER
}, options)),
// Node embeds various properties like code/errno in the Error object.
(err, /* Error */stdoutBuf, stderrBuf) => {
const error = require('util').inspect(err, {customInspect: false, colors: true, depth: null})
console.log( 'asyncExec failed', error, command, args, options )
console.log( error )
console.log( 'path', process.env.PATH )
if (!options || !options.dontLogInNuclide) {
logCall(Math.round((0, (_performanceNow || _load_performanceNow()).default)() - now), command, args);
}
const stdout = stdoutBuf.toString('utf8');
const stderr = stderrBuf.toString('utf8');
if (err == null) {
resolve({
stdout,
stderr,
exitCode: 0
});
} else if (Number.isInteger(err.code)) {
resolve({
stdout,
stderr,
exitCode: err.code
});
} else {
resolve({
stdout,
stderr,
errorCode: err.errno || 'EUNKNOWN',
errorMessage: err.message
});
}
});
writeToStdin(process, options);
});
}
function writeToStdin(childProcess, options) {
if (typeof options.stdin === 'string' && childProcess.stdin != null) {
// Note that the Node docs have this scary warning about stdin.end() on
// http://nodejs.org/api/child_process.html#child_process_child_stdin:
//
// "A Writable Stream that represents the child process's stdin. Closing
// this stream via end() often causes the child process to terminate."
//
// In practice, this has not appeared to cause any issues thus far.
childProcess.stdin.write(options.stdin);
childProcess.stdin.end();
}
}function runCommand(command, args = [], options = {}, killTreeOnComplete = false) {
const seed = {
error: null,
stdout: [],
stderr: [],
exitMessage: null
};
return observeProcess(() => safeSpawn(command, args, options), killTreeOnComplete).reduce((acc, event) => {
switch (event.kind) {
case 'stdout':
return Object.assign({}, acc, { stdout: acc.stdout.concat(event.data) });
case 'stderr':
return Object.assign({}, acc, { stderr: acc.stderr.concat(event.data) });
case 'error':
return Object.assign({}, acc, { error: event.error });
case 'exit':
return Object.assign({}, acc, { exitMessage: event });
}
return acc;
}, seed).map(acc => {
if (acc.error != null) {
throw new ProcessSystemError({
command,
args,
options,
code: acc.error.code, // Alias of errno
originalError: acc.error });
}
const stdout = acc.stdout.join('');
if (acc.exitMessage != null && acc.exitMessage.exitCode !== 0) {
throw new ProcessExitError({
command,
args,
options,
exitMessage: acc.exitMessage,
stdout,
stderr: acc.stderr.join('')
});
}
return stdout;
});
}
// If provided, read the original environment from NUCLIDE_ORIGINAL_ENV.
// This should contain the base64-encoded output of `env -0`.
let cachedOriginalEnvironment = null;
let loadedShellResolve;
const loadedShellPromise = new Promise(resolve => {
loadedShellResolve = resolve;
}).then(() => {
// No need to include default paths now that the environment is loaded.
DEFAULT_PATH_INCLUDE = [];
cachedOriginalEnvironment = null;
});
if (!loadedShellResolve) {
throw new Error('Invariant violation: "loadedShellResolve"');
}
if (typeof atom === 'undefined' || atom.inSpecMode()) {
// This doesn't apply server-side or in tests, so just immediately resolve.
loadedShellResolve();
}
function loadedShellEnvironment() {
loadedShellResolve();
}
function exitEventToMessage(event) {
if (event.exitCode != null) {
return `exit code ${event.exitCode}`;
} else {
if (!(event.signal != null)) {
throw new Error('Invariant violation: "event.signal != null"');
}
return `signal ${event.signal}`;
}
}
function isWindowsPlatform() {
return (/^win/.test(process.platform)
);
}
function parsePsOutput(psOutput) {
// Remove the first header line.
const lines = psOutput.split(/\n|\r\n/).slice(1);
return lines.map(line => {
const columns = line.trim().split(/\s+/);
const [parentPid, pid] = columns;
const command = columns.slice(2).join(' ');
return {
command,
parentPid: parseInt(parentPid, 10),
pid: parseInt(pid, 10)
};
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment