diff options
Diffstat (limited to 'node_modules/shelljs/src/exec.js')
-rw-r--r-- | node_modules/shelljs/src/exec.js | 295 |
1 files changed, 0 insertions, 295 deletions
diff --git a/node_modules/shelljs/src/exec.js b/node_modules/shelljs/src/exec.js deleted file mode 100644 index 5d360e868..000000000 --- a/node_modules/shelljs/src/exec.js +++ /dev/null @@ -1,295 +0,0 @@ -var common = require('./common'); -var _tempDir = require('./tempdir'); -var _pwd = require('./pwd'); -var path = require('path'); -var fs = require('fs'); -var child = require('child_process'); - -var DEFAULT_MAXBUFFER_SIZE = 20 * 1024 * 1024; - -common.register('exec', _exec, { - unix: false, - canReceivePipe: true, - wrapOutput: false, -}); - -// Hack to run child_process.exec() synchronously (sync avoids callback hell) -// Uses a custom wait loop that checks for a flag file, created when the child process is done. -// (Can't do a wait loop that checks for internal Node variables/messages as -// Node is single-threaded; callbacks and other internal state changes are done in the -// event loop). -function execSync(cmd, opts, pipe) { - if (!common.config.execPath) { - common.error('Unable to find a path to the node binary. Please manually set config.execPath'); - } - - var tempDir = _tempDir(); - var stdoutFile = path.resolve(tempDir + '/' + common.randomFileName()); - var stderrFile = path.resolve(tempDir + '/' + common.randomFileName()); - var codeFile = path.resolve(tempDir + '/' + common.randomFileName()); - var scriptFile = path.resolve(tempDir + '/' + common.randomFileName()); - var sleepFile = path.resolve(tempDir + '/' + common.randomFileName()); - - opts = common.extend({ - silent: common.config.silent, - cwd: _pwd().toString(), - env: process.env, - maxBuffer: DEFAULT_MAXBUFFER_SIZE, - }, opts); - - var previousStdoutContent = ''; - var previousStderrContent = ''; - // Echoes stdout and stderr changes from running process, if not silent - function updateStream(streamFile) { - if (opts.silent || !fs.existsSync(streamFile)) { - return; - } - - var previousStreamContent; - var procStream; - if (streamFile === stdoutFile) { - previousStreamContent = previousStdoutContent; - procStream = process.stdout; - } else { // assume stderr - previousStreamContent = previousStderrContent; - procStream = process.stderr; - } - - var streamContent = fs.readFileSync(streamFile, 'utf8'); - // No changes since last time? - if (streamContent.length <= previousStreamContent.length) { - return; - } - - procStream.write(streamContent.substr(previousStreamContent.length)); - previousStreamContent = streamContent; - } - - if (fs.existsSync(scriptFile)) common.unlinkSync(scriptFile); - if (fs.existsSync(stdoutFile)) common.unlinkSync(stdoutFile); - if (fs.existsSync(stderrFile)) common.unlinkSync(stderrFile); - if (fs.existsSync(codeFile)) common.unlinkSync(codeFile); - - var execCommand = JSON.stringify(common.config.execPath) + ' ' + JSON.stringify(scriptFile); - var script; - - opts.cwd = path.resolve(opts.cwd); - var optString = JSON.stringify(opts); - - if (typeof child.execSync === 'function') { - script = [ - "var child = require('child_process')", - " , fs = require('fs');", - 'var childProcess = child.exec(' + JSON.stringify(cmd) + ', ' + optString + ', function(err) {', - ' var fname = ' + JSON.stringify(codeFile) + ';', - ' if (!err) {', - ' fs.writeFileSync(fname, "0");', - ' } else if (err.code === undefined) {', - ' fs.writeFileSync(fname, "1");', - ' } else {', - ' fs.writeFileSync(fname, err.code.toString());', - ' }', - '});', - 'var stdoutStream = fs.createWriteStream(' + JSON.stringify(stdoutFile) + ');', - 'var stderrStream = fs.createWriteStream(' + JSON.stringify(stderrFile) + ');', - 'childProcess.stdout.pipe(stdoutStream, {end: false});', - 'childProcess.stderr.pipe(stderrStream, {end: false});', - 'childProcess.stdout.pipe(process.stdout);', - 'childProcess.stderr.pipe(process.stderr);', - ].join('\n') + - (pipe ? '\nchildProcess.stdin.end(' + JSON.stringify(pipe) + ');\n' : '\n') + - [ - 'var stdoutEnded = false, stderrEnded = false;', - 'function tryClosingStdout(){ if(stdoutEnded){ stdoutStream.end(); } }', - 'function tryClosingStderr(){ if(stderrEnded){ stderrStream.end(); } }', - "childProcess.stdout.on('end', function(){ stdoutEnded = true; tryClosingStdout(); });", - "childProcess.stderr.on('end', function(){ stderrEnded = true; tryClosingStderr(); });", - ].join('\n'); - - fs.writeFileSync(scriptFile, script); - - if (opts.silent) { - opts.stdio = 'ignore'; - } else { - opts.stdio = [0, 1, 2]; - } - - // Welcome to the future - try { - child.execSync(execCommand, opts); - } catch (e) { - // Clean up immediately if we have an exception - try { common.unlinkSync(scriptFile); } catch (e2) {} - try { common.unlinkSync(stdoutFile); } catch (e2) {} - try { common.unlinkSync(stderrFile); } catch (e2) {} - try { common.unlinkSync(codeFile); } catch (e2) {} - throw e; - } - } else { - cmd += ' > ' + stdoutFile + ' 2> ' + stderrFile; // works on both win/unix - - script = [ - "var child = require('child_process')", - " , fs = require('fs');", - 'var childProcess = child.exec(' + JSON.stringify(cmd) + ', ' + optString + ', function(err) {', - ' var fname = ' + JSON.stringify(codeFile) + ';', - ' if (!err) {', - ' fs.writeFileSync(fname, "0");', - ' } else if (err.code === undefined) {', - ' fs.writeFileSync(fname, "1");', - ' } else {', - ' fs.writeFileSync(fname, err.code.toString());', - ' }', - '});', - ].join('\n') + - (pipe ? '\nchildProcess.stdin.end(' + JSON.stringify(pipe) + ');\n' : '\n'); - - fs.writeFileSync(scriptFile, script); - - child.exec(execCommand, opts); - - // The wait loop - // sleepFile is used as a dummy I/O op to mitigate unnecessary CPU usage - // (tried many I/O sync ops, writeFileSync() seems to be only one that is effective in reducing - // CPU usage, though apparently not so much on Windows) - while (!fs.existsSync(codeFile)) { updateStream(stdoutFile); fs.writeFileSync(sleepFile, 'a'); } - while (!fs.existsSync(stdoutFile)) { updateStream(stdoutFile); fs.writeFileSync(sleepFile, 'a'); } - while (!fs.existsSync(stderrFile)) { updateStream(stderrFile); fs.writeFileSync(sleepFile, 'a'); } - try { common.unlinkSync(sleepFile); } catch (e) {} - } - - // At this point codeFile exists, but it's not necessarily flushed yet. - // Keep reading it until it is. - var code = parseInt('', 10); - while (isNaN(code)) { - code = parseInt(fs.readFileSync(codeFile, 'utf8'), 10); - } - - var stdout = fs.readFileSync(stdoutFile, 'utf8'); - var stderr = fs.readFileSync(stderrFile, 'utf8'); - - // No biggie if we can't erase the files now -- they're in a temp dir anyway - try { common.unlinkSync(scriptFile); } catch (e) {} - try { common.unlinkSync(stdoutFile); } catch (e) {} - try { common.unlinkSync(stderrFile); } catch (e) {} - try { common.unlinkSync(codeFile); } catch (e) {} - - if (code !== 0) { - common.error('', code, { continue: true }); - } - var obj = common.ShellString(stdout, stderr, code); - return obj; -} // execSync() - -// Wrapper around exec() to enable echoing output to console in real time -function execAsync(cmd, opts, pipe, callback) { - var stdout = ''; - var stderr = ''; - - opts = common.extend({ - silent: common.config.silent, - cwd: _pwd().toString(), - env: process.env, - maxBuffer: DEFAULT_MAXBUFFER_SIZE, - }, opts); - - var c = child.exec(cmd, opts, function (err) { - if (callback) { - if (!err) { - callback(0, stdout, stderr); - } else if (err.code === undefined) { - // See issue #536 - callback(1, stdout, stderr); - } else { - callback(err.code, stdout, stderr); - } - } - }); - - if (pipe) c.stdin.end(pipe); - - c.stdout.on('data', function (data) { - stdout += data; - if (!opts.silent) process.stdout.write(data); - }); - - c.stderr.on('data', function (data) { - stderr += data; - if (!opts.silent) process.stderr.write(data); - }); - - return c; -} - -//@ -//@ ### exec(command [, options] [, callback]) -//@ Available options (all `false` by default): -//@ -//@ + `async`: Asynchronous execution. If a callback is provided, it will be set to -//@ `true`, regardless of the passed value. -//@ + `silent`: Do not echo program output to console. -//@ + and any option available to Node.js's -//@ [child_process.exec()](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var version = exec('node --version', {silent:true}).stdout; -//@ -//@ var child = exec('some_long_running_process', {async:true}); -//@ child.stdout.on('data', function(data) { -//@ /* ... do something with data ... */ -//@ }); -//@ -//@ exec('some_long_running_process', function(code, stdout, stderr) { -//@ console.log('Exit code:', code); -//@ console.log('Program output:', stdout); -//@ console.log('Program stderr:', stderr); -//@ }); -//@ ``` -//@ -//@ Executes the given `command` _synchronously_, unless otherwise specified. When in synchronous -//@ mode, this returns a ShellString (compatible with ShellJS v0.6.x, which returns an object -//@ of the form `{ code:..., stdout:... , stderr:... }`). Otherwise, this returns the child process -//@ object, and the `callback` gets the arguments `(code, stdout, stderr)`. -//@ -//@ Not seeing the behavior you want? `exec()` runs everything through `sh` -//@ by default (or `cmd.exe` on Windows), which differs from `bash`. If you -//@ need bash-specific behavior, try out the `{shell: 'path/to/bash'}` option. -//@ -//@ **Note:** For long-lived processes, it's best to run `exec()` asynchronously as -//@ the current synchronous implementation uses a lot of CPU. This should be getting -//@ fixed soon. -function _exec(command, options, callback) { - options = options || {}; - if (!command) common.error('must specify command'); - - var pipe = common.readFromPipe(); - - // Callback is defined instead of options. - if (typeof options === 'function') { - callback = options; - options = { async: true }; - } - - // Callback is defined with options. - if (typeof options === 'object' && typeof callback === 'function') { - options.async = true; - } - - options = common.extend({ - silent: common.config.silent, - async: false, - }, options); - - try { - if (options.async) { - return execAsync(command, options, pipe, callback); - } else { - return execSync(command, options, pipe); - } - } catch (e) { - common.error('internal error'); - } -} -module.exports = _exec; |