1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-22 19:26:13 +02:00
metamask-extension/development/lib/runCommand.js
Mark Stacey b1dcbcec2c
Rewrite changelog script from Bash to JavaScript (#10782)
The `auto-changelog` script has been rewritten from Bash to JavaScript.
Functionally it should behave identically.
2021-03-31 14:15:53 -02:30

80 lines
2.6 KiB
JavaScript

const spawn = require('cross-spawn');
/**
* Run a command to completion using the system shell.
*
* This will run a command with the specified arguments, and resolve when the
* process has exited. The STDOUT stream is monitored for output, which is
* returned after being split into lines. All output is expected to be UTF-8
* encoded, and empty lines are removed from the output.
*
* Anything received on STDERR is assumed to indicate a problem, and is tracked
* as an error.
*
* @param {string} command - The command to run
* @param {Array<string>} [args] - The arguments to pass to the command
* @returns {Array<string>} Lines of output received via STDOUT
*/
async function runCommand(command, args) {
const output = [];
let mostRecentError;
let errorSignal;
let errorCode;
const internalError = new Error('Internal');
try {
await new Promise((resolve, reject) => {
const childProcess = spawn(command, args, { encoding: 'utf8' });
childProcess.stdout.setEncoding('utf8');
childProcess.stderr.setEncoding('utf8');
childProcess.on('error', (error) => {
mostRecentError = error;
});
childProcess.stdout.on('data', (message) => {
const nonEmptyLines = message.split('\n').filter((line) => line !== '');
output.push(...nonEmptyLines);
});
childProcess.stderr.on('data', (message) => {
mostRecentError = new Error(message.trim());
});
childProcess.once('exit', (code, signal) => {
if (code === 0) {
return resolve();
}
errorCode = code;
errorSignal = signal;
return reject(internalError);
});
});
} catch (error) {
/**
* The error is re-thrown here in an `async` context to preserve the stack trace. If this was
* was thrown inside the Promise constructor, the stack trace would show a few frames of
* Node.js internals then end, without indicating where `runCommand` was called.
*/
if (error === internalError) {
let errorMessage;
if (errorCode !== null && errorSignal !== null) {
errorMessage = `Terminated by signal '${errorSignal}'; exited with code '${errorCode}'`;
} else if (errorSignal !== null) {
errorMessage = `Terminaled by signal '${errorSignal}'`;
} else if (errorCode === null) {
errorMessage = 'Exited with no code or signal';
} else {
errorMessage = `Exited with code '${errorCode}'`;
}
const improvedError = new Error(errorMessage);
if (mostRecentError) {
improvedError.cause = mostRecentError;
}
throw improvedError;
}
}
return output;
}
module.exports = runCommand;