"use strict";
/* eslint header/header: off */
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) 2021 Vercel, Inc. All rights reserved.
 *  Licensed under the MIT License. See OSSREADME.json in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.DIR = DIR;
exports.getRepoInfo = getRepoInfo;
exports.getStoragePathForCustomTemplates = getStoragePathForCustomTemplates;
exports.loadCustomTemplatesGitRepo = loadCustomTemplatesGitRepo;
const tslib_1 = require("tslib");
/**
 * The following implementation are adapted from create-next-app
 * See https://github.com/vercel/next.js for more information
 */
const crypto = require("crypto");
const nodeFs = require("fs");
const got_1 = require("got");
const path = require("path");
const tar_1 = require("tar");
const os = require("node:os");
const i18n_1 = require("../i18n");
const hpagent_1 = require("hpagent");
const proxy_from_env_1 = require("proxy-from-env");
const SFDX_STATE_FOLDER = '.sfdx';
/**
 * The full system path to the preferred global state folder
 */
function DIR() {
    return path.join(os.homedir(), SFDX_STATE_FOLDER);
}
/**
 * extract repo info from uri
 * @param repoUri uri to git repo
 */
function getRepoInfo(repoUri) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const [, username, name, t, branch, ...file] = repoUri.pathname.split('/');
        const filePath = `${file.join('/')}`;
        // For repos with no branch information, fetch default branch
        if (t === undefined) {
            const url = `https://api.github.com/repos/${username}/${name}`;
            const proxy = (0, proxy_from_env_1.getProxyForUrl)(url);
            // proxy will be empty string if no proxy is set
            const infoResponse = yield (proxy !== ''
                ? (0, got_1.default)(url, {
                    agent: {
                        https: new hpagent_1.HttpsProxyAgent({
                            keepAlive: true,
                            keepAliveMsecs: 1000,
                            maxSockets: 256,
                            maxFreeSockets: 256,
                            scheduling: 'lifo',
                            proxy,
                        }),
                    },
                })
                : (0, got_1.default)(url)).catch((e) => e);
            if (infoResponse.statusCode !== 200) {
                throw new Error(i18n_1.nls.localize('customTemplatesCannotRetrieveDefaultBranch', repoUri.href));
            }
            const info = JSON.parse(infoResponse.body);
            return { username, name, branch: info['default_branch'], filePath };
        }
        if (username && name && branch && t === 'tree') {
            return { username, name, branch, filePath };
        }
        else {
            throw new Error(i18n_1.nls.localize('customTemplatesInvalidRepoUrl', repoUri.href));
        }
    });
}
/**
 * Returns a path to store custom templates from a Git repo
 * @param repoUri repository uri
 * @returns path to store custom templates
 */
function getStoragePathForCustomTemplates(repoUri) {
    const folderHash = crypto
        .createHash('md5')
        .update(repoUri.href)
        .digest('hex');
    const customTemplatesPath = path.join(DIR(), 'custom-templates', folderHash);
    return customTemplatesPath;
}
/**
 * Load custom templates Git repo. Currently only supports GitHub.
 * @param repoUri repo uri
 * @param forceLoadingRemoteRepo by default do not reload remote repo if the repo is already downloaded
 * @param fs node-fs-compatible object, defaults to node:fs
 * @returns path to the local storage location of the repo
 */
function loadCustomTemplatesGitRepo(repoUri_1) {
    return tslib_1.__awaiter(this, arguments, void 0, function* (repoUri, forceLoadingRemoteRepo = false, fs = nodeFs) {
        const customTemplatesPath = getStoragePathForCustomTemplates(repoUri);
        // Do not load the remote repo if already the repo is already downloaded.
        if (fs.existsSync(customTemplatesPath) && !forceLoadingRemoteRepo) {
            return customTemplatesPath;
        }
        if (repoUri.protocol !== 'https:') {
            throw new Error(i18n_1.nls.localize('customTemplatesShouldUseHttpsProtocol', `"${repoUri.protocol}"`));
        }
        if (repoUri.hostname !== 'github.com') {
            throw new Error(i18n_1.nls.localize('customTemplatesSupportsGitHubOnly', repoUri.href));
        }
        const { username, name, branch, filePath } = yield getRepoInfo(repoUri);
        yield fs.promises.mkdir(customTemplatesPath, { recursive: true });
        // Download the repo and extract to the SFDX global state folder
        const response = yield (0, got_1.default)(`https://codeload.github.com/${username}/${name}/tar.gz/${branch}`);
        // Create a temporary file to extract from
        const tempFile = path.join(customTemplatesPath, 'temp.tar.gz');
        yield fs.promises.writeFile(tempFile, new Uint8Array(response.rawBody));
        try {
            yield (0, tar_1.extract)({
                cwd: customTemplatesPath,
                strip: filePath ? filePath.split('/').length + 1 : 1,
                file: tempFile,
            });
        }
        finally {
            // Clean up the temporary file
            yield fs.promises.unlink(tempFile).catch(() => { });
        }
        return customTemplatesPath;
    });
}
//# sourceMappingURL=gitRepoUtils.js.map