mirror of https://github.com/aminya/setup-cpp
feat!: resolve the version of installed apt package
BREAKING the return type of apt install packages now returns an array instead of a single value
This commit is contained in:
parent
cb3bbf182c
commit
e80fe67578
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
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"problemMatcher": [
|
|
||||||
{
|
|
||||||
"owner": "gcc",
|
|
||||||
"pattern": [
|
|
||||||
{
|
|
||||||
"regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
|
|
||||||
"file": 1,
|
|
||||||
"line": 2,
|
|
||||||
"column": 3,
|
|
||||||
"severity": 4,
|
|
||||||
"message": 5
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"problemMatcher": [
|
|
||||||
{
|
|
||||||
"owner": "llvm",
|
|
||||||
"pattern": [
|
|
||||||
{
|
|
||||||
"regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
|
|
||||||
"file": 1,
|
|
||||||
"line": 2,
|
|
||||||
"column": 3,
|
|
||||||
"severity": 4,
|
|
||||||
"message": 5
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"problemMatcher": [
|
|
||||||
{
|
|
||||||
"owner": "msvc",
|
|
||||||
"pattern": [
|
|
||||||
{
|
|
||||||
"regexp": "^(?:\\s+\\d+>)?(\\S.*)\\((\\d+),?(\\d+)?(?:,\\d+,\\d+)?\\)\\s*:\\s+(error|warning|info)\\s+(\\w{1,2}\\d+)\\s*:\\s*(.*)$",
|
|
||||||
"file": 1,
|
|
||||||
"line": 2,
|
|
||||||
"column": 3,
|
|
||||||
"severity": 4,
|
|
||||||
"code": 5,
|
|
||||||
"message": 6
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"problemMatcher": [
|
|
||||||
{
|
|
||||||
"owner": "python",
|
|
||||||
"pattern": [
|
|
||||||
{
|
|
||||||
"regexp": "^\\s*File\\s\\\"(.*)\\\",\\sline\\s(\\d+),\\sin\\s(.*)$",
|
|
||||||
"file": 1,
|
|
||||||
"line": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"regexp": "^\\s*raise\\s(.*)\\(\\'(.*)\\'\\)$",
|
|
||||||
"message": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"problemMatcher": [
|
|
||||||
{
|
|
||||||
"owner": "gcc",
|
|
||||||
"pattern": [
|
|
||||||
{
|
|
||||||
"regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
|
|
||||||
"file": 1,
|
|
||||||
"line": 2,
|
|
||||||
"column": 3,
|
|
||||||
"severity": 4,
|
|
||||||
"message": 5
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"problemMatcher": [
|
|
||||||
{
|
|
||||||
"owner": "llvm",
|
|
||||||
"pattern": [
|
|
||||||
{
|
|
||||||
"regexp": "^(.*?):(\\d+):(\\d*):?\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
|
|
||||||
"file": 1,
|
|
||||||
"line": 2,
|
|
||||||
"column": 3,
|
|
||||||
"severity": 4,
|
|
||||||
"message": 5
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"problemMatcher": [
|
|
||||||
{
|
|
||||||
"owner": "msvc",
|
|
||||||
"pattern": [
|
|
||||||
{
|
|
||||||
"regexp": "^(?:\\s+\\d+>)?(\\S.*)\\((\\d+),?(\\d+)?(?:,\\d+,\\d+)?\\)\\s*:\\s+(error|warning|info)\\s+(\\w{1,2}\\d+)\\s*:\\s*(.*)$",
|
|
||||||
"file": 1,
|
|
||||||
"line": 2,
|
|
||||||
"column": 3,
|
|
||||||
"severity": 4,
|
|
||||||
"code": 5,
|
|
||||||
"message": 6
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"problemMatcher": [
|
|
||||||
{
|
|
||||||
"owner": "python",
|
|
||||||
"pattern": [
|
|
||||||
{
|
|
||||||
"regexp": "^\\s*File\\s\\\"(.*)\\\",\\sline\\s(\\d+),\\sin\\s(.*)$",
|
|
||||||
"file": 1,
|
|
||||||
"line": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"regexp": "^\\s*raise\\s(.*)\\(\\'(.*)\\'\\)$",
|
|
||||||
"message": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -32,9 +32,10 @@
|
||||||
"bump": "ncu -u -x numerous,execa,prettier,@types/node,eslint,@types/eslint && pnpm update && pnpx typesync && pnpm run clean",
|
"bump": "ncu -u -x numerous,execa,prettier,@types/node,eslint,@types/eslint && pnpm update && pnpx typesync && pnpm run clean",
|
||||||
"clean": "shx rm -rf ./dist ./packages/*/dist ./exe ./.parcel-cache && shx mkdir -p ./dist/legacy ./dist/modern ./dist/modern ",
|
"clean": "shx rm -rf ./dist ./packages/*/dist ./exe ./.parcel-cache && shx mkdir -p ./dist/legacy ./dist/modern ./dist/modern ",
|
||||||
"copy.json": "shx cp ./src/*/*.json ./dist/legacy/ && shx cp ./dist/legacy/*.json ./dist/modern",
|
"copy.json": "shx cp ./src/*/*.json ./dist/legacy/ && shx cp ./dist/legacy/*.json ./dist/modern",
|
||||||
|
"dev.root.tsc": "tsc --noEmit --pretty --watch",
|
||||||
"dev.vite": "cross-env NODE_ENV=development vite build --watch",
|
"dev.vite": "cross-env NODE_ENV=development vite build --watch",
|
||||||
"dev.packages": "turbo dev",
|
"dev.packages": "turbo dev",
|
||||||
"dev": "run-p dev.packages dev.vite",
|
"dev": "run-p dev.packages dev.vite dev.root.tsc",
|
||||||
"docs": "shx rm -rf packages/*/README.md && pnpm -r exec readme --path ../../dev/readme/template.md -y && pnpm -r exec ts-readme",
|
"docs": "shx rm -rf packages/*/README.md && pnpm -r exec readme --path ../../dev/readme/template.md -y && pnpm -r exec ts-readme",
|
||||||
"format": "run-s lint.dprint",
|
"format": "run-s lint.dprint",
|
||||||
"lint": "turbo lint && run-p --aggregate-output --continue-on-error lint.**",
|
"lint": "turbo lint && run-p --aggregate-output --continue-on-error lint.**",
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { ubuntuVersion as getUbuntuVersion } from "../../../src/utils/env/ubuntu_version.js"
|
||||||
|
import { aptCacheShow } from "../src/qualify-install.js"
|
||||||
|
|
||||||
|
describe("aptCacheShow", () => {
|
||||||
|
const ubuntuVersionP = getUbuntuVersion()
|
||||||
|
let ubuntuVersion: number[] | null
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
ubuntuVersion = await ubuntuVersionP
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should find the package if installed", async () => {
|
||||||
|
if (ubuntuVersion === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = await aptCacheShow("dpkg", undefined)
|
||||||
|
expect(info).not.toBeUndefined()
|
||||||
|
expect(info?.name).toBe("dpkg")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should find the version of the package if installed", async () => {
|
||||||
|
if (ubuntuVersion === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = await aptCacheShow("gcc", undefined)
|
||||||
|
|
||||||
|
expect(info).not.toBeUndefined()
|
||||||
|
expect(info?.name).toBe("gcc")
|
||||||
|
|
||||||
|
if (ubuntuVersion[0] === 22) {
|
||||||
|
expect(info?.version).toBe("4:11.2.0-1ubuntu1")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should find the version of the package if installed", async () => {
|
||||||
|
if (ubuntuVersion === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ubuntuVersion[0] !== 22) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const info = await aptCacheShow("gcc", "4:11.2.0-1ubuntu1")
|
||||||
|
|
||||||
|
expect(info).not.toBeUndefined()
|
||||||
|
expect(info?.name).toBe("gcc")
|
||||||
|
expect(info?.version).toBe("4:11.2.0-1ubuntu1")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("will not find the package via imprecise version", async () => {
|
||||||
|
const info = await aptCacheShow("gcc", "11")
|
||||||
|
|
||||||
|
expect(info).toBeUndefined()
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { ubuntuVersion as getUbuntuVersion } from "../../../src/utils/env/ubuntu_version.js"
|
||||||
|
import { findAptPackageInfo } from "../src/qualify-install.js"
|
||||||
|
|
||||||
|
describe("findAptPackageInfo", () => {
|
||||||
|
const ubuntuVersionP = getUbuntuVersion()
|
||||||
|
let ubuntuVersion: number[] | null
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
ubuntuVersion = await ubuntuVersionP
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should find the package if installed", async () => {
|
||||||
|
if (ubuntuVersion === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = await findAptPackageInfo("dpkg", undefined)
|
||||||
|
expect(info).not.toBeUndefined()
|
||||||
|
expect(info?.name).toBe("dpkg")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should find the version of the package if installed", async () => {
|
||||||
|
if (ubuntuVersion === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const info = await findAptPackageInfo("gcc", undefined)
|
||||||
|
|
||||||
|
expect(info).not.toBeUndefined()
|
||||||
|
expect(info?.name).toBe("gcc")
|
||||||
|
|
||||||
|
if (ubuntuVersion[0] === 22) {
|
||||||
|
expect(info?.version).toBe("4:11.2.0-1ubuntu1")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should find the version of the package if installed", async () => {
|
||||||
|
if (ubuntuVersion === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ubuntuVersion[0] !== 22) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const info = await findAptPackageInfo("gcc", "4:11.2.0-1ubuntu1")
|
||||||
|
|
||||||
|
expect(info).not.toBeUndefined()
|
||||||
|
expect(info?.name).toBe("gcc")
|
||||||
|
expect(info?.version).toBe("4:11.2.0-1ubuntu1")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("will find the package even with imprecise version", async () => {
|
||||||
|
const info = await findAptPackageInfo("gcc", "11")
|
||||||
|
|
||||||
|
expect(info).not.toBeUndefined()
|
||||||
|
expect(info?.name).toBe("gcc-11")
|
||||||
|
|
||||||
|
if (ubuntuVersion![0] === 22) {
|
||||||
|
expect(info?.version).toBe("4:11.2.0-1ubuntu1")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"include": ["**/*.ts"]
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
import jestConfig from "../../jest.config.mjs"
|
||||||
|
export default jestConfig
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "setup-apt",
|
"name": "setup-apt",
|
||||||
"version": "2.0.0",
|
"version": "3.0.0",
|
||||||
"description": "Setup apt packages and repositories in Debian/Ubuntu-based distributions",
|
"description": "Setup apt packages and repositories in Debian/Ubuntu-based distributions",
|
||||||
"repository": "https://github.com/aminya/setup-cpp",
|
"repository": "https://github.com/aminya/setup-cpp",
|
||||||
"homepage": "https://github.com/aminya/setup-cpp/tree/master/packages/setup-apt",
|
"homepage": "https://github.com/aminya/setup-cpp/tree/master/packages/setup-apt",
|
||||||
|
@ -14,7 +14,8 @@
|
||||||
"dev": "tsc --watch --pretty",
|
"dev": "tsc --watch --pretty",
|
||||||
"lint.tsc": "tsc --noEmit --pretty",
|
"lint.tsc": "tsc --noEmit --pretty",
|
||||||
"lint.eslint": "eslint **/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/ --fix",
|
"lint.eslint": "eslint **/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/ --fix",
|
||||||
"prepublishOnly": "pnpm run build"
|
"prepublishOnly": "pnpm run build",
|
||||||
|
"test": "jest --coverage"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "^12",
|
"@types/node": "^12",
|
||||||
|
|
|
@ -17,7 +17,7 @@ export async function initApt(apt: string) {
|
||||||
], apt)
|
], apt)
|
||||||
|
|
||||||
if (toInstall.length !== 0) {
|
if (toInstall.length !== 0) {
|
||||||
execRootSync(apt, ["install", "-y", "--fix-broken", "-o", aptTimeout, ...toInstall], {
|
execRootSync(apt, ["install", "-y", "--fix-broken", "-o", aptTimeout, ...toInstall.map(pack => pack.qualified)], {
|
||||||
...defaultExecOptions,
|
...defaultExecOptions,
|
||||||
env: getAptEnv(apt),
|
env: getAptEnv(apt),
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,13 +7,13 @@ import { addAptRepository } from "./apt-repository.js"
|
||||||
import { aptTimeout } from "./apt-timeout.js"
|
import { aptTimeout } from "./apt-timeout.js"
|
||||||
import { getApt } from "./get-apt.js"
|
import { getApt } from "./get-apt.js"
|
||||||
import { initAptMemoized } from "./init-apt.js"
|
import { initAptMemoized } from "./init-apt.js"
|
||||||
import { filterAndQualifyAptPackages } from "./qualify-install.js"
|
import { AptPackageInfo, filterAndQualifyAptPackages } from "./qualify-install.js"
|
||||||
import { updateAptReposMemoized } from "./update.js"
|
import { updateAptReposMemoized } from "./update.js"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The information about an installation result
|
* The information about an installation result
|
||||||
*/
|
*/
|
||||||
export type InstallationInfo = {
|
export type InstallationInfo = AptPackageInfo & {
|
||||||
/** The install dir of the package (Defaults to `undefined`) */
|
/** The install dir of the package (Defaults to `undefined`) */
|
||||||
installDir?: string
|
installDir?: string
|
||||||
/** The bin dir of the package (Defaults to `/usr/bin`) */
|
/** The bin dir of the package (Defaults to `/usr/bin`) */
|
||||||
|
@ -67,7 +67,7 @@ const retryErrors = [
|
||||||
])
|
])
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export async function installAptPack(packages: AptPackage[], update = false): Promise<InstallationInfo> {
|
export async function installAptPack(packages: AptPackage[], update = false): Promise<InstallationInfo[]> {
|
||||||
const apt: string = getApt()
|
const apt: string = getApt()
|
||||||
|
|
||||||
for (const { name, version } of packages) {
|
for (const { name, version } of packages) {
|
||||||
|
@ -83,10 +83,11 @@ export async function installAptPack(packages: AptPackage[], update = false): Pr
|
||||||
await addRepositories(apt, packages)
|
await addRepositories(apt, packages)
|
||||||
|
|
||||||
const needToInstall = await filterAndQualifyAptPackages(packages, apt)
|
const needToInstall = await filterAndQualifyAptPackages(packages, apt)
|
||||||
|
const needToInstallArgs = needToInstall.map((pack) => pack.qualified)
|
||||||
|
|
||||||
if (needToInstall.length === 0) {
|
if (needToInstall.length === 0) {
|
||||||
info("All packages are already installed")
|
info("All packages are already installed")
|
||||||
return { binDir: "/usr/bin/" }
|
return needToInstall.map((pack) => ({ ...pack, binDir: "/usr/bin/" }))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize apt if needed
|
// Initialize apt if needed
|
||||||
|
@ -97,17 +98,17 @@ export async function installAptPack(packages: AptPackage[], update = false): Pr
|
||||||
await addAptKeys(packages)
|
await addAptKeys(packages)
|
||||||
|
|
||||||
// Install
|
// Install
|
||||||
execRootSync(apt, ["install", "--fix-broken", "-y", ...needToInstall], {
|
execRootSync(apt, ["install", "--fix-broken", "-y", ...needToInstallArgs], {
|
||||||
...defaultExecOptions,
|
...defaultExecOptions,
|
||||||
env: getAptEnv(apt),
|
env: getAptEnv(apt),
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (isExecaError(err)) {
|
if (isExecaError(err)) {
|
||||||
if (retryErrors.some((error) => err.stderr.includes(error))) {
|
if (retryErrors.some((error) => err.stderr.includes(error))) {
|
||||||
warning(`Failed to install packages ${needToInstall}. Retrying...`)
|
warning(`Failed to install packages ${needToInstallArgs}. Retrying...`)
|
||||||
execRootSync(
|
execRootSync(
|
||||||
apt,
|
apt,
|
||||||
["install", "--fix-broken", "-y", "-o", aptTimeout, ...needToInstall],
|
["install", "--fix-broken", "-y", "-o", aptTimeout, ...needToInstallArgs],
|
||||||
{ ...defaultExecOptions, env: getAptEnv(apt) },
|
{ ...defaultExecOptions, env: getAptEnv(apt) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -116,7 +117,7 @@ export async function installAptPack(packages: AptPackage[], update = false): Pr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { binDir: "/usr/bin/" }
|
return needToInstall.map((pack) => ({ ...pack, binDir: "/usr/bin/" }))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addRepositories(apt: string, packages: AptPackage[]) {
|
async function addRepositories(apt: string, packages: AptPackage[]) {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { warning } from "ci-log"
|
|
||||||
import escapeRegex from "escape-string-regexp"
|
import escapeRegex from "escape-string-regexp"
|
||||||
import { execa } from "execa"
|
import { execa } from "execa"
|
||||||
import { getAptEnv } from "./apt-env.js"
|
import { getAptEnv } from "./apt-env.js"
|
||||||
|
@ -7,16 +6,6 @@ import type { AptPackage } from "./install.js"
|
||||||
import { isAptPackInstalled } from "./is-installed.js"
|
import { isAptPackInstalled } from "./is-installed.js"
|
||||||
import { updateAptReposMemoized, updatedRepos } from "./update.js"
|
import { updateAptReposMemoized, updatedRepos } from "./update.js"
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of apt package to install
|
|
||||||
*/
|
|
||||||
export enum AptPackageType {
|
|
||||||
NameDashVersion = 0,
|
|
||||||
NameEqualsVersion = 1,
|
|
||||||
Name = 2,
|
|
||||||
None = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter out the packages that are already installed and qualify the packages into a full package name/version
|
* Filter out the packages that are already installed and qualify the packages into a full package name/version
|
||||||
*/
|
*/
|
||||||
|
@ -31,66 +20,110 @@ export async function filterAndQualifyAptPackages(packages: AptPackage[], apt: s
|
||||||
* If the package is already installed, return undefined
|
* If the package is already installed, return undefined
|
||||||
*/
|
*/
|
||||||
export async function qualifiedNeededAptPackage(pack: AptPackage, apt: string = getApt()) {
|
export async function qualifiedNeededAptPackage(pack: AptPackage, apt: string = getApt()) {
|
||||||
// Qualify the package into full package name/version
|
const info = await findAptPackageInfo(pack.name, pack.version, apt)
|
||||||
const qualified = await getAptArg(apt, pack.name, pack.version)
|
if (info === undefined) {
|
||||||
// filter out the package that are already installed
|
throw new Error(`Could not find package ${pack.name} ${pack.version}`)
|
||||||
return (await isAptPackInstalled(qualified)) ? undefined : qualified
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function aptPackageType(apt: string, name: string, version: string | undefined): Promise<AptPackageType> {
|
// filter out the package that are already installed
|
||||||
if (version !== undefined && version !== "") {
|
return (await isAptPackInstalled(info.qualified)) ? undefined : info
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AptPackageInfo = {
|
||||||
|
name: string
|
||||||
|
version: string
|
||||||
|
qualified: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the version of the package from apt-cache show
|
||||||
|
* If the version is not found, check if apt-cache search can find the version
|
||||||
|
* If the version is still not found, update the repos and try again
|
||||||
|
*/
|
||||||
|
export async function findAptPackageInfo(
|
||||||
|
name: string,
|
||||||
|
version: string | undefined,
|
||||||
|
apt: string = getApt(),
|
||||||
|
): Promise<AptPackageInfo | undefined> {
|
||||||
|
const info = await aptCacheShow(name, version, apt)
|
||||||
|
if (info !== undefined) {
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version !== undefined) {
|
||||||
|
// check if apt-cache search can find the version
|
||||||
const { stdout } = await execa("apt-cache", [
|
const { stdout } = await execa("apt-cache", [
|
||||||
"search",
|
"search",
|
||||||
"--names-only",
|
"--names-only",
|
||||||
`^${escapeRegex(name)}-${escapeRegex(version)}$`,
|
`^${escapeRegex(name)}-${escapeRegex(version)}$`,
|
||||||
], { env: getAptEnv(apt), stdio: "pipe" })
|
], { env: getAptEnv(apt), stdio: "pipe" })
|
||||||
if (stdout.trim() !== "") {
|
|
||||||
return AptPackageType.NameDashVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
const stdOutTrim = (stdout as string).trim()
|
||||||
// check if apt-get show can find the version
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
||||||
const { stdout } = await execa("apt-cache", ["show", `${name}=${version}`], { env: getAptEnv(apt) })
|
|
||||||
if (stdout.trim() === "") {
|
|
||||||
return AptPackageType.NameEqualsVersion
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
if (stdOutTrim !== "") {
|
||||||
const { stdout: showStdout } = await execa("apt-cache", ["show", name], { env: getAptEnv(apt), stdio: "pipe" })
|
// get the package name by splitting the first line by " - "
|
||||||
if (showStdout.trim() !== "") {
|
const packages = stdOutTrim.split("\n")
|
||||||
return AptPackageType.Name
|
const actualName = packages[0].split(" - ")[0]
|
||||||
|
|
||||||
|
// get the version from apt-cache show
|
||||||
|
return aptCacheShow(actualName, undefined, apt)
|
||||||
}
|
}
|
||||||
} catch {
|
|
||||||
// ignore
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If apt-cache fails, update the repos and try again
|
// If apt-cache fails, update the repos and try again
|
||||||
if (!updatedRepos) {
|
if (!updatedRepos) {
|
||||||
updateAptReposMemoized(apt)
|
updateAptReposMemoized(apt)
|
||||||
return aptPackageType(apt, name, version)
|
return findAptPackageInfo(apt, name, version)
|
||||||
}
|
}
|
||||||
|
|
||||||
return AptPackageType.None
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getAptArg(apt: string, name: string, version: string | undefined) {
|
/**
|
||||||
const package_type = await aptPackageType(apt, name, version)
|
* Get the info about a package from apt-cache show
|
||||||
switch (package_type) {
|
*
|
||||||
case AptPackageType.NameDashVersion:
|
* @param name The name of the package
|
||||||
return `${name}-${version}`
|
* @param version The version of the package
|
||||||
case AptPackageType.NameEqualsVersion:
|
* @param apt The apt command to use
|
||||||
return `${name}=${version}`
|
*
|
||||||
case AptPackageType.Name:
|
* @returns The package info or undefined if the package is not found
|
||||||
if (version !== undefined && version !== "") {
|
*/
|
||||||
warning(`Could not find package ${name} with version ${version}. Installing the latest version.`)
|
export async function aptCacheShow(
|
||||||
|
name: string,
|
||||||
|
version: string | undefined,
|
||||||
|
apt: string = getApt(),
|
||||||
|
): Promise<AptPackageInfo | undefined> {
|
||||||
|
try {
|
||||||
|
const { stdout } = await execa("apt-cache", [
|
||||||
|
"show",
|
||||||
|
version !== undefined && version !== ""
|
||||||
|
? `${name}=${version}`
|
||||||
|
: name,
|
||||||
|
], { env: getAptEnv(apt), stdout: "pipe" })
|
||||||
|
|
||||||
|
const stdoutTrim = (stdout as string).trim()
|
||||||
|
|
||||||
|
if (stdoutTrim === "") {
|
||||||
|
return undefined
|
||||||
}
|
}
|
||||||
return name
|
|
||||||
default:
|
// parse the version from the output
|
||||||
throw new Error(`Could not find package ${name} ${version ?? ""}`)
|
// Version: 4:11.2.0-1ubuntu1
|
||||||
|
const versionMatch = stdoutTrim.match(/^Version: (.*)$/m)
|
||||||
|
|
||||||
|
if (versionMatch !== null) {
|
||||||
|
const actualVersion = versionMatch[1]
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
version: actualVersion,
|
||||||
|
qualified: `${name}-${actualVersion}`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue