Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions 5 .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
language: c++
sudo: false
env:
- NODE_VERSION="0.11"
- NODE_VERSION="0.12"
- NODE_VERSION="iojs-v1"
- NODE_VERSION="iojs-v2"
- NODE_VERSION="iojs-v3"
- NODE_VERSION="4"
- NODE_VERSION="5"
- NODE_VERSION="6"
Expand Down
2 changes: 1 addition & 1 deletion 2 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Node.js API. You can use it to eliminate your shell script's dependency on Unix
its familiar and powerful commands. You can also install it globally so you can run it from outside
Node projects - say goodbye to those gnarly Bash scripts!

ShellJS is proudly tested on every node release since `v0.11`!
ShellJS is proudly tested on every node release since `v4`!

The project is [unit-tested](http://travis-ci.org/shelljs/shelljs) and battled-tested in projects like:

Expand Down
3 changes: 1 addition & 2 deletions 3 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
},
"optionalDependencies": {},
"engines": {
"node": ">=0.11.0",
"iojs": "*"
"node": ">=4"
}
}
23 changes: 4 additions & 19 deletions 23 src/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,7 @@ var shell = require('..');

var shellMethods = Object.create(shell);

// objectAssign(target_obj, source_obj1 [, source_obj2 ...])
// "Ponyfill" for Object.assign
// objectAssign({A:1}, {b:2}, {c:3}) returns {A:1, b:2, c:3}
var objectAssign = typeof Object.assign === 'function' ?
Object.assign :
function objectAssign(target) {
var sources = [].slice.call(arguments, 1);
sources.forEach(function (source) {
Object.keys(source).forEach(function (key) {
target[key] = source[key];
});
});

return target;
};
exports.extend = objectAssign;
exports.extend = Object.assign;

// Check if we're running under electron
var isElectron = Boolean(process.versions.electron);
Expand All @@ -42,7 +27,7 @@ var DEFAULT_CONFIG = {

var config = {
reset: function () {
objectAssign(this, DEFAULT_CONFIG);
Object.assign(this, DEFAULT_CONFIG);
if (!isElectron) {
this.execPath = process.execPath;
}
Expand Down Expand Up @@ -100,7 +85,7 @@ function error(msg, _code, options) {
} else if (typeof _code !== 'number') { // only 'msg'
options = {};
}
options = objectAssign({}, DEFAULT_OPTIONS, options);
options = Object.assign({}, DEFAULT_OPTIONS, options);

if (!state.errorCode) state.errorCode = options.code;

Expand Down Expand Up @@ -413,7 +398,7 @@ var DEFAULT_WRAP_OPTIONS = {
function _register(name, implementation, wrapOptions) {
wrapOptions = wrapOptions || {};
// If an option isn't specified, use the default
wrapOptions = objectAssign({}, DEFAULT_WRAP_OPTIONS, wrapOptions);
wrapOptions = Object.assign({}, DEFAULT_WRAP_OPTIONS, wrapOptions);

if (shell[name] && !wrapOptions.overWrite) {
throw new Error('unable to overwrite `' + name + '` command');
Expand Down
152 changes: 45 additions & 107 deletions 152 src/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ function execSync(cmd, opts, pipe) {
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,
Expand All @@ -37,34 +36,6 @@ function execSync(cmd, opts, pipe) {
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);
Expand All @@ -76,86 +47,53 @@ function execSync(cmd, opts, pipe) {
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;
}
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 {
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);
opts.stdio = [0, 1, 2];
}

// 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) {}
// 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;
}

// At this point codeFile exists, but it's not necessarily flushed yet.
Expand Down
1 change: 0 additions & 1 deletion 1 src/tempdir.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ function _tempDir() {
if (state.tempDir) return state.tempDir; // from cache

state.tempDir = writeableDir(os.tmpdir && os.tmpdir()) || // node 0.10+
writeableDir(os.tmpDir && os.tmpDir()) || // node 0.8+
writeableDir(process.env.TMPDIR) ||
writeableDir(process.env.TEMP) ||
writeableDir(process.env.TMP) ||
Expand Down
15 changes: 5 additions & 10 deletions 15 test/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,22 +113,17 @@ test('set maxBuffer (very small)', t => {
t.falsy(shell.error());
t.is(result.code, 0);
t.is(result.stdout, '1234567890' + os.EOL);
if (process.version >= 'v0.11') { // this option doesn't work on v0.10
shell.exec('echo 1234567890', { maxBuffer: 6 });
t.truthy(shell.error());
}
shell.exec('echo 1234567890', { maxBuffer: 6 });
t.truthy(shell.error());
});

test('set timeout option', t => {
const result = shell.exec(`${JSON.stringify(common.config.execPath)} resources/exec/slow.js 100`); // default timeout is ok
t.falsy(shell.error());
t.is(result.code, 0);
if (process.version >= 'v0.11') {
// this option doesn't work on v0.10
shell.exec(`${JSON.stringify(common.config.execPath)} resources/exec/slow.js 100`, { timeout: 10 }); // times out
shell.exec(`${JSON.stringify(common.config.execPath)} resources/exec/slow.js 100`, { timeout: 10 }); // times out

t.truthy(shell.error());
}
t.truthy(shell.error());
});

test('check process.env works', t => {
Expand All @@ -149,7 +144,7 @@ test('set shell option (TODO: add tests for Windows)', t => {
t.is(result.stdout, '/bin/sh\n'); // sh by default
const bashPath = shell.which('bash').trim();
// this option doesn't work on v0.10
if (bashPath && process.version >= 'v0.11') {
if (bashPath) {
result = shell.exec('echo $0', { shell: '/bin/bash' });
t.falsy(shell.error());
t.is(result.code, 0);
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.