"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.registryTag = exports.registryImageId = exports.registryDelete = exports.registryCopy = exports.execCrane = void 0;
const tslib_1 = require("tslib");
/*
 * Copyright 2020 Unbounded Systems, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const utils_1 = require("@adpt/utils");
const execa_1 = tslib_1.__importDefault(require("execa"));
const path_1 = tslib_1.__importDefault(require("path"));
const cli_1 = require("./cli");
const craneVersion = "v0.1.3";
function cranePlatform() {
    switch (process.platform) {
        case "darwin":
            return "Darwin";
        case "linux":
            return "Linux";
        case "win32":
        // TODO: No release is published, but building from source on
        // Windows seems to work fine.
        // Waiting for https://github.com/google/go-containerregistry/pull/780
        default:
            throw new Error(`Platform ${process.platform} unsupported by crane releases`);
    }
}
function craneArch() {
    switch (process.arch) {
        case "x64":
            return "x86_64";
        case "x32":
            return "i386";
        default:
            throw new Error(`CPU architecture ${process.arch} unsupported by crane releases`);
    }
}
async function cranePath() {
    const url = `https://github.com/google/go-containerregistry/releases/download/${craneVersion}/go-containerregistry_${cranePlatform()}_${craneArch()}.tar.gz`;
    let filename = "crane";
    if (process.platform === "win32")
        filename += ".exe";
    const { dir } = await utils_1.fetchToCache({
        name: "crane",
        untar: true,
        url,
        version: craneVersion,
        fileList: [filename],
    });
    return path_1.default.join(dir, filename);
}
/** @internal */
async function execCrane(args) {
    const crane = await cranePath();
    const cmdDebug = cli_1.debugOut.enabled ? cli_1.debugOut.extend((cli_1.cmdId()).toString()) :
        cli_1.debug.enabled ? cli_1.debug :
            null;
    if (cmdDebug)
        cmdDebug(`Running: ${crane} ${args.join(" ")}`);
    try {
        const ret = execa_1.default(crane, args, { all: true });
        if (cli_1.debugOut.enabled && cmdDebug) {
            cli_1.streamToDebug(ret.stdout, cmdDebug);
            cli_1.streamToDebug(ret.stderr, cmdDebug);
        }
        return await ret;
    }
    catch (e) {
        if (e.all)
            e.message = `${e.shortMessage}\n${e.all}`;
        throw e;
    }
}
exports.execCrane = execCrane;
const copyDigestRe = /digest: +(sha\d+:[0-9a-f]+) /m;
async function registryCopy(from, to) {
    const { stderr } = await execCrane(["copy", from, to]);
    const m = stderr.match(copyDigestRe);
    const digest = m && m[1];
    if (!digest)
        throw new Error(`Container image copy did not return resulting digest. Output:\n${stderr}\n`);
    return { digest };
}
exports.registryCopy = registryCopy;
async function registryDelete(nameTag) {
    await execCrane(["delete", nameTag]);
}
exports.registryDelete = registryDelete;
async function registryImageId(nameTag) {
    const { stdout } = await execCrane(["manifest", nameTag]);
    let manifest;
    try {
        manifest = JSON.parse(stdout);
    }
    catch (err) {
        throw new Error(`Unable to parse JSON output from 'crane manifest '${nameTag}': ${err.message}`);
    }
    const id = manifest && manifest.config && manifest.config.digest;
    if (!id || typeof id !== "string") {
        throw new Error(`Cannot get image ID for '${nameTag}': Unable to find config.digest`);
    }
    return id;
}
exports.registryImageId = registryImageId;
async function registryTag({ existing, newTag }) {
    await execCrane(["tag", existing, newTag]);
}
exports.registryTag = registryTag;
//# sourceMappingURL=image-tools.js.map