"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.execute = exports.sh = exports.executeProcess = exports.executeAndControlProcess = void 0;
const child_process_1 = require("child_process");
const fs_1 = require("fs");
function makeError(error, properties) {
    if (typeof error === 'string') {
        error = new Error(error);
    }
    if (!properties)
        return error;
    return Object.assign(error, properties);
}
function executeAndControlProcess(command, args = [], options) {
    const subProcess = (0, child_process_1.spawn)(command, args, {
        stdio: 'pipe',
        ...options === null || options === void 0 ? void 0 : options.spawnOptions,
    });
    const exitPromise = new Promise((resolve, reject) => {
        subProcess.on('error', reject).on('close', (exitCode, signal) => exitCode === 0
            ? resolve({ exitCode, stdout, stderr })
            : signal
                ? reject(makeError(new Error(`process exited due to signal ${signal} executing process ${command} with args ${JSON.stringify(args)}`), {
                    signal,
                    stdout,
                    stderr,
                }))
                : reject(makeError(new Error(`non-zero exit code (${exitCode}) executing process ${command} with args ${JSON.stringify(args)}`), {
                    exitCode,
                    stdout,
                    stderr,
                })));
        let stdout = subProcess.stdout ? '' : undefined;
        let stderr = subProcess.stderr ? '' : undefined;
        subProcess.stdout && subProcess.stdout.on('data', data => (stdout += data.toString()));
        subProcess.stderr && subProcess.stderr.on('data', data => (stderr += data.toString()));
        if (options === null || options === void 0 ? void 0 : options.timeout) {
            setTimeout(() => subProcess.kill(), options.timeout);
        }
        return { stdout, stderr };
    });
    return { subProcess, exitPromise };
}
exports.executeAndControlProcess = executeAndControlProcess;
async function executeProcess(command, args = [], options) {
    return await executeAndControlProcess(command, args, options).exitPromise;
}
exports.executeProcess = executeProcess;
async function sh(command, options) {
    let shell;
    if (process.platform === 'win32') {
        shell = 'C:\\Program Files\\Git\\bin\\bash.exe';
    }
    else if ((0, fs_1.existsSync)('/bin/bash')) {
        shell = '/bin/bash';
    }
    else {
        shell = '/bin/sh';
    }
    return await executeProcess(command, [], {
        ...options,
        spawnOptions: {
            stdio: 'inherit',
            shell,
            ...options === null || options === void 0 ? void 0 : options.spawnOptions,
        },
    });
}
exports.sh = sh;
async function execute(command, options) {
    return new Promise(resolve => {
        (0, child_process_1.exec)(command, options, (error, stdout, stderr) => {
            if (error)
                resolve({ stdout: stdout.toString('utf8'), stderr: stderr.toString('utf8'), code: error.code });
            resolve({ stdout: stdout.toString('utf8'), stderr: stderr.toString('utf8'), code: 0 });
        });
    });
}
exports.execute = execute;
