in src/proc.ts [109:244]
export function execute(command: string,
args?: string[],
outputConsumer?: OutputConsumer | null,
options?: ExecutionOptions): Subprocess {
const cmdstr = buildCmdStr(command, args);
if (options && options.silent !== true) {
log.info(// We do simple quoting of arguments with spaces.
// This is only shown to the user,
// and doesn't have to be 100% correct.
localize('executing.command', 'Executing command: {0}', cmdstr));
}
if (!options) {
options = {};
}
const localeOverride = EnvironmentUtils.create({
LANG: "C",
LC_ALL: "C"
});
const final_env = EnvironmentUtils.merge([
process.env,
options.environment,
options.overrideLocale ? localeOverride : {}]);
const spawn_opts: proc.SpawnOptions = {
env: final_env,
shell: !!options.shell
};
if (options && options.cwd) {
spawn_opts.cwd = options.cwd;
}
let child: proc.ChildProcess | undefined;
let result: Promise<ExecutionResult>;
const useTask = (options && options.useTask) ? options.useTask : false;
if (useTask) {
// child = undefined;
// const term = vscode.window.createTerminal("Cmake Build");
// term.show(true);
// term.sendText(cmdstr);
void vscode.commands.executeCommand("workbench.action.tasks.build");
result = new Promise<ExecutionResult>((resolve) => {
resolve({ retc: 0, stdout: '', stderr: '' });
});
} else {
try {
child = proc.spawn(command, args ?? [], spawn_opts);
} catch {
child = undefined;
}
if (child === undefined) {
return {
child: undefined,
result: Promise.resolve({
retc: -1,
stdout: "",
stderr: ""
})
};
}
if (options.encoding) {
child.stdout?.setEncoding(options.encoding);
}
const encoding = options.outputEncoding && iconv.encodingExists(options.outputEncoding) ? options.outputEncoding : 'utf8';
result = new Promise<ExecutionResult>(resolve => {
if (child) {
child.on('error', err => resolve({ retc: -1, stdout: "", stderr: err.message ?? '' }));
let stdout_acc = '';
let line_acc = '';
let stderr_acc = '';
let stderr_line_acc = '';
child.stdout?.on('data', (data: Uint8Array) => {
rollbar.invoke(localize('processing.data.event.stdout', 'Processing "data" event from proc stdout'), { data, command, args }, () => {
const str = iconv.decode(Buffer.from(data), encoding);
const lines = str.split('\n').map(l => l.endsWith('\r') ? l.substr(0, l.length - 1) : l);
while (lines.length > 1) {
line_acc += lines[0];
if (outputConsumer) {
outputConsumer.output(line_acc);
} else if (util.isTestMode()) {
log.info(line_acc);
}
line_acc = '';
// Erase the first line from the list
lines.splice(0, 1);
}
console.assert(lines.length, 'Invalid lines', JSON.stringify(lines));
line_acc += lines[0];
stdout_acc += str;
});
});
child.stderr?.on('data', (data: Uint8Array) => {
rollbar.invoke(localize('processing.data.event.stderr', 'Processing "data" event from proc stderr'), { data, command, args }, () => {
const str = iconv.decode(Buffer.from(data), encoding);
const lines = str.split('\n').map(l => l.endsWith('\r') ? l.substr(0, l.length - 1) : l);
while (lines.length > 1) {
stderr_line_acc += lines[0];
if (outputConsumer) {
outputConsumer.error(stderr_line_acc);
} else if (util.isTestMode() && stderr_line_acc) {
log.info(stderr_line_acc);
}
stderr_line_acc = '';
// Erase the first line from the list
lines.splice(0, 1);
}
console.assert(lines.length, 'Invalid lines', JSON.stringify(lines));
stderr_line_acc += lines[0];
stderr_acc += str;
});
});
// Don't stop until the child stream is closed, otherwise we might not read
// the whole output of the command.
child.on('close', retc => {
try {
rollbar.invoke(localize('resolving.close.event', 'Resolving process on "close" event'), { line_acc, stderr_line_acc, command, retc }, () => {
if (line_acc && outputConsumer) {
outputConsumer.output(line_acc);
}
if (stderr_line_acc && outputConsumer) {
outputConsumer.error(stderr_line_acc);
}
resolve({ retc, stdout: stdout_acc, stderr: stderr_acc });
});
} catch (_) {
// No error handling since Rollbar has taken the error.
resolve({ retc, stdout: stdout_acc, stderr: stderr_acc });
}
});
}
});
}
return { child, result };
}