UNPKG

setup-cpp

Version:

Install all the tools required for building and testing C++/C projects.

201 lines (174 loc) 5.72 kB
import { basename, dirname, join } from "path" import { grantUserWriteAccess } from "admina" import { info, warning } from "ci-log" import { execa } from "execa" import { mkdirp, move } from "fs-extra" import { rm } from "fs/promises" import { hasApk, installApkPack } from "setup-alpine" import { installAptPack } from "setup-apt" import which from "which" import { setupSevenZip } from "../../sevenzip/sevenzip.js" import { hasDnf } from "../env/hasDnf.js" import { isArch } from "../env/isArch.js" import { isUbuntu } from "../env/isUbuntu.js" import { setupDnfPack } from "./setupDnfPack.js" import { setupPacmanPack } from "./setupPacmanPack.js" export { extractTar, extractXar } from "@actions/tool-cache" export enum ArchiveType { Tar = 0, TarGz = 1, TarXz = 2, Zip = 3, SevenZip = 4, } export function getArchiveType(file: string): ArchiveType { const ext = file.split(".").pop() if (ext === "tar") { return ArchiveType.Tar } if (ext === "gz" || ext === "tgz") { return ArchiveType.TarGz } if (ext === "xz" || ext === "txz") { return ArchiveType.TarXz } if (ext === "zip") { return ArchiveType.Zip } if (ext === "7z" || ext === "exe") { return ArchiveType.SevenZip } // default to 7z warning(`Unknown archive type: ${ext}. Defaulting to 7z`) return ArchiveType.SevenZip } export function getExtractFunction(archiveType: ArchiveType) { switch (archiveType) { case ArchiveType.Tar: case ArchiveType.TarGz: return extractTarByExe case ArchiveType.TarXz: return extractTarByExe case ArchiveType.Zip: return extractZip default: return extract7Zip } } let sevenZip: string | undefined /// Extract 7z using 7z export async function extract7Zip(file: string, dest: string) { const name = basename(file) if (/.*\.tar\..+$/.test(name)) { // if the file is tar.*, extract the compression first const tarDir = dirname(file) await run7zip(file, tarDir) // extract the tar const tarName = name.slice(0, -3) const tarFile = join(tarDir, tarName) await run7zip(tarFile, tarDir) await rm(tarFile) // Move the extracted files to the destination const folderName = tarName.slice(0, -4) const folderPath = join(tarDir, folderName) info(`Moving ${folderPath} to ${dest}`) await move(folderPath, dest, { overwrite: true }) } else { // extract the 7z file directly await run7zip(file, dest) } return dest } async function run7zip(file: string, dest: string) { info(`7z: extracting ${file} to ${dest}`) await execa(await getSevenZip(), ["x", file, `-o${dest}`, "-y"], { stdio: "inherit" }) await grantUserWriteAccess(dest) } /// install 7z if needed async function getSevenZip() { if (sevenZip === undefined) { if (which.sync("7z", { nothrow: true }) === null) { await setupSevenZip("", "", process.arch) } // eslint-disable-next-line require-atomic-updates sevenZip = "7z" } return sevenZip } /// Extract Exe using 7z export function extractExe(file: string, dest: string) { return extract7Zip(file, dest) } /// Extract Zip using unzip or 7z export async function extractZip(file: string, dest: string) { // prefer 7z if available (faster especially on Windows) if (which.sync("7z", { nothrow: true }) !== null) { return extract7Zip(file, dest) } // if unzip is available use it (usually available on posix systems) if (which.sync("unzip", { nothrow: true }) !== null) { await execa("unzip", ["-q", file, "-d", dest], { stdio: "inherit" }) await grantUserWriteAccess(dest) return dest } // fallback to 7z (will install 7z if needed) return extract7Zip(file, dest) } export async function extractTarByExe(file: string, dest: string, stripComponents: number = 0, flags: string[] = []) { await installTarDependencies(getArchiveType(file)) try { await mkdirp(dest) } catch { // ignore } // TODO windows fails to create symlinks // https://github.com/heroku/heroku-slugs/issues/3 try { await execa("tar", ["xf", file, "-C", dest, `--strip-components=${stripComponents}`, ...flags], { stdio: "inherit", }) } catch (e) { if (process.platform === "win32" && (e as Error).message.includes("Can't create '\\\\?\\C:")) { warning(`Failed to extract symlink ${file} to ${dest}. Ignoring this symlink.`) } } await grantUserWriteAccess(dest) return dest } async function installTarDependencies(archiveType: ArchiveType) { info("Installing tar extraction dependencies") switch (archiveType) { case ArchiveType.TarGz: { if (process.platform === "linux") { if (isArch()) { await setupPacmanPack("gzip") await setupPacmanPack("tar") } else if (hasDnf()) { await setupDnfPack([{ name: "gzip" }, { name: "tar" }]) } else if (isUbuntu()) { await installAptPack([{ name: "gzip" }, { name: "tar" }]) } else if (await hasApk()) { await installApkPack([{ name: "gzip" }, { name: "tar" }]) } } break } case ArchiveType.TarXz: { if (process.platform === "linux") { if (isArch()) { await setupPacmanPack("xz") await setupPacmanPack("tar") } else if (hasDnf()) { await setupDnfPack([{ name: "xz" }, { name: "tar" }]) } else if (isUbuntu()) { await installAptPack([{ name: "xz-utils" }, { name: "tar" }]) } else if (await hasApk()) { await installApkPack([{ name: "xz" }, { name: "tar" }]) } } break } default: throw new Error(`Unsupported archive type: ${archiveType} for tar extraction`) } }