feat: parallelize the apt package installation chunks

This commit is contained in:
Amin Yahyaabadi 2022-11-22 21:33:06 -08:00
parent eea16aa8c7
commit dac72316df
21 changed files with 72 additions and 59 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

View File

@ -36,7 +36,7 @@ export async function setupBazel(version: string, _setupDir: string, _arch: stri
"-c",
`echo "deb [arch=amd64 signed-by=${keyFileName}] https://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list`,
])
return setupAptPack("bazel", version, [], true)
return setupAptPack([{ name: "bazel", version }], true)
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -22,7 +22,7 @@ export function setupCcache(version: string, _setupDir: string, _arch: string) {
} else if (hasDnf()) {
return setupDnfPack("ccache", version)
} else if (isUbuntu()) {
return setupAptPack("ccache", version)
return setupAptPack([{ name: "ccache", version }])
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -25,7 +25,7 @@ export async function setupCppcheck(version: string | undefined, _setupDir: stri
} else if (hasDnf()) {
return setupDnfPack("ccache", version)
} else if (isUbuntu()) {
return setupAptPack("cppcheck", version)
return setupAptPack([{ name: "cppcheck", version }])
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -67,7 +67,7 @@ export async function setupDoxygen(version: string, setupDir: string, arch: stri
} else if (hasDnf()) {
return setupDnfPack("doxygen", version)
} else if (isUbuntu()) {
installationInfo = await setupAptPack("doxygen", version)
installationInfo = await setupAptPack([{ name: "doxygen", version }])
} else {
throw new Error(`Unsupported linux distributions`)
}
@ -75,10 +75,10 @@ export async function setupDoxygen(version: string, setupDir: string, arch: stri
try {
// doxygen on stable Ubuntu repositories is very old. So, we use get the binary from the website itself
installationInfo = await setupBin("doxygen", version, getDoxygenPackageInfo, setupDir, arch)
await setupAptPack("libclang-cpp9")
await setupAptPack([{ name: "libclang-cpp9" }])
} catch (err) {
notice(`Failed to download doxygen binary. ${err}. Falling back to apt-get.`)
installationInfo = await setupAptPack("doxygen", undefined)
installationInfo = await setupAptPack([{ name: "doxygen" }])
}
} else {
throw new Error(`Unsupported linux distributions`)

View File

@ -96,15 +96,17 @@ export async function setupGcc(version: string, setupDir: string, arch: string)
setupDnfPack("gcc-c++", version)
setupDnfPack("libstdc++-devel", undefined)
} else if (isUbuntu()) {
await setupAptPack("gcc", version, ["ppa:ubuntu-toolchain-r/test"])
installationInfo = await setupAptPack("g++", version, [])
installationInfo = await setupAptPack([
{ name: "gcc", version, repositories: ["ppa:ubuntu-toolchain-r/test"] },
{ name: "g++", version, repositories: ["ppa:ubuntu-toolchain-r/test"] },
])
}
} else {
info(`Install g++-multilib because gcc for ${arch} was requested`)
if (isArch()) {
setupPacmanPack("gcc-multilib", version)
} else if (isUbuntu()) {
await setupAptPack("gcc-multilib", version, ["ppa:ubuntu-toolchain-r/test"])
await setupAptPack([{ name: "gcc-multilib", version, repositories: ["ppa:ubuntu-toolchain-r/test"] }])
}
}
break

View File

@ -25,7 +25,7 @@ export async function setupGraphviz(version: string, _setupDir: string, _arch: s
} else if (hasDnf()) {
return setupDnfPack("graphviz", version)
} else if (isUbuntu()) {
return setupAptPack("graphviz", version)
return setupAptPack([{ name: "graphviz", version }])
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -50,8 +50,7 @@ async function buildKcov(file: string, dest: string) {
setupDnfPack("libdwarf-devel")
setupDnfPack("libcurl-devel")
} else if (isUbuntu()) {
await setupAptPack("libdw-dev")
await setupAptPack("libcurl4-openssl-dev")
await setupAptPack([{ name: "libdw-dev" }, { name: "libcurl4-openssl-dev" }])
}
}
const buildDir = join(out, "build")
@ -102,7 +101,7 @@ export async function setupKcov(versionGiven: string, setupDir: string, arch: st
} else if (hasDnf()) {
setupDnfPack("binutils")
} else if (isUbuntu()) {
await setupAptPack("libbinutils")
await setupAptPack([{ name: "libbinutils" }])
}
return installationInfo
} else {

View File

@ -52,9 +52,9 @@ async function setupLLVMDeps(arch: string, version: string) {
if (isUbuntu()) {
const majorVersion = parseInt(version.split(".")[0], 10)
if (majorVersion <= 10) {
await setupAptPack("libtinfo5")
await setupAptPack([{ name: "libtinfo5" }])
} else {
await setupAptPack("libtinfo-dev")
await setupAptPack([{ name: "libtinfo-dev" }])
}
}
// TODO: install libtinfo on other distros

View File

@ -25,7 +25,7 @@ export async function setupMake(version: string, _setupDir: string, _arch: strin
} else if (hasDnf()) {
return setupDnfPack("make", version)
} else if (isUbuntu()) {
return setupAptPack("make", version)
return setupAptPack([{ name: "make", version }])
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -33,12 +33,12 @@ export async function setupNala(version: string, _setupDir: string, _arch: strin
try {
if (version !== "legacy") {
await setupAptPack("nala", undefined, [], true)
await setupAptPack([{ name: "nala" }], true)
} else {
await setupAptPack("nala-legacy", undefined, [], true)
await setupAptPack([{ name: "nala-legacy" }], true)
}
} catch (err) {
await setupAptPack("nala-legacy", undefined, [], true)
await setupAptPack([{ name: "nala-legacy" }], true)
}
binDir = "/usr/bin" // eslint-disable-line require-atomic-updates

View File

@ -33,7 +33,7 @@ export async function setupPowershell(version: string | undefined, _setupDir: st
])
return setupDnfPack("powershell", version)
} else if (isUbuntu()) {
await setupAptPack("curl")
await setupAptPack([{ name: "curl" }])
const ubuntuVerSplitted = (await ubuntuVersion())!
const ubuntuVersionString = `${ubuntuVerSplitted[0]}.0${ubuntuVerSplitted[1]}`
@ -53,7 +53,7 @@ export async function setupPowershell(version: string | undefined, _setupDir: st
// `echo "deb [arch=amd64 signed-by=${keyFileName}] https://packages.microsoft.com/repos/microsoft-debian-bullseye-prod bullseye main" > /etc/apt/sources.list.d/microsoft.list`,
// ])
return setupAptPack("powershell", version, [], true)
return setupAptPack([{ name: "powershell", version }], true)
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -69,8 +69,7 @@ export async function setupPythonViaSystem(
installInfo = setupDnfPack("python3", version)
setupDnfPack("python3-pip")
} else if (isUbuntu()) {
installInfo = await setupAptPack("python3", version)
await setupAptPack("python3-pip")
installInfo = await setupAptPack([{ name: "python3", version }, { name: "python3-pip" }])
} else {
throw new Error(`Unsupported linux distributions`)
}
@ -118,7 +117,7 @@ export async function setupPythonAndPip(): Promise<string> {
} else if (hasDnf()) {
setupDnfPack("python3-pip")
} else if (isUbuntu()) {
await setupAptPack("python3-pip")
await setupAptPack([{ name: "python3-pip" }])
}
}

View File

@ -23,7 +23,7 @@ export function setupSevenZip(version: string, _setupDir: string, _arch: string)
setupDnfPack("p7zip", version)
return setupDnfPack("p7zip-plugins", version)
} else if (isUbuntu()) {
return setupAptPack("p7zip-full", version)
return setupAptPack([{ name: "p7zip-full", version }])
}
throw new Error(`Unsupported linux distribution`)
}

View File

@ -8,7 +8,7 @@ export async function ubuntuVersion(): Promise<number[] | null> {
try {
if (isUbuntu()) {
if (which.sync("lsb_release", { nothrow: true }) === null) {
await setupAptPack("lsb-release")
await setupAptPack([{ name: "lsb-release" }])
}
const versionSplitted = await getUbuntuVersion()

View File

@ -8,20 +8,24 @@ import which from "which"
import pathExists from "path-exists"
import { promises as fsPromises } from "fs"
const { appendFile } = fsPromises
import execa from "execa"
let didUpdate: boolean = false
let didInit: boolean = false
export type AptPackage = {
name: string
version?: string
repositories?: string[]
}
/** A function that installs a package using apt */
export async function setupAptPack(
name: string,
version?: string,
repositories: string[] = [],
update = false
): Promise<InstallationInfo> {
export async function setupAptPack(packages: AptPackage[], update = false): Promise<InstallationInfo> {
const apt: string = getApt()
for (const { name, version } of packages) {
info(`Installing ${name} ${version ?? ""} via ${apt}`)
}
process.env.DEBIAN_FRONTEND = "noninteractive"
@ -35,27 +39,36 @@ export async function setupAptPack(
didInit = true
}
if (Array.isArray(repositories) && repositories.length !== 0) {
for (const repo of repositories) {
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", ["--update", "-y", repo])
execRootSync("add-apt-repository", ["-y", repo])
}
updateRepos(apt)
}
if (version !== undefined && version !== "") {
try {
execRootSync(apt, ["install", "--fix-broken", "-y", `${name}=${version}`])
} catch {
execRootSync(apt, ["install", "--fix-broken", "-y", `${name}-${version}`])
}
} else {
execRootSync(apt, ["install", "--fix-broken", "-y", name])
}
const aptArgs = await Promise.all(packages.map((pack) => getAptArg(pack.name, pack.version)))
execRootSync(apt, ["install", "--fix-broken", "-y", ...aptArgs])
return { binDir: "/usr/bin/" }
}
async function getAptArg(name: string, version: string | undefined) {
if (version !== undefined && version !== "") {
const { stdout } = await execa("apt-cache", ["search", "--names-only", `^${name}-${version}$`])
if (stdout.trim() !== "") {
return `${name}-${version}`
} else {
return `${name}=${version}`
}
} else {
return name
}
}
function getApt() {
let apt: string
if (which.sync("nala", { nothrow: true }) !== null) {
@ -118,7 +131,7 @@ export async function addAptKeyViaDownload(name: string, url: string) {
const fileName = `/etc/apt/trusted.gpg.d/${name}`
if (!(await pathExists(fileName))) {
initGpg()
await setupAptPack("curl", undefined)
await setupAptPack([{ name: "curl" }], undefined)
execRootSync("bash", ["-c", `curl -s ${url} | gpg --no-default-keyring --keyring gnupg-ring:${fileName} --import`])
execRootSync("chmod", ["644", fileName])
}

View File

@ -103,9 +103,7 @@ export async function setupBin(
setupDnfPack("tar")
setupDnfPack("xz")
} else if (isUbuntu()) {
await setupAptPack("unzip")
await setupAptPack("tar")
await setupAptPack("xz-utils")
await setupAptPack([{ name: "unzip" }, { name: "tar" }, { name: "xz-utils" }])
}
}
// eslint-disable-next-line require-atomic-updates

View File

@ -36,12 +36,14 @@ export async function setupVcpkg(_version: string, setupDir: string, _arch: stri
setupDnfPack("git")
setupDnfPack("pkg-config")
} else if (isUbuntu()) {
await setupAptPack("curl")
await setupAptPack("zip")
await setupAptPack("unzip")
await setupAptPack("tar")
await setupAptPack("git")
await setupAptPack("pkg-config")
await setupAptPack([
{ name: "curl" },
{ name: "zip" },
{ name: "unzip" },
{ name: "tar" },
{ name: "git" },
{ name: "pkg-config" },
])
}
}