# Copyright 2019-2022 ActiveState Software Inc. All rights reserved. <# .EXAMPLE install.ps1 -b branchToInstall #> Set-StrictMode -Off # URL to fetch update infos from. $script:BASEINFOURL = "https://platform.activestate.com/sv/state-update/api/v1/info" # URL to fetch installer archive from $script:BASEFILEURL = "https://state-tool.s3.amazonaws.com/update/state" # The name of the remove archive to download $script:ARCHIVENAME = "state-installer.zip" # Name of the installer executable to ultimately use $script:INSTALLERNAME = "state-install\\state-installer.exe" # Channel the installer will target $script:CHANNEL = "release" # The version to install (autodetermined to be the latest if left unspecified) $script:VERSION = "" $script:SESSION_TOKEN_VERIFY = -join ("{", "TOKEN", "}") $script:SESSION_TOKEN = "" $script:SESSION_TOKEN_VALUE = "" if ("$SESSION_TOKEN" -ne "$SESSION_TOKEN_VERIFY") { $script:SESSION_TOKEN_VALUE = $script:SESSION_TOKEN } function getopt([string] $opt, [string] $default, [string[]] $arr) { for ($i = 0; $i -le $arr.Length; $i++) { $arg = $arr[$i] if ($arg -eq $opt -and $arr.Length -ge ($i + 2)) { return $arr[$i + 1] } } return $default } $script:CHANNEL = getopt "-b" $script:CHANNEL $args $script:VERSION = getopt "-v" $script:VERSION $args function download([string] $url, [string] $out) { [int]$Retrycount = "0" do { try { $downloader = New-Object System.Net.WebClient if ($out -eq "") { return $downloader.DownloadString($url) } else { return $downloader.DownloadFile($url, $out) } } catch { if ($Retrycount -gt 5) { $exception = $_.Exception $errorMessage = "" if ($exception -is [System.Management.Automation.MethodInvocationException] -and $exception.InnerException -is [System.Net.WebException]) { $webException = [System.Net.WebException]$exception.InnerException $response = $webException.Response if ($response -ne $null) { $responseStream = $response.GetResponseStream() $reader = New-Object System.IO.StreamReader($responseStream) $responseBody = $reader.ReadToEnd() $reader.Close() $responseStream.Close() try { $errorMessage = (ConvertFrom-Json $responseBody).message } catch { $errorMessage = $responseBody } } else { $errorMessage = $webException.Message } } else { $errorMessage = $exception.Message } Write-Error "Could not download after 5 retries. Received error: $errorMessage" throw $exception } else { Write-Host "Could not download, retrying..." $Retrycount = $Retrycount + 1 } } } While ($true) } function tempDir() { $parent = [System.IO.Path]::GetTempPath() [string]$name = [System.Guid]::NewGuid() New-Item -ItemType Directory -Path (Join-Path $parent $name) } function progress([string] $msg) { Write-Host "• $msg..." -NoNewline } function progress_done() { $greenCheck = @{ Object = [Char]8730 ForegroundColor = 'Green' NoNewLine = $true } Write-Host @greenCheck Write-Host ' Done' -ForegroundColor Green } function progress_fail() { Write-Host 'x Failed' -ForegroundColor Red } function error([string] $msg) { Write-Host $msg -ForegroundColor Red } $version = $script:VERSION if (!$version) { # If the user did not specify a version, formulate a query to fetch the JSON info of the latest # version, including where it is. $jsonURL = "$script:BASEINFOURL/?channel=$script:CHANNEL&platform=windows&source=install" } elseif (!($version | Select-String -Pattern "-SHA" -SimpleMatch)) { # If the user specified a partial version (i.e. no SHA), formulate a query to fetch the JSON # info of that version's latest SHA, including where it is. $versionNoSHA = $version $version = "" $jsonURL = "$script:BASEINFOURL/?channel=$script:CHANNEL&platform=windows&source=install&target-version=$versionNoSHA" } else { # If the user specified a full version with SHA, formulate a query to fetch the JSON info of # that version. $versionNoSHA = $version -replace "-SHA.*", "" $jsonURL = "$script:BASEINFOURL/?channel=$script:CHANNEL&platform=windows&source=install&target-version=$versionNoSHA" } # Fetch version info. try { $infoJson = ConvertFrom-Json -InputObject (download $jsonURL) } catch [System.Exception] { } if (!$infoJson) { if (!$version) { Write-Error "Unable to retrieve the latest version number" } else { Write-Error "Could not download a State Tool Installer for the given command line arguments" } Write-Error $_.Exception.Message exit 1 } # Extract checksum. $checksum = $infoJson.Sha256 if (!$version) { # If the user specified no version or a partial version we need to use the json URL to get the # actual installer URL. $version = $infoJson.Version $relUrl = $infoJson.Path } else { # If the user specified a full version, construct the installer URL. if ($version -ne $infoJson.Version) { Write-Error "Unknown version: $version" exit 1 } $relUrl = "$script:CHANNEL/$versionNoSHA/windows-amd64/state-windows-amd64-$version.zip" } # Fetch the requested or latest version. progress "Preparing Installer for State Tool Package Manager version $version" $zipURL = "$script:BASEFILEURL/$relUrl" $tmpParentPath = tempDir $zipPath = Join-Path $tmpParentPath $script:ARCHIVENAME $exePath = Join-Path $tmpParentPath $script:INSTALLERNAME try { download $zipURL $zipPath } catch [System.Exception] { progress_fail Write-Error "Could not download $zipURL to $zipPath." Write-Error $_.Exception.Message exit 1 } # Verify checksum. $hash = (Get-FileHash -Path $zipPath -Algorithm SHA256).Hash if ($hash -ne $checksum) { Write-Warning "SHA256 sum did not match:" Write-Warning "Expected: $checksum" Write-Warning "Received: $hash" Write-Warning "Aborting installation" exit 1 } # Extract it. try { Expand-Archive -ErrorAction Stop -LiteralPath $zipPath -DestinationPath $tmpParentPath } catch { progress_fail Write-Error $_.Exception.Message exit 1 } progress_done Write-Host "" $OutputEncoding = [System.Console]::OutputEncoding = [System.Console]::InputEncoding = [System.Text.Encoding]::UTF8 $PSDefaultParameterValues['*:Encoding'] = 'utf8' [System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 # Run the installer. $env:ACTIVESTATE_SESSION_TOKEN = $script:SESSION_TOKEN_VALUE & $exePath $args --source-installer="install.ps1" $success = $? if (Test-Path env:ACTIVESTATE_SESSION_TOKEN) { Remove-Item Env:\ACTIVESTATE_SESSION_TOKEN } if ( !$success ) { exit 1 } # SIG # Begin signature block # MIIQGAYJKoZIhvcNAQcCoIIQCTCCEAUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUWHFDpG4gF+q/dpvO+4+tc9qK # X+2gggx5MIIGGjCCBAKgAwIBAgIQYh1tDFIBnjuQeRUgiSEcCjANBgkqhkiG9w0B # AQwFADBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0w # KwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwHhcN # MjEwMzIyMDAwMDAwWhcNMzYwMzIxMjM1OTU5WjBUMQswCQYDVQQGEwJHQjEYMBYG # A1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBD # b2RlIFNpZ25pbmcgQ0EgUjM2MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKC # AYEAmyudU/o1P45gBkNqwM/1f/bIU1MYyM7TbH78WAeVF3llMwsRHgBGRmxDeEDI # ArCS2VCoVk4Y/8j6stIkmYV5Gej4NgNjVQ4BYoDjGMwdjioXan1hlaGFt4Wk9vT0 # k2oWJMJjL9G//N523hAm4jF4UjrW2pvv9+hdPX8tbbAfI3v0VdJiJPFy/7XwiunD # 7mBxNtecM6ytIdUlh08T2z7mJEXZD9OWcJkZk5wDuf2q52PN43jc4T9OkoXZ0arW # ZVeffvMr/iiIROSCzKoDmWABDRzV/UiQ5vqsaeFaqQdzFf4ed8peNWh1OaZXnYvZ # QgWx/SXiJDRSAolRzZEZquE6cbcH747FHncs/Kzcn0Ccv2jrOW+LPmnOyB+tAfiW # u01TPhCr9VrkxsHC5qFNxaThTG5j4/Kc+ODD2dX/fmBECELcvzUHf9shoFvrn35X # Gf2RPaNTO2uSZ6n9otv7jElspkfK9qEATHZcodp+R4q2OIypxR//YEb3fkDn3Uay # WW9bAgMBAAGjggFkMIIBYDAfBgNVHSMEGDAWgBQy65Ka/zWWSC8oQEJwIDaRXBeF # 5jAdBgNVHQ4EFgQUDyrLIIcouOxvSK4rVKYpqhekzQwwDgYDVR0PAQH/BAQDAgGG # MBIGA1UdEwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwGwYDVR0g # BBQwEjAGBgRVHSAAMAgGBmeBDAEEATBLBgNVHR8ERDBCMECgPqA8hjpodHRwOi8v # Y3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RSNDYu # Y3JsMHsGCCsGAQUFBwEBBG8wbTBGBggrBgEFBQcwAoY6aHR0cDovL2NydC5zZWN0 # aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdSb290UjQ2LnA3YzAjBggr # BgEFBQcwAYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQAD # ggIBAAb/guF3YzZue6EVIJsT/wT+mHVEYcNWlXHRkT+FoetAQLHI1uBy/YXKZDk8 # +Y1LoNqHrp22AKMGxQtgCivnDHFyAQ9GXTmlk7MjcgQbDCx6mn7yIawsppWkvfPk # KaAQsiqaT9DnMWBHVNIabGqgQSGTrQWo43MOfsPynhbz2Hyxf5XWKZpRvr3dMapa # ndPfYgoZ8iDL2OR3sYztgJrbG6VZ9DoTXFm1g0Rf97Aaen1l4c+w3DC+IkwFkvjF # V3jS49ZSc4lShKK6BrPTJYs4NG1DGzmpToTnwoqZ8fAmi2XlZnuchC4NPSZaPATH # vNIzt+z1PHo35D/f7j2pO1S8BCysQDHCbM5Mnomnq5aYcKCsdbh0czchOm8bkinL # rYrKpii+Tk7pwL7TjRKLXkomm5D1Umds++pip8wH2cQpf93at3VDcOK4N7EwoIJB # 0kak6pSzEu4I64U6gZs7tS/dGNSljf2OSSnRr7KWzq03zl8l75jy+hOds9TWSenL # bjBQUGR96cFr6lEUfAIEHVC1L68Y1GGxx4/eRI82ut83axHMViw1+sVpbPxg51Tb # nio1lB93079WPFnYaOvfGAA0e0zcfF/M9gXr+korwQTh2Prqooq2bYNMvUoUKD85 # gnJ+t0smrWrb8dee2CvYZXD5laGtaAxOfy/VKNmwuWuAh9kcMIIGVzCCBL+gAwIB # AgIQasv8vtolVsYeQ3y8VhcugzANBgkqhkiG9w0BAQwFADBUMQswCQYDVQQGEwJH # QjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1 # YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2MB4XDTIyMTAxNzAwMDAwMFoXDTI1MTAx # NjIzNTk1OVowbjELMAkGA1UEBhMCQ0ExGTAXBgNVBAgMEEJyaXRpc2ggQ29sdW1i # aWExITAfBgNVBAoMGEFjdGl2ZVN0YXRlIFNvZnR3YXJlIEluYzEhMB8GA1UEAwwY # QWN0aXZlU3RhdGUgU29mdHdhcmUgSW5jMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A # MIICCgKCAgEAsujxI97OVPS8IWdjalUyvqoY55TxP9hniTRz8cLRP9sKzataElA/ # PfVETsWI40yjXBxQVn6qc+HUFhCTtDW/jyXczD0yp10Ht5wfp+1O2BJ6d+aCHvdL # V/U9LfLdP4i7SxIwcfVlP+HkIrGEE4cZPaDvP6v+dTaYihd+O3I8FZ8SDInN0ukI # 0Luz2grO7ziMTpDMnC+O4mbkR42G+SnTZU6EnJFQmC4iXcxX8oboIBGa7H6Mlkj8 # sCFtuf50pOq04uRXKtNNRmcwk2wLumjNAqplsIQnQHI9p7IJ9naC0p0vtm6SA4TQ # 0ajlhlMsNMDTA6dIk085gw4z+qoiulnzjnY8Fid3BgUhkvwNyPAU/Cjjeg/FvnDc # NgJCCcHdw8wrXnqltaYIwWLraSvzSjYKIDbhdcUVkc4sBVWBGPil3zNUwxBlMLk2 # R80mAQbUst3AD8LWdbACO1cMGLw3p6k/DiyoG2HmunNhbfVG+DOFKvJwby8fgG0s # M+ZVCxkqowQyGIs6hSM+zlANdPG6rDNGHMLcOktTVhMUmsjkf2CxJ2p5HmbarhYR # 9pWr4biKZUzkuMAqmhN+Gu1f333REWHfE4nmQ6FG6+1MeB85H4ZYVUCARfqXLnwz # Fr5vsZATZoQdVeXOldds4Eh/sMSV39KKnCct77jYJNrqRC4LSEMedUkCAwEAAaOC # AYkwggGFMB8GA1UdIwQYMBaAFA8qyyCHKLjsb0iuK1SmKaoXpM0MMB0GA1UdDgQW # BBQ5OzloWJN0KewaLtqZGI9tj38ROjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/ # BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzBKBgNVHSAEQzBBMDUGDCsGAQQBsjEB # AgEDAjAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28uY29tL0NQUzAIBgZn # gQwBBAEwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2NybC5zZWN0aWdvLmNvbS9T # ZWN0aWdvUHVibGljQ29kZVNpZ25pbmdDQVIzNi5jcmwweQYIKwYBBQUHAQEEbTBr # MEQGCCsGAQUFBzAChjhodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJs # aWNDb2RlU2lnbmluZ0NBUjM2LmNydDAjBggrBgEFBQcwAYYXaHR0cDovL29jc3Au # c2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggGBAIr/fSszO0Cii3HdCPY8bjwh # ZpgZr25jhm/ItH1ddOdVjtBm49KQyZfAmT8MDrk5SrJnLImmMAdnJl2gU4HExTu2 # NoOgTgR4mL8AXJb5vw3Y3jpqQOZsGOyK08VZiu/AKdZUzanHMtDFkfGKfBljl+SB # jCl/OZl0fOUXge1vSa3aozqie1QTzpb5IWgwiCy1HmaSyj+7iwaqIIn3jnT7Ra4N # iRcDHYGx7McQQv8YJ2k4s2PynoVJxDb3xnVuUBIFEVzun+pMcZ0+pRdNdlP+NHMj # NdYI9Ao2HIB6OMZZuoBqk3cnCJPE8nYTAxfSunXFSVrnJXyW7mlOBBN6x/9ZnOSA # t1Q8WqcFmbfH0J9XhgQ3QeILm5RztOXYrAWbeKDqJU8wHg8+D2hqlOvIe8HwYIxD # M+EzOvFoyaRjTW6Cmrbd83ILXdeprsoyD4D/q+PZSfDVSvmWIrsQkMBJ8vrnjkn2 # KxENnSPG3aa8HvO4ucgJJVdRBNW0T9GqY4EHYrAqWjGCAwkwggMFAgEBMGgwVDEL # MAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UEAxMi # U2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIFIzNgIQasv8vtolVsYeQ3y8 # VhcugzAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkq # hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGC # NwIBFTAjBgkqhkiG9w0BCQQxFgQUFxdJeOC3scEmS3X6JJDnZMV3laYwDQYJKoZI # hvcNAQEBBQAEggIAFsCbzDHPHNmGaPO2BcE4wtVSVJSt4VM9DQuL6BPktg8pIeVa # HrnrHobxtvHnp9Upmwu19i9RbTQ797yc8KAcX1eiau8wX7h9PfyOattYSBRWnRGm # 9ZhzKftPdHAGzT0jV2GmkgPiIVKBAP5ItqAZ0KM9oyN+9Wxni0fdZ7hMfTAuW3gL # qv2yPuhjD26zxVr475bCBekOp5ZrQOkJel/58AwY8DtRA4nCNDsYWL78PS1IXX+n # 90x6U9/qX6Rr13r3L8qpGTSkqrsspa3sX5QIKVkjQmR3Mvk7Ni2+WPYGZbtA38uL # cqcEfaDmjYwyyk8UneTIOEe00mfgxKNm4NMNRLu0MOZm+VCdiwG4tnb0+xvIPWe/ # J9ercmBSazF8N5EZh3IgxfbLt1Di6UxqWUfg2D7vOr+JlZtQCX8ujtzTU0WfEvBx # g/tIjXRo3EeM6+c1utAoraIwvKoscAFIsG4F+p3oJkDJvzKPf3THKpPrQ7Pd9ZSJ # bwbc4+gs8rI2zNKONTSiKIZq5V4oAf9HR+H4M9p13QmZksHXLNGXljDzVmWSAjCO # EwLHsWcG7LvuA9pXGFYUu1i80Hp24Xj136FVyCtT0NHpeVQDWULw4Y6ntFL0rkr7 # uBLm8PQc6LqkQ9iU0UD6x/iS410k693iZ2eVCs0Q2pHljTL5NRRVsHEE2hs= # SIG # End signature block