diff options
| author | Kumar Priyansh <[email protected]> | 2019-01-19 12:37:14 +0530 |
|---|---|---|
| committer | Kumar Priyansh <[email protected]> | 2019-01-19 12:37:14 +0530 |
| commit | dcdfc94cb39dfe2c39925a0145ffa45e2d061c30 (patch) | |
| tree | 4f6379d955555b298c0e7b83a67e264240ee5614 /cordova/node_modules/shelljs/src/exec.js | |
| parent | 76f7b3678d3f1ff99c3935a774d420453b0c3cb9 (diff) | |
| download | WeatherApp-dcdfc94cb39dfe2c39925a0145ffa45e2d061c30.tar.xz WeatherApp-dcdfc94cb39dfe2c39925a0145ffa45e2d061c30.zip | |
Initial Upload via GIT
Diffstat (limited to 'cordova/node_modules/shelljs/src/exec.js')
| -rwxr-xr-x | cordova/node_modules/shelljs/src/exec.js | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/cordova/node_modules/shelljs/src/exec.js b/cordova/node_modules/shelljs/src/exec.js new file mode 100755 index 0000000..d259a9f --- /dev/null +++ b/cordova/node_modules/shelljs/src/exec.js @@ -0,0 +1,216 @@ +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'); + +// 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) { + var tempDir = _tempDir(); + var stdoutFile = path.resolve(tempDir+'/'+common.randomFileName()), + codeFile = path.resolve(tempDir+'/'+common.randomFileName()), + scriptFile = path.resolve(tempDir+'/'+common.randomFileName()), + sleepFile = path.resolve(tempDir+'/'+common.randomFileName()); + + var options = common.extend({ + silent: common.config.silent + }, opts); + + var previousStdoutContent = ''; + // Echoes stdout changes from running process, if not silent + function updateStdout() { + if (options.silent || !fs.existsSync(stdoutFile)) + return; + + var stdoutContent = fs.readFileSync(stdoutFile, 'utf8'); + // No changes since last time? + if (stdoutContent.length <= previousStdoutContent.length) + return; + + process.stdout.write(stdoutContent.substr(previousStdoutContent.length)); + previousStdoutContent = stdoutContent; + } + + function escape(str) { + return (str+'').replace(/([\\"'])/g, "\\$1").replace(/\0/g, "\\0"); + } + + if (fs.existsSync(scriptFile)) common.unlinkSync(scriptFile); + if (fs.existsSync(stdoutFile)) common.unlinkSync(stdoutFile); + if (fs.existsSync(codeFile)) common.unlinkSync(codeFile); + + var execCommand = '"'+process.execPath+'" '+scriptFile; + var execOptions = { + env: process.env, + cwd: _pwd(), + maxBuffer: 20*1024*1024 + }; + + if (typeof child.execSync === 'function') { + var script = [ + "var child = require('child_process')", + " , fs = require('fs');", + "var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {", + " fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');", + "});", + "var stdoutStream = fs.createWriteStream('"+escape(stdoutFile)+"');", + "childProcess.stdout.pipe(stdoutStream, {end: false});", + "childProcess.stderr.pipe(stdoutStream, {end: false});", + "childProcess.stdout.pipe(process.stdout);", + "childProcess.stderr.pipe(process.stderr);", + "var stdoutEnded = false, stderrEnded = false;", + "function tryClosing(){ if(stdoutEnded && stderrEnded){ stdoutStream.end(); } }", + "childProcess.stdout.on('end', function(){ stdoutEnded = true; tryClosing(); });", + "childProcess.stderr.on('end', function(){ stderrEnded = true; tryClosing(); });" + ].join('\n'); + + fs.writeFileSync(scriptFile, script); + + if (options.silent) { + execOptions.stdio = 'ignore'; + } else { + execOptions.stdio = [0, 1, 2]; + } + + // Welcome to the future + child.execSync(execCommand, execOptions); + } else { + cmd += ' > '+stdoutFile+' 2>&1'; // works on both win/unix + + var script = [ + "var child = require('child_process')", + " , fs = require('fs');", + "var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {", + " fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');", + "});" + ].join('\n'); + + fs.writeFileSync(scriptFile, script); + + child.exec(execCommand, execOptions); + + // 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)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); } + while (!fs.existsSync(stdoutFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); } + } + + // 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'); + + // 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(codeFile); } catch(e) {} + try { common.unlinkSync(sleepFile); } catch(e) {} + + // some shell return codes are defined as errors, per http://tldp.org/LDP/abs/html/exitcodes.html + if (code === 1 || code === 2 || code >= 126) { + common.error('', true); // unix/shell doesn't really give an error message after non-zero exit codes + } + // True if successful, false if not + var obj = { + code: code, + output: stdout + }; + return obj; +} // execSync() + +// Wrapper around exec() to enable echoing output to console in real time +function execAsync(cmd, opts, callback) { + var output = ''; + + var options = common.extend({ + silent: common.config.silent + }, opts); + + var c = child.exec(cmd, {env: process.env, maxBuffer: 20*1024*1024}, function(err) { + if (callback) + callback(err ? err.code : 0, output); + }); + + c.stdout.on('data', function(data) { + output += data; + if (!options.silent) + process.stdout.write(data); + }); + + c.stderr.on('data', function(data) { + output += data; + if (!options.silent) + process.stdout.write(data); + }); + + return c; +} + +//@ +//@ ### exec(command [, options] [, callback]) +//@ Available options (all `false` by default): +//@ +//@ + `async`: Asynchronous execution. Defaults to true if a callback is provided. +//@ + `silent`: Do not echo program output to console. +//@ +//@ Examples: +//@ +//@ ```javascript +//@ var version = exec('node --version', {silent:true}).output; +//@ +//@ 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, output) { +//@ console.log('Exit code:', code); +//@ console.log('Program output:', output); +//@ }); +//@ ``` +//@ +//@ Executes the given `command` _synchronously_, unless otherwise specified. +//@ When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's +//@ `output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and +//@ the `callback` gets the arguments `(code, output)`. +//@ +//@ **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) { + if (!command) + common.error('must specify command'); + + // 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); + + if (options.async) + return execAsync(command, options, callback); + else + return execSync(command, options); +} +module.exports = _exec; |
