79 lines
2.2 KiB
JavaScript
79 lines
2.2 KiB
JavaScript
import byline from 'byline';
|
|
import chip from 'child_process';
|
|
import fs from 'fs';
|
|
import { log } from './log.js';
|
|
|
|
const MAX_LINES = 20;
|
|
const DEBUG_THRESHOLDS = false;
|
|
|
|
function errorLines (lines) {
|
|
return lines.slice(-MAX_LINES)
|
|
.map((line) => line[1]).join('\n');
|
|
}
|
|
|
|
export function spawn (cmd, args, opts) {
|
|
const child = chip.spawn(cmd, args, opts);
|
|
const stdout = byline(child.stdout);
|
|
const stderr = byline(child.stderr);
|
|
const lines = [];
|
|
|
|
let onData = function (data) {
|
|
const time = (new Date()).getTime();
|
|
lines.push([ time, data.toString() ]); // TODO chalk stdout/stderr?
|
|
const { thresholds } = this; // eslint-disable-line no-invalid-this
|
|
if (thresholds) {
|
|
for (const key in thresholds) {
|
|
if (data.indexOf(key) >= 0) {
|
|
const p = thresholds[key];
|
|
log.showProgress(p);
|
|
if (DEBUG_THRESHOLDS) {
|
|
lines.push([ time, '************' ]);
|
|
lines.push([ time, p + ': ' + key ]);
|
|
lines.push([ time, '************' ]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
const promise = new Promise((resolve, reject) => {
|
|
child.on('error', (error) => {
|
|
console.error(errorLines(lines)); // dont use `log` here
|
|
reject(error);
|
|
});
|
|
child.on('close', (code) => {
|
|
if (code) {
|
|
console.error(errorLines(lines)); // dont use `log` here
|
|
return reject(new Error(`${cmd} failed with code ${code}`));
|
|
}
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
onData = onData.bind(promise);
|
|
if (stdout) stdout.on('data', onData);
|
|
if (stderr) stderr.on('data', onData);
|
|
|
|
promise.child = child;
|
|
promise.lines = lines;
|
|
return promise;
|
|
}
|
|
|
|
export function progress (promise, thresholds) {
|
|
promise.thresholds = thresholds;
|
|
const { child, lines } = promise;
|
|
log.enableProgress(promise.child.spawnfile);
|
|
log.showProgress(0);
|
|
const start = (new Date()).getTime();
|
|
child.on('close', () => {
|
|
if (DEBUG_THRESHOLDS) {
|
|
const finish = (new Date()).getTime();
|
|
const content = lines.map((line) =>
|
|
((100 * (line[0] - start) / (finish - start)) | 0) + ': ' + line[1]
|
|
).join('\n');
|
|
fs.writeFileSync(child.spawnfile + '.debug', content);
|
|
}
|
|
log.disableProgress();
|
|
});
|
|
}
|