Skip to content

Commit

Permalink
chore: remove v0.12 and iojs support (#648)
Browse files Browse the repository at this point in the history
Fixes #647
  • Loading branch information
nfischer committed Jun 7, 2017
1 parent 5d05d27 commit f74e783
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 142 deletions.
5 changes: 0 additions & 5 deletions .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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ script's dependency on Unix while still keeping 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 battle-tested in projects like:

Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
},
"optionalDependencies": {},
"engines": {
"node": ">=0.11.0",
"iojs": "*"
"node": ">=4"
}
}
23 changes: 4 additions & 19 deletions 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 @@ -43,7 +28,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 @@ -116,7 +101,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 @@ -449,7 +434,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 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 src/tempdir.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,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
11 changes: 4 additions & 7 deletions test/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,8 @@ 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 => {
Expand All @@ -125,9 +123,8 @@ test('set timeout option', t => {
if (process.version >= 'v0.11') {
// this option doesn't work on v0.10
shell.exec(`${JSON.stringify(shell.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 @@ -148,7 +145,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

0 comments on commit f74e783

Please sign in to comment.