8000 refactor: change how internal errors are handled · shelljs/shelljs@67a26e2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 67a26e2

Browse files
committed
refactor: change how internal errors are handled
This is an internal refactor to change how we handle execa errors inside of shell.cmd(). This also adds a test case for a command which fails silently to make sure that we handle this case correctly.
1 parent bfd06fa commit 67a26e2

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

src/cmd.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function isNullOrUndefined(val) {
1515
return val === null || val === undefined;
1616
}
1717

18-
function commandNotFound(execaResult) {
18+
function isCommandNotFound(execaResult) {
1919
if (process.platform === 'win32') {
2020
var str = 'is not recognized as an internal or external command';
2121
return execaResult.code && execaResult.stderr.includes(str);
@@ -28,6 +28,16 @@ function commandNotFound(execaResult) {
2828
}
2929
}
3030

31+
function isExecaInternalError(result) {
32+
if (typeof result.stdout !== 'string') return true;
33+
if (typeof result.stderr !== 'string') return true;
34+
if (typeof result.code !== 'number') return true;
35+
if (result.code === 0 && result.failed) return true;
36+
// Otherwise assume this executed correctly. The command may still have exited
37+
// with non-zero status, but that's not due to anything execa did.
38+
return false;
39+
}
40+
3141
//@
3242
//@ ### cmd(arg1[, arg2, ...] [, options])
3343
//@
@@ -110,26 +120,24 @@ function _cmd(options, command, commandArgs, userOptions) {
110120
var stdout;
111121
var stderr;
112122
var code;
113-
if (commandNotFound(result)) {
123+
if (isCommandNotFound(result)) {
114124
// This can happen if `command` is not an executable binary, or possibly
115125
// under other conditions.
116126
stdout = '';
117127
stderr = "'" + command + "': command not found";
118128
code = COMMAND_NOT_FOUND_ERROR_CODE;
119-
} else if (typeof result.stdout === 'string' &&
120-
typeof result.stderr === 'string' &&
121-
typeof result.code === 'number') {
122-
// Normal exit: execa was able to execute `command` and get a return value.
123-
stdout = result.stdout.toString();
124-
stderr = result.stderr.toString();
125-
code = result.code;
126-
} else {
129+
} else if (isExecaInternalError(result)) {
127130
// Catch-all: execa tried to run `command` but it encountered some error
128131
// (ex. maxBuffer, timeout).
129132
stdout = result.stdout || '';
130133
stderr = result.stderr ||
131134
`'${command}' encountered an error during execution`;
132-
code = result.code > 0 ? result.code : 1;
135+
code = typeof result.code === 'number' && result.code > 0 ? result.code : 1;
136+
} else {
137+
// Normal exit: execa was able to execute `command` and get a return value.
138+
stdout = result.stdout.toString();
139+
stderr = result.stderr.toString();
140+
code = result.code;
133141
}
134142

135143
// Pass `continue: true` so we can specify a value for stdout.

test/cmd.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ test('set cwd', t => {
177177
t.is(result.stdout, path.resolve('..') + '\n');
178178
});
179179

180+
test('command fails silently with non-zero status', t => {
181+
const result = shell.cmd('shx', 'false');
182+
t.truthy(shell.error());
183+
t.is(result.code, 1);
184+
t.is(result.stdout, '');
185+
t.is(result.stderr, '');
186+
});
187+
180188
test('set maxBuffer (very small)', t => {
181189
let result = shell.cmd('shx', 'echo', '1234567890'); // default maxBuffer is ok
182190
t.falsy(shell.error());

0 commit comments

Comments
 (0)
0