import * as fs from "fs" ; import * as path from "path" ; import * as os from "os" ; import * as core from "@actions/core" ; import * as io from "@actions/io" ; import * as types from "./types" ; import * as constants from "./constants" ; import * as utils from "./utils" ; /**
 * Provide current location of miniconda or location where it will be installed
 */ export function condaBasePath ( options ) { let condaPath = constants . MINICONDA_DIR_PATH ; if ( ! options . useBundled ) { if ( constants . IS_MAC ) { condaPath = "/Users/runner/miniconda3" ; } else { condaPath += "3" ; } } return condaPath ; } /**
 * Provide conda CLI arguments for identifying an env by name or prefix/path
 *
 * ### Note
 * Only really detects by presence of a path separator, as the path may not yet exist
 */ export function envCommandFlag ( inputs ) { return [ inputs . activateEnvironment . match ( /(\\|\/)/ ) ? "--prefix" : "--name" , inputs . activateEnvironment , ] ; } /**
 * Provide cross platform location of conda/mamba executable
 */ export function condaExecutable ( options , subcommand ? ) { const dir = condaBasePath ( options ) ; let condaExe ; let commandName = "conda" ; if ( options . useMamba && ( subcommand == null || constants . MAMBA_SUBCOMMANDS . includes ( subcommand ) ) ) { commandName = "mamba" ; } commandName = constants . IS_WINDOWS ? commandName + ".bat" : commandName ; condaExe = path . join ( dir , "condabin" , commandName ) ; return condaExe ; } /** Detect the presence of mamba */ export function isMambaInstalled ( options ) { const mamba = condaExecutable ( { ... options , useMamba : true } ) ; return fs . existsSync ( mamba ) ; } /**
 * Run Conda command
 */ export async function condaCommand ( cmd , options ) { const command = [ condaExecutable ( options , cmd [ 0 ] ) , ... cmd ] ; return await utils . execute ( command ) ; } /**
 * Create a baseline .condarc
 */ export async function bootstrapConfig ( ) { await fs . promises . writeFile ( constants . CONDARC_PATH , constants . BOOTSTRAP_CONDARC ) ; } /**
 * Copy the given condarc file into place
 */ export async function copyConfig ( inputs ) { const sourcePath = path . join ( process . env [ "GITHUB_WORKSPACE" ] || "" , inputs . condaConfigFile ) ; core . info ( `Copying "${ sourcePath }" to "${ constants . CONDARC_PATH }..."` ) ; await io . cp ( sourcePath , constants . CONDARC_PATH ) ; } /**
 * Setup Conda configuration
 */ export async function applyCondaConfiguration ( inputs , options ) { const configEntries = Object . entries ( inputs . condaConfig ) as [ keyof types . ICondaConfig , string ] [ ] ; let channels = inputs . condaConfig . channels . trim ( ) . split ( /,/ ) . map ( ( c ) => c . trim ( ) ) . filter ( ( c ) => c . length ) ; if ( ! channels . length && options . envSpec ?. yaml ?. channels ?. length ) { channels = options . envSpec . yaml . channels ; } for ( const channel of channels . slice ( ) . reverse ( ) ) { core . info ( `Adding channel '${ channel }'` ) ; await condaCommand ( [ "config" , "--add" , "channels" , channel ] , options ) ; } for ( const [ key , value ] of configEntries ) { if ( value . trim ( ) . length === 0 || key === "channels" ) { continue ; } core . info ( `${ key }: ${ value }` ) ; try { await condaCommand ( [ "config" , "--set" , key , value ] , options ) ; } catch ( err ) { core . warning ( err ) ; } } await condaCommand ( [ "config" , "--show-sources" ] , options ) ; await condaCommand ( [ "config" , "--show" ] , options ) ; } /**
 * Initialize Conda
 */ export async function condaInit ( inputs , options ) { let ownPath ; const isValidActivate = ! utils . isBaseEnv ( inputs . activateEnvironment ) ; const autoActivateBase = options . condaConfig [ "auto_activate_base" ] === "true" ; if ( options . useBundled ) { if ( constants . IS_MAC ) { core . info ( "Fixing conda folders ownership" ) ; const userName = process . env . USER as string ; await utils . execute ( [ "sudo" , "chown" , "-R" , `${ userName }:staff` , condaBasePath ( options ) , ] ) ; } else if ( constants . IS_WINDOWS ) { for ( let folder of constants . WIN_PERMS_FOLDERS ) { ownPath = path . join ( condaBasePath ( options ) , folder ) ; if ( fs . existsSync ( ownPath ) ) { core . info ( `Fixing ${ folder } ownership` ) ; await utils . execute ( [ "takeown" , "/f" , ownPath , "/r" , "/d" , "y" ] ) ; } } } } if ( inputs . removeProfiles == "true" ) { for ( let rc of constants . PROFILES ) { try { let file = path . join ( os . homedir ( ) , rc ) ; if ( fs . existsSync ( file ) ) { core . info ( `Removing "${ file }"` ) ; await io . rmRF ( file ) ; } } catch ( err ) { core . warning ( err ) ; } } } for ( let cmd of [ "--all" ] ) { await condaCommand ( [ "init" , cmd ] , options ) ; } if ( constants . IS_LINUX ) { let source = "~/.bashrc" . replace ( "~" , os . homedir ( ) ) ; let dest = "~/.profile" . replace ( "~" , os . homedir ( ) ) ; core . info ( `Renaming "${ source }" to "${ dest }"\n` ) ; await io . mv ( source , dest ) ; } else if ( constants . IS_MAC ) { let source = "~/.bash_profile" . replace ( "~" , os . homedir ( ) ) ; let dest = "~/.profile" . replace ( "~" , os . homedir ( ) ) ; core . info ( `Renaming "${ source }" to "${ dest }"\n` ) ; await io . mv ( source , dest ) ; } let powerExtraText = `
  # ----------------------------------------------------------------------------` ; if ( isValidActivate ) { powerExtraText += `
  # Conda Setup Action: Custom activation
  conda activate "${ inputs . activateEnvironment }"` ; } powerExtraText += `
  # ----------------------------------------------------------------------------` ; let bashExtraText = `
  # ----------------------------------------------------------------------------
  # Conda Setup Action: Basic configuration
  set -eo pipefail` ; if ( isValidActivate ) { bashExtraText += `
  # Conda Setup Action: Custom activation
  conda activate "${ inputs . activateEnvironment }"` ; bashExtraText += `
  # ----------------------------------------------------------------------------` ; } let batchExtraText = `
  :: ---------------------------------------------------------------------------` ; if ( autoActivateBase ) { batchExtraText += `
  :: Conda Setup Action: Activate base
  @CALL "%CONDA_BAT%" activate base` ; } if ( isValidActivate ) { batchExtraText += `
  :: Conda Setup Action: Custom activation
  @CALL "%CONDA_BAT%" activate "${ inputs . activateEnvironment }"` ; } batchExtraText += `
  :: Conda Setup Action: Basic configuration
  @SETLOCAL EnableExtensions
  @SETLOCAL DisableDelayedExpansion
  :: ---------------------------------------------------------------------------` ; let extraShells ; const shells = { "~/.bash_profile" : bashExtraText , "~/.profile" : bashExtraText , "~/.zshrc" : bashExtraText , "~/.config/fish/config.fish" : bashExtraText , "~/.tcshrc" : bashExtraText , "~/.xonshrc" : bashExtraText , "~/.config/powershell/profile.ps1" : powerExtraText , "~/Documents/PowerShell/profile.ps1" : powerExtraText , "~/Documents/WindowsPowerShell/profile.ps1" : powerExtraText , } ; if ( options . useBundled ) { extraShells = { "C:/Miniconda/etc/profile.d/conda.sh" : bashExtraText , "C:/Miniconda/etc/fish/conf.d/conda.fish" : bashExtraText , "C:/Miniconda/condabin/conda_hook.bat" : batchExtraText , } ; } else { extraShells = { "C:/Miniconda3/etc/profile.d/conda.sh" : bashExtraText , "C:/Miniconda3/etc/fish/conf.d/conda.fish" : bashExtraText , "C:/Miniconda3/condabin/conda_hook.bat" : batchExtraText , } ; } const allShells = { ... shells , ... extraShells } ; Object . keys ( allShells ) . forEach ( ( key ) => { let filePath = key . replace ( "~" , os . homedir ( ) ) ; const text = allShells [ key ] ; if ( fs . existsSync ( filePath ) ) { core . info ( `Append to "${ filePath }":\n ${ text } \n` ) ; fs . appendFileSync ( filePath , text ) ; } } ) ; }