"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRuleDefinition = exports.extractDepFromTarget = exports.supportedRulesRegex = exports.dockerDependency = exports.httpDependency = exports.goDependency = exports.gitDependency = exports.parseArchiveUrl = void 0;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const dequal_1 = require("dequal");
const github_url_from_git_1 = tslib_1.__importDefault(require("github-url-from-git"));
const logger_1 = require("../../../logger");
const regex_1 = require("../../../util/regex");
const url_1 = require("../../../util/url");
const docker_1 = require("../../datasource/docker");
const github_releases_1 = require("../../datasource/github-releases");
const github_tags_1 = require("../../datasource/github-tags");
const go_1 = require("../../datasource/go");
const docker_2 = require("../../versioning/docker");
function parseArchiveUrl(urlString) {
    if (!urlString) {
        return null;
    }
    const url = (0, url_1.parseUrl)(urlString);
    if (!url || url.host !== 'github.com' || !url.pathname) {
        return null;
    }
    const path = url.pathname.split('/').slice(1);
    const repo = path[0] + '/' + path[1];
    let datasource = '';
    let currentValue = null;
    if (path[2] === 'releases' && path[3] === 'download') {
        datasource = github_releases_1.GithubReleasesDatasource.id;
        currentValue = path[4];
    }
    if (path[2] === 'archive') {
        datasource = github_tags_1.GithubTagsDatasource.id;
        currentValue = path[3];
        // Strip archive extension to get hash or tag.
        // Tolerates formats produced by Git(Hub|Lab) and allowed by http_archive
        // Note: Order matters in suffix list to strip, e.g. .tar.gz.
        for (const extension of ['.gz', '.bz2', '.xz', '.tar', '.tgz', '.zip']) {
            if (currentValue.endsWith(extension)) {
                currentValue = currentValue.slice(0, -extension.length);
            }
        }
    }
    if (currentValue) {
        return { datasource, repo, currentValue };
    }
    return null;
}
exports.parseArchiveUrl = parseArchiveUrl;
function gitDependency({ rule: depType, name: depName, tag: currentValue, commit: currentDigest, remote, }) {
    let dep = null;
    if (depType === 'git_repository' &&
        is_1.default.string(depName) &&
        (is_1.default.string(currentValue) || is_1.default.string(currentDigest)) &&
        is_1.default.string(remote)) {
        dep = {
            datasource: github_releases_1.GithubReleasesDatasource.id,
            depType,
            depName,
        };
        if (is_1.default.string(currentValue)) {
            dep.currentValue = currentValue;
        }
        if (is_1.default.string(currentDigest)) {
            dep.currentDigest = currentDigest;
        }
        // TODO: Check if we really need to use parse here or if it should always be a plain https url (#9605)
        const packageName = (0, github_url_from_git_1.default)(remote)?.substring('https://github.com/'.length);
        // istanbul ignore else
        if (packageName) {
            dep.packageName = packageName;
        }
        else {
            dep.skipReason = 'unsupported-remote';
        }
    }
    return dep;
}
exports.gitDependency = gitDependency;
function goDependency({ rule: depType, name: depName, tag: currentValue, commit: currentDigest, importpath: packageName, remote, }) {
    let dep = null;
    if (depType === 'go_repository' &&
        is_1.default.string(depName) &&
        (is_1.default.string(currentValue) || is_1.default.string(currentDigest)) &&
        is_1.default.string(packageName)) {
        dep = {
            datasource: go_1.GoDatasource.id,
            depType,
            depName,
            packageName,
        };
        if (is_1.default.string(currentValue)) {
            dep.currentValue = currentValue;
        }
        if (is_1.default.string(currentDigest)) {
            dep.currentValue = 'v0.0.0';
            dep.currentDigest = currentDigest;
            dep.currentDigestShort = currentDigest.substring(0, 7);
            dep.digestOneAndOnly = true;
        }
        if (is_1.default.string(remote)) {
            const remoteMatch = (0, regex_1.regEx)(/https:\/\/github\.com(?:.*\/)(([a-zA-Z]+)([-])?([a-zA-Z]+))/).exec(remote);
            if (remoteMatch && remoteMatch[0].length === remote.length) {
                dep.packageName = remote.replace('https://', '');
            }
            else {
                dep.skipReason = 'unsupported-remote';
            }
        }
    }
    return dep;
}
exports.goDependency = goDependency;
function httpDependency({ rule: depType, name: depName, url, urls, sha256, }) {
    let dep = null;
    if ((depType === 'http_archive' || depType === 'http_file') &&
        is_1.default.string(depName) &&
        is_1.default.string(sha256)) {
        let parsedUrl = null;
        if (is_1.default.string(url)) {
            parsedUrl = parseArchiveUrl(url);
        }
        else if (is_1.default.array(urls, is_1.default.string)) {
            for (const u of urls) {
                parsedUrl = parseArchiveUrl(u);
                if (parsedUrl) {
                    break;
                }
            }
        }
        if (parsedUrl) {
            dep = {
                datasource: parsedUrl.datasource,
                depType,
                depName,
                packageName: parsedUrl.repo,
            };
            if ((0, regex_1.regEx)(/^[a-f0-9]{40}$/i).test(parsedUrl.currentValue)) {
                dep.currentDigest = parsedUrl.currentValue;
            }
            else {
                dep.currentValue = parsedUrl.currentValue;
            }
        }
    }
    return dep;
}
exports.httpDependency = httpDependency;
function dockerDependency({ rule: depType, name: depName, tag: currentValue, digest: currentDigest, repository: packageName, registry, }) {
    let dep = null;
    if (depType === 'container_pull' &&
        is_1.default.string(depName) &&
        is_1.default.string(currentValue) &&
        is_1.default.string(currentDigest) &&
        is_1.default.string(packageName) &&
        is_1.default.string(registry)) {
        dep = {
            datasource: docker_1.DockerDatasource.id,
            versioning: docker_2.id,
            depType,
            depName,
            packageName,
            currentValue,
            currentDigest,
            registryUrls: [registry],
        };
    }
    return dep;
}
exports.dockerDependency = dockerDependency;
const dependencyExtractorRegistry = {
    git_repository: gitDependency,
    go_repository: goDependency,
    http_archive: httpDependency,
    http_file: httpDependency,
    container_pull: dockerDependency,
};
const supportedRules = Object.keys(dependencyExtractorRegistry);
exports.supportedRulesRegex = (0, regex_1.regEx)(`^${supportedRules.join('|')}$`);
function extractDepFromTarget(target) {
    const dependencyExtractor = dependencyExtractorRegistry[target.rule];
    if (!dependencyExtractor) {
        logger_1.logger.warn(`Bazel dependency extractor function not found for ${target.rule}`);
        return null;
    }
    return dependencyExtractor(target);
}
exports.extractDepFromTarget = extractDepFromTarget;
// TODO: remove it (#9667)
function getRuleDefinition(content, meta, ruleIndex) {
    let result = null;
    const rulePath = [ruleIndex];
    const ruleMeta = meta.find(({ path }) => (0, dequal_1.dequal)(path, rulePath));
    if (ruleMeta) {
        const { data: { offset, length }, } = ruleMeta;
        const begin = offset;
        const end = offset + length;
        result = content.slice(begin, end);
    }
    return result;
}
exports.getRuleDefinition = getRuleDefinition;
//# sourceMappingURL=common.js.map