export function execute()

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 };
}