Merge pull request #190 from aminya/pipx [skip ci]

This commit is contained in:
Amin Yahyaabadi 2023-09-01 09:58:08 -07:00 committed by GitHub
commit 2ab6e8f154
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 122 additions and 61 deletions

View File

@ -32,6 +32,7 @@ words:
- DCMAKE - DCMAKE
- deps - deps
- devel - devel
- DVCPKG
- dyld - dyld
- eabi - eabi
- esmodule - esmodule
@ -67,6 +68,7 @@ words:
- OSSDK - OSSDK
- papm - papm
- patha - patha
- pipx
- pnpm - pnpm
- pwsh - pwsh
- pygments - pygments
@ -74,6 +76,7 @@ words:
- Sccache - Sccache
- setupcpp - setupcpp
- setx - setx
- SYSROOT
- Syuu - Syuu
- terserrc - terserrc
- Trofimovich - Trofimovich
@ -83,16 +86,15 @@ words:
- upleveled - upleveled
- vbatts - vbatts
- vcpkg - vcpkg
- VCPKG
- vcvarsall - vcvarsall
- venv
- visualc - visualc
- visualcpp - visualcpp
- vsversion - vsversion
- whatwg - whatwg
- xcrun - xcrun
- Yahyaabadi - Yahyaabadi
- VCPKG
- DVCPKG
- SYSROOT
ignoreWords: [] ignoreWords: []
import: [] import: []
dictionaryDefinitions: [] dictionaryDefinitions: []

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

@ -1,7 +1,6 @@
import { setupPipPack } from "../utils/setup/setupPipPack" import { setupPipPack } from "../utils/setup/setupPipPack"
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function setupConan(version: string | undefined, _setupDir: string, _arch: string) { export function setupConan(version: string | undefined, _setupDir: string, _arch: string) {
await setupPipPack("setuptools", "")
return setupPipPack("conan", version) return setupPipPack("conan", version)
} }

View File

@ -21,7 +21,7 @@ import { isBinUptoDate } from "../utils/setup/version"
import { unique } from "../utils/std" import { unique } from "../utils/std"
import { MinVersions } from "../versions/default_versions" import { MinVersions } from "../versions/default_versions"
import { pathExists } from "path-exists" import { pathExists } from "path-exists"
import { setupPipPackWithPython } from "../utils/setup/setupPipPack" import { hasPipx, setupPipPackSystem, setupPipPackWithPython } from "../utils/setup/setupPipPack"
export async function setupPython(version: string, setupDir: string, arch: string): Promise<InstallationInfo> { export async function setupPython(version: string, setupDir: string, arch: string): Promise<InstallationInfo> {
const installInfo = await findOrSetupPython(version, setupDir, arch) const installInfo = await findOrSetupPython(version, setupDir, arch)
@ -34,15 +34,37 @@ export async function setupPython(version: string, setupDir: string, arch: strin
throw new Error("pip was not installed correctly") throw new Error("pip was not installed correctly")
} }
// setup wheel and setuptools await setupPipx(foundPython)
await setupWheel(foundPython)
return installInfo
}
async function setupPipx(foundPython: string) {
try { try {
await setupPipPackWithPython(foundPython, "setuptools", undefined, true) if (!(await hasPipx(foundPython))) {
await setupPipPackWithPython(foundPython, "wheel", undefined, true) await setupPipPackWithPython(foundPython, "pipx", undefined, { upgrade: true, usePipx: false })
}
await execa(foundPython, ["-m", "pipx", "ensurepath"], { stdio: "inherit" })
await setupPipPackWithPython(foundPython, "venv", undefined, { upgrade: false, usePipx: false })
} catch (err) {
warning(`Failed to install pipx: ${(err as Error).toString()}. Ignoring...`)
}
}
/** Setup wheel and setuptools */
async function setupWheel(foundPython: string) {
try {
await setupPipPackWithPython(foundPython, "setuptools", undefined, {
upgrade: true,
isLibrary: true,
usePipx: false,
})
await setupPipPackWithPython(foundPython, "wheel", undefined, { upgrade: true, isLibrary: true, usePipx: false })
} catch (err) { } catch (err) {
warning(`Failed to install setuptools or wheel: ${(err as Error).toString()}. Ignoring...`) warning(`Failed to install setuptools or wheel: ${(err as Error).toString()}. Ignoring...`)
} }
return installInfo
} }
async function findOrSetupPython(version: string, setupDir: string, arch: string) { async function findOrSetupPython(version: string, setupDir: string, arch: string) {
@ -203,7 +225,9 @@ async function isPipUptoDate(pip: string) {
async function setupPip(foundPython: string) { async function setupPip(foundPython: string) {
const upgraded = await ensurePipUpgrade(foundPython) const upgraded = await ensurePipUpgrade(foundPython)
if (!upgraded) { if (!upgraded) {
await setupPipSystem() // ensure that pip is installed on Linux (happens when python is found but pip not installed)
await setupPipPackSystem("pip")
// upgrade pip // upgrade pip
await ensurePipUpgrade(foundPython) await ensurePipUpgrade(foundPython)
} }
@ -228,20 +252,6 @@ async function ensurePipUpgrade(foundPython: string) {
return false return false
} }
function setupPipSystem() {
if (process.platform === "linux") {
// ensure that pip is installed on Linux (happens when python is found but pip not installed)
if (isArch()) {
return setupPacmanPack("python-pip")
} else if (hasDnf()) {
return setupDnfPack([{ name: "python3-pip" }])
} else if (isUbuntu()) {
return setupAptPack([{ name: "python3-pip" }])
}
}
throw new Error(`Could not install pip on ${process.platform}`)
}
async function addPythonBaseExecPrefix_raw(python: string) { async function addPythonBaseExecPrefix_raw(python: string) {
const dirs: string[] = [] const dirs: string[] = []

View File

@ -1,5 +1,5 @@
import { info } from "@actions/core" import { info } from "@actions/core"
import { execaSync } from "execa" import { execa, execaSync } from "execa"
import { pathExists } from "path-exists" import { pathExists } from "path-exists"
import { addExeExt, dirname, join } from "patha" import { addExeExt, dirname, join } from "patha"
import which from "which" import which from "which"
@ -9,26 +9,59 @@ import { InstallationInfo } from "./setupBin"
import { getVersion } from "../../versions/versions" import { getVersion } from "../../versions/versions"
import { ubuntuVersion } from "../env/ubuntu_version" import { ubuntuVersion } from "../env/ubuntu_version"
import memoize from "micro-memoize" import memoize from "micro-memoize"
import { isArch } from "../env/isArch"
import { setupPacmanPack } from "./setupPacmanPack"
import { hasDnf } from "../env/hasDnf"
import { setupDnfPack } from "./setupDnfPack"
import { isUbuntu } from "../env/isUbuntu"
import { setupAptPack } from "./setupAptPack"
export type SetupPipPackOptions = {
/** Whether to use pipx instead of pip */
usePipx?: boolean
/** Whether to install the package as a user */
user?: boolean
/** Whether to upgrade the package */
upgrade?: boolean
/** Whether the package is a library */
isLibrary?: boolean
}
/** A function that installs a package using pip */ /** A function that installs a package using pip */
export async function setupPipPack(name: string, version?: string, upgrade = false): Promise<InstallationInfo> { export async function setupPipPack(
return setupPipPackWithPython(await getPython(), name, version, upgrade) name: string,
version?: string,
options: SetupPipPackOptions = {},
): Promise<InstallationInfo> {
return setupPipPackWithPython(await getPython(), name, version, options)
} }
export async function setupPipPackWithPython( export async function setupPipPackWithPython(
givenPython: string, givenPython: string,
name: string, name: string,
version?: string, version?: string,
upgrade = false, options: SetupPipPackOptions = {},
): Promise<InstallationInfo> { ): Promise<InstallationInfo> {
info(`Installing ${name} ${version ?? ""} via pip`) const { usePipx = true, user = true, upgrade = false, isLibrary = false } = options
const isPipx = usePipx && !isLibrary && (await hasPipx(givenPython))
const pip = isPipx ? "pipx" : "pip"
info(`Installing ${name} ${version ?? ""} via ${pip}`)
try {
const nameAndVersion = version !== undefined && version !== "" ? `${name}==${version}` : name const nameAndVersion = version !== undefined && version !== "" ? `${name}==${version}` : name
const upgradeFlag = upgrade === true ? ["--upgrade"] : [] const upgradeFlag = upgrade ? (isPipx ? ["upgrade"] : ["install", "--upgrade"]) : ["install"]
const userFlag = !isPipx && user ? ["--user"] : []
execaSync(givenPython, ["-m", "pip", "install", ...upgradeFlag, nameAndVersion], { execaSync(givenPython, ["-m", pip, ...upgradeFlag, ...userFlag, nameAndVersion], {
stdio: "inherit", stdio: "inherit",
}) })
} catch (err) {
if ((await setupPipPackSystem(name)) === null) {
throw new Error(`Failed to install ${name} via ${pip} ${err}`)
}
}
const execPaths = await addPythonBaseExecPrefix(givenPython) const execPaths = await addPythonBaseExecPrefix(givenPython)
const binDir = await findBinDir(execPaths, name) const binDir = await findBinDir(execPaths, name)
@ -38,6 +71,10 @@ export async function setupPipPackWithPython(
return { binDir } return { binDir }
} }
export async function hasPipx(givenPython: string) {
return (await execa(givenPython, ["-m", "pipx", "--help"], { stdio: "ignore", reject: false })).exitCode === 0
}
async function getPython_raw(): Promise<string> { async function getPython_raw(): Promise<string> {
const pythonBin = (await setupPython(getVersion("python", undefined, await ubuntuVersion()), "", process.arch)).bin const pythonBin = (await setupPython(getVersion("python", undefined, await ubuntuVersion()), "", process.arch)).bin
if (pythonBin === undefined) { if (pythonBin === undefined) {
@ -62,3 +99,16 @@ async function findBinDir(dirs: string[], name: string) {
return dirs[dirs.length - 1] return dirs[dirs.length - 1]
} }
export function setupPipPackSystem(name: string) {
if (process.platform === "linux") {
if (isArch()) {
return setupPacmanPack(`python-${name}`)
} else if (hasDnf()) {
return setupDnfPack([{ name: `python3-${name}` }])
} else if (isUbuntu()) {
return setupAptPack([{ name: `python3-${name}` }])
}
}
return null
}