# Served by getjack.dev; resolve the release when the installer runs. & { $ErrorActionPreference = 'Stop' $architecture = $env:PROCESSOR_ARCHITECTURE if ($env:PROCESSOR_ARCHITEW6432) { $architecture = $env:PROCESSOR_ARCHITEW6432 } if ($env:OS -ne 'Windows_NT' -or $architecture -ne 'AMD64') { throw 'Unsupported platform. Jack supports Windows x64.' } # Windows PowerShell 5.1 may otherwise default to older TLS versions. [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 $origin = 'https://dl.getjack.dev/runtime' try { $release = (Invoke-WebRequest -UseBasicParsing -Uri "$origin/latest.json").Content | ConvertFrom-Json $version = $release.version $sums = $release.sha256sums } catch { # Only a not-yet-published pointer permits the legacy endpoint fallback. if (-not $_.Exception.Response -or [int]$_.Exception.Response.StatusCode -ne 404) { throw } $versions = (Invoke-WebRequest -UseBasicParsing -Uri 'https://getjack.dev/version.json').Content | ConvertFrom-Json $version = $versions.runtime.latest.latest $sums = "v$version/SHA256SUMS" } if ($version -isnot [string] -or $version -cnotmatch '\A(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\z') { throw 'Invalid Runtime release version.' } if ($version -eq '0.0.0') { throw 'Jack Runtime has no release yet. Please try again after release.' } if ($sums -isnot [string] -or $sums -cne "v$version/SHA256SUMS") { throw 'Invalid release checksum path.' } function New-PrivateDirectory([string]$Path) { $sid = [Security.Principal.WindowsIdentity]::GetCurrent().User $acl = New-Object Security.AccessControl.DirectorySecurity $acl.SetOwner($sid) $acl.SetAccessRuleProtection($true, $false) $rule = New-Object Security.AccessControl.FileSystemAccessRule($sid, 'FullControl', 'ContainerInherit,ObjectInherit', 'None', 'Allow') $acl.AddAccessRule($rule) if (Test-Path -LiteralPath $Path) { Set-Acl -LiteralPath $Path -AclObject $acl } elseif ($PSVersionTable.PSEdition -eq 'Core') { $null = [IO.FileSystemAclExtensions]::CreateDirectory([IO.DirectoryInfo]::new($Path), $acl) } else { $null = [IO.Directory]::CreateDirectory($Path, $acl) } } # Match the Runtime's HOME, USERPROFILE, system-home resolution. $jackHome = $env:HOME if (-not $jackHome -or $jackHome -eq 'undefined') { $jackHome = $env:USERPROFILE } if (-not $jackHome -or $jackHome -eq 'undefined') { $jackHome = [Environment]::GetFolderPath('UserProfile') } $runtime = Join-Path $jackHome '.jack' $bin = Join-Path $runtime 'bin' New-PrivateDirectory $runtime New-PrivateDirectory $bin $staging = Join-Path $bin ('.install.' + [Guid]::NewGuid().ToString('N')) $null = New-Item -ItemType Directory -Path $staging try { $asset = 'jack-windows-x64.exe' $base = "$origin/v$version" Invoke-WebRequest -UseBasicParsing -Uri "$base/$asset" -OutFile (Join-Path $staging $asset) Invoke-WebRequest -UseBasicParsing -Uri "$origin/$sums" -OutFile (Join-Path $staging 'SHA256SUMS') $checksums = @(Get-Content (Join-Path $staging 'SHA256SUMS') | Where-Object { $_ -match '^([0-9a-fA-F]{64}) jack-windows-x64\.exe$' }) if ($checksums.Count -ne 1) { throw 'Missing or invalid release checksum.' } $expected = $checksums[0].Substring(0, 64) $actual = (Get-FileHash -Algorithm SHA256 -LiteralPath (Join-Path $staging $asset)).Hash if ($actual -ne $expected) { throw 'Release checksum mismatch; Jack was not installed.' } [IO.File]::WriteAllText((Join-Path $staging 'install.json'), "{`"method`":`"script`"}`n") Move-Item -LiteralPath (Join-Path $staging $asset) -Destination (Join-Path $bin 'jack.exe') -Force Move-Item -LiteralPath (Join-Path $staging 'install.json') -Destination (Join-Path $jackHome '.jack\install.json') -Force Write-Host "Installed Jack Runtime $version to $bin\jack.exe." Write-Host "Add $bin to your user Path in Environment Variables, then open a new terminal." } finally { Remove-Item -LiteralPath $staging -Recurse -Force } }