import * as path from 'path' ; import * as pypyInstall from './install-pypy' ; import { IS_WINDOWS , WINDOWS_ARCHS , validateVersion , getPyPyVersionFromPath , readExactPyPyVersionFile , validatePythonVersionFormatForPyPy } from './utils' ; import * as semver from 'semver' ; import * as core from '@actions/core' ; import * as tc from '@actions/tool-cache' ; interface IPyPyVersionSpec { pypyVersion : string ; pythonVersion : string ; } export async function findPyPyVersion ( versionSpec , architecture ) { let resolvedPyPyVersion = '' ; let resolvedPythonVersion = '' ; let installDir ; const pypyVersionSpec = parsePyPyVersion ( versionSpec ) ; ( { installDir , resolvedPythonVersion , resolvedPyPyVersion } = findPyPyToolCache ( pypyVersionSpec . pythonVersion , pypyVersionSpec . pypyVersion , architecture ) ) ; if ( ! installDir ) { ( { installDir , resolvedPythonVersion , resolvedPyPyVersion } = await pypyInstall . installPyPy ( pypyVersionSpec . pypyVersion , pypyVersionSpec . pythonVersion , architecture ) ) ; } const pipDir = IS_WINDOWS ? 'Scripts' : 'bin' ; const _binDir = path . join ( installDir , pipDir ) ; const pythonLocation = pypyInstall . getPyPyBinaryPath ( installDir ) ; core . exportVariable ( 'pythonLocation' , pythonLocation ) ; core . addPath ( pythonLocation ) ; core . addPath ( _binDir ) ; return { resolvedPyPyVersion , resolvedPythonVersion } ; } export function findPyPyToolCache ( pythonVersion , pypyVersion , architecture ) { let resolvedPyPyVersion = '' ; let resolvedPythonVersion = '' ; let installDir = IS_WINDOWS ? findPyPyInstallDirForWindows ( pythonVersion ) : tc . find ( 'PyPy' , pythonVersion , architecture ) ; if ( installDir ) { resolvedPythonVersion = getPyPyVersionFromPath ( installDir ) ; resolvedPyPyVersion = readExactPyPyVersionFile ( installDir ) ; const isPyPyVersionSatisfies = semver . satisfies ( resolvedPyPyVersion , pypyVersion ) ; if ( ! isPyPyVersionSatisfies ) { installDir = null ; resolvedPyPyVersion = '' ; resolvedPythonVersion = '' ; } } if ( ! installDir ) { core . info ( `PyPy version ${ pythonVersion } (${ pypyVersion }) was not found in the local cache` ) ; } return { installDir , resolvedPythonVersion , resolvedPyPyVersion } ; } export function parsePyPyVersion ( versionSpec ) { const versions = versionSpec . split ( '-' ) . filter ( item => ! ! item ) ; if ( versions . length < 2 || versions [ 0 ] != 'pypy' ) { throw new Error ( "Invalid 'version' property for PyPy. PyPy version should be specified as 'pypy-<python-version>'. See README for examples and documentation." ) ; } const pythonVersion = versions [ 1 ] ; let pypyVersion ; if ( versions . length > 2 ) { pypyVersion = pypyInstall . pypyVersionToSemantic ( versions [ 2 ] ) ; } else { pypyVersion = 'x' ; } if ( ! validateVersion ( pythonVersion ) || ! validateVersion ( pypyVersion ) ) { throw new Error ( "Invalid 'version' property for PyPy. Both Python version and PyPy versions should satisfy SemVer notation. See README for examples and documentation." ) ; } if ( ! validatePythonVersionFormatForPyPy ( pythonVersion ) ) { throw new Error ( "Invalid format of Python version for PyPy. Python version should be specified in format 'x.y'. See README for examples and documentation." ) ; } return { pypyVersion : pypyVersion , pythonVersion : pythonVersion } ; } export function findPyPyInstallDirForWindows ( pythonVersion ) { let installDir = '' ; WINDOWS_ARCHS . forEach ( architecture => ( installDir = installDir || tc . find ( 'PyPy' , pythonVersion , architecture ) ) ) ; return installDir ; }