Public/Set-DevVmVersion.ps1

<#
.SYNOPSIS
Sets the active version of a runtime for the current session or permanently.
 
.DESCRIPTION
Switches to a specific version of a runtime. Can be persisted to:
- 'session': Only for the current session
- 'project': Saves to nearest .devvm file
- 'global': Saves to global .devvm file
- 'path': Saves to .devvm file AND adds to user PATH permanently
 
.PARAMETER Runtime
The runtime to set (node, java, maven, etc.)
 
.PARAMETER Version
The version to activate.
 
.PARAMETER Persist
Where to save the selection: 'session', 'project', 'global', or 'path'.
Default is 'session'.
 
.PARAMETER Verify
If specified, verifies the runtime command executes after activation by displaying its version output.
Default is $false (no verification).
 
.EXAMPLE
Set-DevVmVersion -Runtime node -Version 18.16.0
Set-DevVmVersion -Runtime node -Version 18.16.0 -Persist project
Set-DevVmVersion -Runtime java -Version 17.0.5 -Persist global
Set-DevVmVersion -Runtime java -Version 17.0.5 -Persist path
Set-DevVmVersion -Runtime java -Version 17.0.5 -Verify
 
#>

function Set-DevVmVersion {
    [CmdletBinding(SupportsShouldProcess = $true)]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateScript({ Test-DevVmRuntime $_ })]
        [string]$Runtime,

        [Parameter(Mandatory = $true)]
        [string]$Version,

        [ValidateSet('session', 'project', 'global', 'path')]
        [string]$Persist = 'session',

        [switch]$Verify = $false
    )

    $runtimeInfo = Get-DevVmRuntimeInfo -Runtime $Runtime
    if (-not $runtimeInfo) {
        Write-Error "Runtime '$Runtime' not configured"
        return
    }

    $basePath = Get-DevVmInstallPath -Runtime $Runtime
    $versionPath = Join-Path -Path $basePath -ChildPath $Version

    if (-not (Test-Path $versionPath)) {
        Write-Error "$Runtime version '$Version' not found at $basePath"
        return
    }

    if ($PSCmdlet.ShouldProcess("$Runtime $Version", 'Activate runtime version')) {
        # Update PATH for current session
        Update-DevVmSessionPath -Runtime $Runtime -Version $Version -BasePath $basePath -BinPath $runtimeInfo.binPath -Confirm:$false -WhatIf:$false

        if ($Verify) {
            # Verify the runtime command executes after activation (output is handled by Test-DevVmRuntimeCommand)
            Test-DevVmRuntimeCommand -Runtime $Runtime -Command $runtimeInfo.command -VersionFlag $runtimeInfo.versionFlag | Out-Null
        }

        if (-not $script:DevVmConfig.SessionSelections) {
            $script:DevVmConfig.SessionSelections = @{}
        }
        $script:DevVmConfig.SessionSelections[$Runtime] = $Version

        Write-Output "Activated $Runtime version $Version in current session"
    }
    else {
        Write-Verbose "Skipped activation for $Runtime $Version"
    }

    # Persist if requested
    if ($Persist -ne 'session') {
        if ($PSCmdlet.ShouldProcess("$Runtime $Version", "Persist selection to $Persist config")) {
            # Save to config file (project or global)
            $target = if ($Persist -eq 'path') { 'project' } else { $Persist }
            Save-DevVmVersionSelection -Runtime $Runtime -Version $Version -Target $target
            Write-Output "Saved selection to $target configuration"

            # Additionally modify user PATH if requested
            if ($Persist -eq 'path') {
                $result = Set-DevVmPersistentPath -Runtime $Runtime -Version $Version -BasePath $basePath -BinPath $runtimeInfo.binPath
                if ($result) {
                    Write-Warning "Runtime added to persistent user PATH. Restart terminal for changes to apply in new windows."
                }
            }
        }
        else {
            Write-Verbose "Skipped persistence for $Runtime $Version to $Persist config"
        }
    }
}