"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 logger_1 = require("@pnpm/logger");
const dint = require("dint");
const execa = require("execa");
const fs = require("mz/fs");
const path = require("path");
const rimraf = require("rimraf-then");
const unpackStream = require("unpack-stream");
const errorTypes_1 = require("./errorTypes");
const loggers_1 = require("./loggers");
const gitLogger = logger_1.default('git');
const fetchLogger = logger_1.default('fetch');
function fetchResolution(resolution, target, opts) {
    return __awaiter(this, void 0, void 0, function* () {
        switch (resolution.type) {
            case undefined:
                const dist = {
                    integrity: resolution.integrity,
                    registry: resolution.registry,
                    tarball: resolution.tarball,
                };
                return yield fetchFromTarball(target, dist, opts);
            case 'git':
                return yield clone(resolution.repo, resolution.commit, target);
            default: {
                throw new Error(`Fetching for dependency type "${resolution.type}" is not supported`);
            }
        }
    });
}
exports.default = fetchResolution;
/**
 * clone a git repository.
 */
function clone(repo, commitId, dest) {
    return __awaiter(this, void 0, void 0, function* () {
        yield execGit(['clone', repo, dest]);
        yield execGit(['checkout', commitId], { cwd: dest });
        // removing /.git to make directory integrity calculation faster
        yield rimraf(path.join(dest, '.git'));
        const dirIntegrity = yield dint.from(dest);
        return {
            headers: dirIntegrity,
            integrityPromise: Promise.resolve(dirIntegrity),
        };
    });
}
function prefixGitArgs() {
    return process.platform === 'win32' ? ['-c', 'core.longpaths=true'] : [];
}
function execGit(args, opts) {
    gitLogger.debug(`executing git with args ${args}`);
    const fullArgs = prefixGitArgs().concat(args || []);
    return execa('git', fullArgs, opts);
}
function fetchFromTarball(dir, dist, opts) {
    if (dist.tarball.startsWith('file:')) {
        dist = Object.assign({}, dist, { tarball: path.join(opts.prefix, dist.tarball.slice(5)) });
        return fetchFromLocalTarball(dir, dist);
    }
    else {
        return fetchFromRemoteTarball(dir, dist, opts);
    }
}
exports.fetchFromTarball = fetchFromTarball;
function fetchFromRemoteTarball(dir, dist, opts) {
    return __awaiter(this, void 0, void 0, function* () {
        const localTarballPath = path.join(opts.storePath, opts.pkgId, 'packed.tgz');
        try {
            const index = yield fetchFromLocalTarball(dir, {
                integrity: dist.integrity,
                tarball: localTarballPath,
            });
            fetchLogger.debug(`finish ${dist.integrity} ${dist.tarball}`);
            return index;
        }
        catch (err) {
            if (err.code !== 'ENOENT')
                throw err;
            if (opts.offline) {
                throw new errorTypes_1.PnpmError('NO_OFFLINE_TARBALL', `Could not find ${localTarballPath} in local registry mirror ${opts.storePath}`);
            }
            return yield opts.got.download(dist.tarball, localTarballPath, {
                integrity: dist.integrity,
                onProgress: (downloaded) => {
                    loggers_1.progressLogger.debug({ status: 'fetching_progress', pkgId: opts.pkgId, downloaded });
                },
                onStart: (size, attempt) => {
                    loggers_1.progressLogger.debug({ status: 'fetching_started', pkgId: opts.pkgId, size, attempt });
                },
                registry: dist.registry,
                unpackTo: dir,
            });
        }
    });
}
exports.fetchFromRemoteTarball = fetchFromRemoteTarball;
function fetchFromLocalTarball(dir, dist) {
    return __awaiter(this, void 0, void 0, function* () {
        return yield unpackStream.local(fs.createReadStream(dist.tarball), dir);
    });
}
//# sourceMappingURL=fetchResolution.js.map