Onset: version control where nobody waits and nothing gets lost. The on command, its core and onset-server.
| 1 | # Installs vcs on Windows: `irm https://downloads.coline.dev/vcs/install.ps1 | iex` |
| 2 | # |
| 3 | # Picks the build for this CPU from the channel's manifest, checks its |
| 4 | # SHA-256 before trusting it, keeps each version in its own folder and puts |
| 5 | # vcs.exe in %LOCALAPPDATA%\Programs\vcs\bin, on your PATH. Running it again |
| # updates in place. |
| 7 |
| 8 | $ErrorActionPreference = 'Stop' |
| 9 | $ProgressPreference = 'SilentlyContinue' |
| 10 |
| 11 | $Channel = if ($env:VCS_INSTALL_CHANNEL) { $env:VCS_INSTALL_CHANNEL } else { 'stable' } |
| 12 | $Base = if ($env:VCS_DOWNLOADS) { $env:VCS_DOWNLOADS } else { 'https://downloads.coline.dev/vcs' } |
| 13 | $InstallDir = if ($env:VCS_INSTALL_DIR) { $env:VCS_INSTALL_DIR } else { Join-Path $env:LOCALAPPDATA 'Programs\vcs' } |
| 14 | $BinDir = Join-Path $InstallDir 'bin' |
| 15 |
| 16 | if ($Channel -notin @('stable', 'latest')) { throw "vcs install: unknown channel '$Channel' (stable or latest)" } |
| 17 |
| 18 | $arch = try { [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString() } catch { $env:PROCESSOR_ARCHITECTURE } |
| 19 | $platform = switch -Regex ($arch) { |
| 20 | '^(X64|AMD64)$' { 'windows-x64' } |
| 21 | '^(Arm64|ARM64)$' { 'windows-arm64' } |
| 22 | default { throw "vcs install: no build for Windows on $arch yet" } |
| 23 | } |
| 24 |
| 25 | $manifest = Invoke-RestMethod -UseBasicParsing "$Base/$Channel.json" |
| 26 | $version = [string]$manifest.version |
| 27 | if ($version -notmatch '^[0-9]+\.[0-9]+\.[0-9]+([-+][A-Za-z0-9.-]+)?$') { throw 'vcs install: the manifest has no valid version' } |
| 28 | $build = $manifest.platforms.$platform |
| 29 | if (-not $build -or -not $build.url -or -not $build.sha256) { throw "vcs install: release $version has no build for $platform" } |
| 30 |
| 31 | $tmp = Join-Path ([System.IO.Path]::GetTempPath()) ("vcs-install-" + [guid]::NewGuid()) |
| 32 | New-Item -ItemType Directory -Path $tmp | Out-Null |
| 33 | try { |
| 34 | $zip = Join-Path $tmp 'vcs.zip' |
| 35 | Write-Host "Downloading vcs $version ($platform)..." |
| 36 | Invoke-WebRequest -UseBasicParsing -Uri $build.url -OutFile $zip |
| 37 | $got = (Get-FileHash -Algorithm SHA256 $zip).Hash.ToLowerInvariant() |
| 38 | if ($got -ne $build.sha256) { throw "vcs install: checksum mismatch: the download isn't the published build" } |
| 39 | Expand-Archive -Path $zip -DestinationPath (Join-Path $tmp 'x') -Force |
| 40 | $exe = Join-Path $tmp 'x\vcs.exe' |
| 41 | if (-not (Test-Path $exe)) { throw 'vcs install: the archive has no vcs.exe' } |
| 42 | & $exe --version | Out-Null |
| 43 | if ($LASTEXITCODE -ne 0) { throw "vcs install: the downloaded vcs doesn't run on this machine" } |
| 44 |
| 45 | $dest = Join-Path $InstallDir $version |
| 46 | New-Item -ItemType Directory -Force -Path $dest, $BinDir | Out-Null |
| 47 | Copy-Item $exe (Join-Path $dest 'vcs.exe') -Force |
| 48 | # A running vcs (the saver) keeps vcs.exe open; Windows lets it be |
| 49 | # renamed, not overwritten, so the old one moves aside first. |
| 50 | $bin = Join-Path $BinDir 'vcs.exe' |
| 51 | $old = Join-Path $BinDir 'vcs.old.exe' |
| 52 | Remove-Item $old -Force -ErrorAction SilentlyContinue |
| 53 | if (Test-Path $bin) { Move-Item $bin $old -Force } |
| 54 | Copy-Item $exe $bin -Force |
| 55 | Remove-Item $old -Force -ErrorAction SilentlyContinue |
| 56 | } finally { |
| 57 | Remove-Item $tmp -Recurse -Force -ErrorAction SilentlyContinue |
| 58 | } |
| 59 |
| 60 | $userPath = [Environment]::GetEnvironmentVariable('Path', 'User') |
| 61 | if (-not (($userPath -split ';') | Where-Object { $_ -ieq $BinDir })) { |
| 62 | $next = if ($userPath) { "$userPath;$BinDir" } else { $BinDir } |
| 63 | [Environment]::SetEnvironmentVariable('Path', $next, 'User') |
| 64 | $env:Path = "$env:Path;$BinDir" |
| 65 | Write-Host "Added $BinDir to your PATH (new terminals have it)." |
| 66 | } |
| 67 | Write-Host "Installed vcs $version at $bin" |
| 68 | Write-Host 'Next: vcs login, then vcs get upstream.codes/<owner>/<project>' |
| 69 |