"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GoDirectDatasource = void 0;
const tslib_1 = require("tslib");
const logger_1 = require("../../../logger");
const decorator_1 = require("../../../util/cache/package/decorator");
const regex_1 = require("../../../util/regex");
const bitbucket_tags_1 = require("../bitbucket-tags");
const datasource_1 = require("../datasource");
const git_tags_1 = require("../git-tags");
const gitea_tags_1 = require("../gitea-tags");
const github_tags_1 = require("../github-tags");
const gitlab_tags_1 = require("../gitlab-tags");
const base_1 = require("./base");
const common_1 = require("./common");
/**
 * This function tries to select tags with longest prefix could be constructed from `packageName`.
 *
 * For package named `example.com/foo/bar/baz/qux`, it will try to detect tags with following prefixes:
 *
 *   - `foo/bar/baz/qux/vX.Y.Z`
 *   - `bar/baz/qux/vX.Y.Z`
 *   - `baz/qux/vX.Y.Z`
 *   - `qux/vX.Y.Z`
 *
 * If none of the following is found, it falls back to simply returning all tags like `vX.Y.Z`.
 */
function filterByPrefix(packageName, releases) {
    const nameParts = packageName
        .replace((0, regex_1.regEx)(/\/v\d+$/), '')
        .split('/')
        .slice(1);
    const submoduleReleases = [];
    while (nameParts.length) {
        const prefix = `${nameParts.join('/')}/`;
        for (const release of releases) {
            if (!release.version.startsWith(prefix)) {
                continue;
            }
            const normalizedVersion = release.version.replace(prefix, '');
            if (!normalizedVersion.match((0, regex_1.regEx)(/^v\d[^/]*/))) {
                continue;
            }
            release.version = release.version.replace(prefix, '');
            submoduleReleases.push(release);
        }
        if (submoduleReleases.length) {
            return submoduleReleases;
        }
        nameParts.shift();
    }
    return releases.filter((release) => release.version.startsWith('v'));
}
class GoDirectDatasource extends datasource_1.Datasource {
    static id = 'go-direct';
    git;
    gitea = new gitea_tags_1.GiteaTagsDatasource();
    github;
    gitlab;
    bitbucket;
    constructor() {
        super(GoDirectDatasource.id);
        this.git = new git_tags_1.GitTagsDatasource();
        this.github = new github_tags_1.GithubTagsDatasource();
        this.gitlab = new gitlab_tags_1.GitlabTagsDatasource();
        this.bitbucket = new bitbucket_tags_1.BitbucketTagsDatasource();
    }
    /**
     * go.getReleases
     *
     * This datasource resolves a go module URL into its source repository
     *  and then fetch it if it is on GitHub.
     *
     * This function will:
     *  - Determine the source URL for the module
     *  - Call the respective getReleases in github/gitlab to retrieve the tags
     *  - Filter module tags according to the module path
     */
    async getReleases(config) {
        const { packageName } = config;
        let res = null;
        logger_1.logger.trace(`go.getReleases(${packageName})`);
        const source = await base_1.BaseGoDatasource.getDatasource(packageName);
        if (!source) {
            logger_1.logger.info({ packageName }, 'Unsupported go host - cannot look up versions');
            return null;
        }
        switch (source.datasource) {
            case git_tags_1.GitTagsDatasource.id: {
                res = await this.git.getReleases(source);
                break;
            }
            case gitea_tags_1.GiteaTagsDatasource.id: {
                res = await this.gitea.getReleases(source);
                break;
            }
            case github_tags_1.GithubTagsDatasource.id: {
                res = await this.github.getReleases(source);
                break;
            }
            case gitlab_tags_1.GitlabTagsDatasource.id: {
                res = await this.gitlab.getReleases(source);
                break;
            }
            case bitbucket_tags_1.BitbucketTagsDatasource.id: {
                res = await this.bitbucket.getReleases(source);
                break;
            }
            /* istanbul ignore next: can never happen, makes lint happy */
            default: {
                return null;
            }
        }
        // istanbul ignore if
        if (!res) {
            return null;
        }
        const sourceUrl = (0, common_1.getSourceUrl)(source) ?? null;
        res.releases = filterByPrefix(packageName, res.releases);
        return { ...res, sourceUrl };
    }
}
exports.GoDirectDatasource = GoDirectDatasource;
tslib_1.__decorate([
    (0, decorator_1.cache)({
        namespace: `datasource-${GoDirectDatasource.id}`,
        key: ({ packageName }) => packageName,
    })
], GoDirectDatasource.prototype, "getReleases", null);
//# sourceMappingURL=releases-direct.js.map