Merge pull request #255 from aminya/skip-apt [skip ci]

This commit is contained in:
Amin Yahyaabadi 2024-08-08 16:30:30 -07:00 committed by GitHub
commit b86c009455
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 171 additions and 115 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -31,8 +31,8 @@
"build.packages": "pnpm run -r build",
"build.parcel": "cross-env NODE_ENV=production parcel build && run-s build.babel && shx cp -r ./dist/actions/* ./dist/modern",
"build.babel": "babel ./dist --out-dir dist --plugins @upleveled/babel-plugin-remove-node-prefix --plugins @babel/plugin-transform-private-methods --compact --no-babelrc --source-maps true",
"bump": "ncu -u -x numerous,execa,prettier,@types/node,eslint,@types/eslint && pnpm update && pnpx typesync",
"clean": "shx rm -rf ./dist ./exe ./packages/*/dist/ ./.parcel-cache && shx mkdir -p ./dist/legacy ./dist/actions ./dist/modern ",
"bump": "ncu -u -x numerous,execa,prettier,@types/node,eslint,@types/eslint && pnpm update && pnpx typesync && pnpm run clean",
"clean": "shx rm -rf ./dist ./exe ./packages/*/dist/ && shx mkdir -p ./dist/legacy ./dist/actions ./dist/modern ",
"copy.matchers": "run-p copy.matchers.legacy copy.matchers.actions",
"copy.matchers.legacy": "shx cp ./src/gcc/gcc_matcher.json ./dist/legacy/ && shx cp ./src/msvc/msvc_matcher.json ./dist/legacy/ && shx cp ./src/python/python_matcher.json ./dist/legacy/ && shx cp ./src/llvm/llvm_matcher.json ./dist/legacy/",
"copy.matchers.actions": "shx cp ./src/gcc/gcc_matcher.json ./dist/actions/ && shx cp ./src/msvc/msvc_matcher.json ./dist/actions/ && shx cp ./src/python/python_matcher.json ./dist/actions/ && shx cp ./src/llvm/llvm_matcher.json ./dist/actions/",

View File

@ -4,7 +4,7 @@ import { execa } from "execa"
import { chmod, readFile, writeFile } from "fs/promises"
import { DEFAULT_TIMEOUT } from "../installTool"
import { addPath } from "../utils/env/addEnv"
import { hasNala, isPackageInstalled, setupAptPack } from "../utils/setup/setupAptPack"
import { hasNala, isPackageRegexInstalled, setupAptPack } from "../utils/setup/setupAptPack"
import type { InstallationInfo } from "../utils/setup/setupBin"
export enum LLVMPackages {
@ -87,7 +87,7 @@ async function removeConflictingPackages(givenScript: string) {
await Promise.all(
conflictingPackages.map(async (pack) => {
const installingPack = pack.replace("$LLVM_VERSION", "*")
if (await isPackageInstalled(installingPack)) {
if (await isPackageRegexInstalled(installingPack)) {
info(`Removing conflicting package ${installingPack}`)
script = script.replace(pack, "")
}

View File

@ -21,6 +21,8 @@ export async function setupNala(version: string, _setupDir: string, _arch: strin
return { binDir }
}
await setupAptPack([{ name: "python3-apt" }])
// https://gitlab.com/volian/nala/-/wikis/Installation
const keyFileName = await addAptKeyViaDownload(
"volian-archive-nala.gpg",

View File

@ -35,36 +35,41 @@ export async function setupAptPack(packages: AptPackage[], update = false): Prom
process.env.DEBIAN_FRONTEND = "noninteractive"
if (!didUpdate || update) {
// Update the repos if needed
if (update) {
updateRepos(apt)
didUpdate = true
}
// Add the repos if needed
await addRepositories(apt, packages)
// Qualify the packages into full package name/version
let qualifiedPacks = await Promise.all(packages.map((pack) => getAptArg(pack.name, pack.version)))
// find the packages that are not installed
qualifiedPacks = await Promise.all(qualifiedPacks.filter(async (pack) => !(await isPackageInstalled(pack))))
if (qualifiedPacks.length === 0) {
info("All packages are already installed")
return { binDir: "/usr/bin/" }
}
// Initialize apt if needed
if (!didInit) {
await initApt(apt)
didInit = true
}
const allRepositories = [...new Set(packages.flatMap((pack) => pack.repositories ?? []))]
if (allRepositories.length !== 0) {
for (const repo of allRepositories) {
// eslint-disable-next-line no-await-in-loop
execRootSync("add-apt-repository", ["-y", repo])
}
updateRepos(apt)
}
const aptArgs = await Promise.all(packages.map((pack) => getAptArg(pack.name, pack.version)))
// Install
try {
execRootSync(apt, ["install", "--fix-broken", "-y", ...aptArgs])
execRootSync(apt, ["install", "--fix-broken", "-y", ...qualifiedPacks])
} catch (err) {
if ("stderr" in (err as ExecaError)) {
const stderr = (err as ExecaError).stderr
if (retryErrors.some((error) => stderr.includes(error))) {
warning(`Failed to install packages ${aptArgs}. Retrying...`)
execRootSync(apt, ["install", "--fix-broken", "-y", ...aptArgs])
warning(`Failed to install packages ${qualifiedPacks}. Retrying...`)
execRootSync(apt, ["install", "--fix-broken", "-y", ...qualifiedPacks])
}
} else {
throw err
@ -81,6 +86,23 @@ export enum AptPackageType {
None = 3,
}
async function addRepositories(apt: string, packages: AptPackage[]) {
const allRepositories = [...new Set(packages.flatMap((pack) => pack.repositories ?? []))]
if (allRepositories.length !== 0) {
if (!didInit) {
await initApt(apt)
didInit = true
}
await installAddAptRepo()
for (const repo of allRepositories) {
// eslint-disable-next-line no-await-in-loop
execRootSync("add-apt-repository", ["-y", repo])
}
updateRepos(apt)
didUpdate = true
}
}
export async function aptPackageType(name: string, version: string | undefined): Promise<AptPackageType> {
if (version !== undefined && version !== "") {
const { stdout } = await execa("apt-cache", [
@ -113,6 +135,13 @@ export async function aptPackageType(name: string, version: string | undefined):
// ignore
}
// If apt-cache fails, update the repos and try again
if (!didUpdate) {
updateRepos(getApt())
didUpdate = true
return aptPackageType(name, version)
}
return AptPackageType.None
}
@ -148,17 +177,27 @@ function updateRepos(apt: string) {
execRootSync(apt, apt !== "nala" ? ["update", "-y"] : ["update"])
}
/** Install apt utils and certificates (usually missing from docker containers) */
async function installAddAptRepo() {
if (await isPackageInstalled("software-properties-common")) {
return
}
execRootSync("apt-get", ["install", "-y", "--fix-broken", "software-properties-common"])
}
/** Install gnupg and certificates (usually missing from docker containers) */
async function initApt(apt: string) {
execRootSync(apt, [
"install",
"--fix-broken",
"-y",
"software-properties-common",
"apt-utils",
"ca-certificates",
"gnupg",
])
// Update the repos if needed
if (!didUpdate) {
updateRepos(apt)
didUpdate = true
}
const toInstall = ["ca-certificates", "gnupg", "apt-utils"].filter(async (pack) => !(await isPackageInstalled(pack)))
if (toInstall.length !== 0) {
execRootSync(apt, ["install", "-y", "--fix-broken", ...toInstall])
}
const promises: Promise<string | void>[] = [
addAptKeyViaServer(["3B4FE6ACC0B21F32", "40976EAF437D05B5"], "setup-cpp-ubuntu-archive.gpg"),
addAptKeyViaServer(["1E9377A2BA9EF27F"], "launchpad-toolchain.gpg"),
@ -229,7 +268,22 @@ export async function updateAptAlternatives(name: string, path: string, priority
}
}
export async function isPackageInstalled(regexp: string) {
export async function isPackageInstalled(pack: string) {
try {
// check if a package is installed
const { stdout } = await execa("dpkg", ["-s", pack])
if (typeof stdout !== "string") {
return false
}
const lines = stdout.split("\n")
// check if the output contains a line that starts with "Status: install ok installed"
return lines.some((line) => line.startsWith("Status: install ok installed"))
} catch {
return false
}
}
export async function isPackageRegexInstalled(regexp: string) {
try {
// check if a package matching the regexp is installed
const { stdout } = await execa("dpkg", ["-l", regexp])