"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const execa = require("execa");
const pnpm_logger_1 = require("pnpm-logger");
const gitLogger = pnpm_logger_1.default('git-logger');
let tryGitHubApi = true;
function resolveGit(parsedSpec, opts) {
    return __awaiter(this, void 0, void 0, function* () {
        const isGitHubHosted = parsedSpec.type === 'git' && parsedSpec.hosted && parsedSpec.hosted.type === 'github';
        if (!isGitHubHosted || isSsh(parsedSpec.rawSpec)) {
            const commit = yield resolveRef(parsedSpec.fetchSpec, parsedSpec.gitCommittish);
            const resolution = {
                type: 'git',
                repo: parsedSpec.fetchSpec,
                commit,
            };
            return {
                id: parsedSpec.fetchSpec
                    .replace(/^.*:\/\/(git@)?/, '')
                    .replace(/:/g, '+')
                    .replace(/\.git$/, '') + '/' + commit,
                resolution,
            };
        }
        const parts = normalizeRepoUrl(parsedSpec).split('#');
        const repo = parts[0];
        const ghSpec = {
            user: parsedSpec.hosted.user,
            project: parsedSpec.hosted.project,
            ref: parsedSpec.hosted.committish || 'HEAD',
        };
        let commitId;
        if (tryGitHubApi) {
            try {
                commitId = yield tryResolveViaGitHubApi(ghSpec, opts.got);
            }
            catch (err) {
                gitLogger.warn({
                    message: `Error while trying to resolve ${parsedSpec.fetchSpec} via GitHub API`,
                    err,
                });
                // if it fails once, don't bother retrying for other packages
                tryGitHubApi = false;
                commitId = yield resolveRef(repo, ghSpec.ref);
            }
        }
        else {
            commitId = yield resolveRef(repo, ghSpec.ref);
        }
        const resolution = {
            tarball: `https://codeload.github.com/${ghSpec.user}/${ghSpec.project}/tar.gz/${commitId}`,
        };
        return {
            id: ['github.com', ghSpec.user, ghSpec.project, commitId].join('/'),
            resolution,
        };
    });
}
exports.default = resolveGit;
function resolveRef(repo, ref) {
    return __awaiter(this, void 0, void 0, function* () {
        const result = yield execa('git', ['ls-remote', '--refs', repo, ref]);
        // should output something like:
        //   572bc3d4e16220c2e986091249e62a5913294b25    	refs/heads/master
        // if no ref was found, assume that ref is the commit ID
        if (!result.stdout)
            return ref;
        return result.stdout.match(/^[a-z0-9]+/)[0];
    });
}
function normalizeRepoUrl(parsedSpec) {
    const hosted = parsedSpec.hosted; // tslint:disable-line
    return hosted.getDefaultRepresentation() == 'shortcut' ? hosted.git() : hosted.toString();
}
function isSsh(gitSpec) {
    return gitSpec.substr(0, 10) === 'git+ssh://'
        || gitSpec.substr(0, 4) === 'git@';
}
/**
 * Resolves a 'hosted' package hosted on 'github'.
 */
function tryResolveViaGitHubApi(spec, got) {
    return __awaiter(this, void 0, void 0, function* () {
        const url = [
            'https://api.github.com/repos',
            spec.user,
            spec.project,
            'commits',
            spec.ref
        ].join('/');
        // TODO: investigate what should be the correct registry path here
        const body = yield got.getJSON(url, url);
        return body.sha;
    });
}
//# sourceMappingURL=git.js.map