"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const util_1 = require("util");
const fs = require("fs");
const tmp = require("tmp");
const rimraf = require("rimraf");
const lookpath_1 = require("lookpath");
function delay(durationMs) {
    return new Promise((resolve) => setTimeout(resolve, durationMs));
}
exports.delay = delay;
async function waitUntil(delayMs, tries, test) {
    let result = tries > 0 && await test();
    while (tries > 0 && !result) {
        tries = tries - 1;
        await delay(delayMs);
        result = await test();
    }
    if (!result)
        throw new Error(`Wait loop failed`);
    else
        return result;
}
exports.waitUntil = waitUntil;
function getDeferred() {
    let resolve = undefined;
    let reject = undefined;
    let promise = new Promise((resolveCb, rejectCb) => {
        resolve = resolveCb;
        reject = rejectCb;
    });
    // TS thinks we're using these before they're assigned, which is why
    // we need the undefined types, and the any here.
    return { resolve, reject, promise };
}
exports.getDeferred = getDeferred;
exports.statFile = util_1.promisify(fs.stat);
exports.readFile = util_1.promisify(fs.readFile);
exports.readDir = util_1.promisify(fs.readdir);
exports.deleteFile = util_1.promisify(fs.unlink);
exports.checkAccess = util_1.promisify(fs.access);
exports.mkDir = util_1.promisify(fs.mkdir);
exports.writeFile = util_1.promisify(fs.writeFile);
exports.renameFile = util_1.promisify(fs.rename);
exports.copyFile = util_1.promisify(fs.copyFile);
exports.canAccess = (path) => exports.checkAccess(path).then(() => true).catch(() => false);
exports.deleteFolder = util_1.promisify(rimraf);
exports.ensureDirectoryExists = (path) => exports.checkAccess(path).catch(() => exports.mkDir(path, { recursive: true }));
exports.commandExists = (path) => lookpath_1.lookpath(path).then((result) => result !== undefined);
exports.createTmp = (options = {}) => new Promise((resolve, reject) => {
    tmp.file(options, (err, path, fd, cleanupCallback) => {
        if (err)
            return reject(err);
        resolve({ path, fd, cleanupCallback });
    });
});
exports.moveFile = async (oldPath, newPath) => {
    try {
        await exports.renameFile(oldPath, newPath);
    }
    catch (e) {
        if (e.code === 'EXDEV') {
            // Cross-device - can't rename files across partions etc.
            // In that case, we fallback to copy then delete:
            await exports.copyFile(oldPath, newPath);
            await exports.deleteFile(oldPath);
        }
    }
};
//# sourceMappingURL=util.js.map