Created
May 19, 2026 06:29
-
-
Save CypherpunkSamurai/10482a5fac89cdf1b8b0bf847f118de5 to your computer and use it in GitHub Desktop.
Rust Installer - Portable
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| Creates a portable Rust installation with virtualenv-style activation scripts. | |
| .DESCRIPTION | |
| This script creates a self-contained, portable Rust installation that can be | |
| moved between systems or run from external drives. Supports both GNU and MSVC toolchains. | |
| Creates Python virtualenv-style activate/deactivate scripts for shell integration. | |
| .PARAMETER InstallDir | |
| Directory where portable Rust will be installed. Default: .PortableRust | |
| .PARAMETER ToolchainVersion | |
| Rust toolchain version to install. Default: stable (Options: stable, beta, nightly, or specific version) | |
| .PARAMETER ToolchainType | |
| Type of toolchain to install. Default: gnu (Options: gnu, msvc) | |
| .EXAMPLE | |
| .\Install-PortableRust.ps1 | |
| Creates a portable Rust installation with GNU toolchain in .PortableRust | |
| .EXAMPLE | |
| .\Install-PortableRust.ps1 -ToolchainType msvc | |
| Creates a portable Rust installation with MSVC toolchain | |
| .EXAMPLE | |
| .\Install-PortableRust.ps1 -InstallDir "D:\Rust" -ToolchainVersion "nightly" -ToolchainType "gnu" | |
| Creates a portable nightly Rust installation with GNU toolchain in D:\Rust | |
| .EXAMPLE | |
| iwr -useb https://raw.githubusercontent.com/yourusername/Install-PortableRust.ps1/main/Install-PortableRust.ps1 | iex | |
| Downloads and runs the script directly | |
| .NOTES | |
| Author: CypherpunkSamurai | |
| Version: 1.4 (Architecture Fix) | |
| Date: 2026-05-19 | |
| #> | |
| param ( | |
| [string]$InstallDir = ".PortableRust", | |
| [string]$ToolchainVersion = "stable", | |
| [ValidateSet("gnu", "msvc")] | |
| [string]$ToolchainType = "gnu" | |
| ) | |
| function Show-Banner { | |
| $bannerColor = "Cyan" | |
| $version = "v1.4 (Architecture Fix)" | |
| Write-Host "`n=======================================================" -ForegroundColor $bannerColor | |
| Write-Host " PORTABLE RUST INSTALLER $version" -ForegroundColor $bannerColor | |
| Write-Host "=======================================================" -ForegroundColor $bannerColor | |
| Write-Host " A tool to create portable Rust development environments" -ForegroundColor $bannerColor | |
| Write-Host "=======================================================" -ForegroundColor $bannerColor | |
| Write-Host "" | |
| } | |
| function Write-ColorMessage { | |
| param( | |
| [Parameter(Mandatory=$true)] | |
| [string]$Message, | |
| [Parameter(Mandatory=$false)] | |
| [string]$ForegroundColor = "White", | |
| [switch]$NoNewline | |
| ) | |
| $params = @{ | |
| Object = $Message | |
| ForegroundColor = $ForegroundColor | |
| } | |
| if ($NoNewline) { | |
| $params.Add("NoNewline", $true) | |
| } | |
| Write-Host @params | |
| } | |
| function Initialize-InstallationDirectory { | |
| param ( | |
| [Parameter(Mandatory=$true)] | |
| [string]$Path | |
| ) | |
| Write-ColorMessage "Setting up installation directory..." "Cyan" | |
| if (-not (Test-Path -Path $Path)) { | |
| New-Item -Path $Path -ItemType Directory | Out-Null | |
| Write-ColorMessage "Created directory: $Path" "Green" | |
| } | |
| $absolutePath = (Resolve-Path $Path).Path | |
| Write-ColorMessage "Installation directory: $absolutePath" "Yellow" | |
| return $absolutePath | |
| } | |
| # ✅ FIXED: Proper PowerShell comment-based help (not Python docstrings) | |
| function Get-SystemArchitecture { | |
| <# | |
| .SYNOPSIS | |
| Detects the appropriate Rust host architecture triplet for Windows. | |
| .DESCRIPTION | |
| Returns architecture string like x86_64-pc-windows-gnu | |
| #> | |
| $arch = $env:PROCESSOR_ARCHITECTURE | |
| switch ($arch) { | |
| "ARM64" { return "aarch64-pc-windows-$ToolchainType" } | |
| "AMD64" { return "x86_64-pc-windows-$ToolchainType" } | |
| "x86" { return "i686-pc-windows-$ToolchainType" } | |
| default { | |
| if ([Environment]::Is64BitOperatingSystem) { | |
| return "x86_64-pc-windows-$ToolchainType" | |
| } | |
| return "i686-pc-windows-$ToolchainType" | |
| } | |
| } | |
| } | |
| function Get-RustupInitializer { | |
| param ( | |
| [Parameter(Mandatory=$true)] | |
| [string]$InstallDirectory, | |
| [Parameter(Mandatory=$true)] | |
| [string]$HostArch | |
| ) | |
| $rustupBaseUrl = "https://static.rust-lang.org/rustup/dist" | |
| $rustupInitUrl = "$rustupBaseUrl/$HostArch/rustup-init.exe" | |
| $rustupInitPath = Join-Path $InstallDirectory "rustup-init.exe" | |
| try { | |
| Write-ColorMessage "Downloading rustup-init.exe... " "Cyan" -NoNewline | |
| $oldProgress = $ProgressPreference | |
| $ProgressPreference = "SilentlyContinue" | |
| try { | |
| Invoke-WebRequest -Uri $rustupInitUrl -OutFile $rustupInitPath | |
| } | |
| finally { | |
| $ProgressPreference = $oldProgress | |
| } | |
| Write-ColorMessage "DONE!" "Green" | |
| return $rustupInitPath | |
| } | |
| catch { | |
| Write-ColorMessage "FAILED!" "Red" | |
| Write-ColorMessage "Error: $_" "Red" | |
| exit 1 | |
| } | |
| } | |
| function Install-Rust { | |
| param ( | |
| [Parameter(Mandatory=$true)] | |
| [string]$InitializerPath, | |
| [Parameter(Mandatory=$true)] | |
| [string]$ToolchainVersion, | |
| [Parameter(Mandatory=$true)] | |
| [string]$HostArch | |
| ) | |
| try { | |
| Write-ColorMessage "Installing Rust ($ToolchainVersion) with $HostArch toolchain..." "Cyan" | |
| & $InitializerPath --no-modify-path -y --default-toolchain $ToolchainVersion --default-host $HostArch | |
| if ($LASTEXITCODE -ne 0) { | |
| throw "rustup-init.exe failed with exit code $LASTEXITCODE" | |
| } | |
| Write-ColorMessage "Rust installation completed successfully!" "Green" | |
| Remove-Item -Path $InitializerPath -Force | |
| Write-ColorMessage "Removed rustup-init.exe" "Green" | |
| return $true | |
| } | |
| catch { | |
| Write-ColorMessage "Failed to install Rust: $_" "Red" | |
| exit 1 | |
| } | |
| } | |
| function Create-ActivationScripts { | |
| param ( | |
| [Parameter(Mandatory=$true)] | |
| [string]$InstallDirectory, | |
| [Parameter(Mandatory=$true)] | |
| [string]$RustupDir, | |
| [Parameter(Mandatory=$true)] | |
| [string]$CargoDir, | |
| [Parameter(Mandatory=$true)] | |
| [string]$HostArch | |
| ) | |
| Write-ColorMessage "Creating activation scripts..." "Cyan" | |
| $scriptsDir = Join-Path $InstallDirectory "Scripts" | |
| if (-not (Test-Path -Path $scriptsDir)) { | |
| New-Item -Path $scriptsDir -ItemType Directory | Out-Null | |
| } | |
| # FIXED: Correct path separators with backslashes | |
| $activateBatContent = @" | |
| @echo off | |
| REM Rust Virtual Environment Activation Script (CMD) | |
| set "RUSTUP_HOME=%~dp0..\.rustup" | |
| set "CARGO_HOME=%~dp0..\.cargo" | |
| set "PATH=%~dp0..\.cargo\bin;%PATH%" | |
| if "%~1"=="" goto :show_info | |
| %* | |
| goto :end | |
| :show_info | |
| if not defined _RUST_OLD_PATH ( set "_RUST_OLD_PATH=%PATH%" ) | |
| if not defined _RUST_OLD_RUSTUP_HOME ( if defined RUSTUP_HOME ( set "_RUST_OLD_RUSTUP_HOME=%RUSTUP_HOME%" ) ) | |
| if not defined _RUST_OLD_CARGO_HOME ( if defined CARGO_HOME ( set "_RUST_OLD_CARGO_HOME=%CARGO_HOME%" ) ) | |
| if not defined _RUST_OLD_PROMPT ( set "_RUST_OLD_PROMPT=%PROMPT%" ) | |
| set "PROMPT=(rust-env) %PROMPT%" | |
| echo Rust environment activated (CMD) | |
| echo Toolchain: $HostArch | |
| echo. | |
| echo Available commands: rustc, cargo, rustup | |
| echo To deactivate, run: deactivate | |
| echo. | |
| echo Quick start: cargo new my_project | |
| :end | |
| "@ | |
| $deactivateBatContent = @" | |
| @echo off | |
| if defined _RUST_OLD_PATH ( set "PATH=%_RUST_OLD_PATH%" & set "_RUST_OLD_PATH=" ) | |
| if defined _RUST_OLD_RUSTUP_HOME ( set "RUSTUP_HOME=%_RUST_OLD_RUSTUP_HOME%" & set "_RUST_OLD_RUSTUP_HOME=" ) else ( set "RUSTUP_HOME=" ) | |
| if defined _RUST_OLD_CARGO_HOME ( set "CARGO_HOME=%_RUST_OLD_CARGO_HOME%" & set "_RUST_OLD_CARGO_HOME=" ) else ( set "CARGO_HOME=" ) | |
| if defined _RUST_OLD_PROMPT ( set "PROMPT=%_RUST_OLD_PROMPT%" & set "_RUST_OLD_PROMPT=" ) | |
| echo Rust environment deactivated | |
| "@ | |
| # FIXED: Correct PowerShell path construction and secure command execution | |
| $activatePs1Content = @" | |
| # Rust Virtual Environment Activation Script (PowerShell) | |
| param( | |
| [Parameter(ValueFromRemainingArguments=`$true)] | |
| [string[]]`$Command | |
| ) | |
| function global:deactivate { | |
| if (`$env:_RUST_OLD_PATH) { `$env:PATH = `$env:_RUST_OLD_PATH; Remove-Item -Path Env:_RUST_OLD_PATH } | |
| if (`$env:_RUST_OLD_RUSTUP_HOME) { `$env:RUSTUP_HOME = `$env:_RUST_OLD_RUSTUP_HOME; Remove-Item -Path Env:_RUST_OLD_RUSTUP_HOME } elseif (`$env:RUSTUP_HOME) { Remove-Item -Path Env:RUSTUP_HOME } | |
| if (`$env:_RUST_OLD_CARGO_HOME) { `$env:CARGO_HOME = `$env:_RUST_OLD_CARGO_HOME; Remove-Item -Path Env:_RUST_OLD_CARGO_HOME } elseif (`$env:CARGO_HOME) { Remove-Item -Path Env:CARGO_HOME } | |
| if (Get-Command _OLD_RUST_PROMPT -ErrorAction SilentlyContinue) { Copy-Item -Path Function:_OLD_RUST_PROMPT -Destination Function:prompt; Remove-Item -Path Function:_OLD_RUST_PROMPT } | |
| Remove-Item -Path Function:deactivate | |
| Write-Host "Rust environment deactivated" -ForegroundColor Green | |
| } | |
| `$scriptDir = Split-Path -Parent `$MyInvocation.MyCommand.Path | |
| `$installDir = Split-Path -Parent `$scriptDir | |
| `$rustupDir = Join-Path `$installDir ".rustup" | |
| `$cargoDir = Join-Path `$installDir ".cargo" | |
| `$env:RUSTUP_HOME = `$rustupDir | |
| `$env:CARGO_HOME = `$cargoDir | |
| # FIXED: Correct path separator | |
| `$env:PATH = "`$cargoDir\bin;" + `$env:PATH | |
| if (`$Command) { | |
| if (`$Command.Count -gt 0) { | |
| `$exe = `$Command[0] | |
| `$args = if (`$Command.Count -gt 1) { `$Command[1..(`$Command.Count-1)] } else { @() } | |
| # FIXED: Secure execution with & operator | |
| & `$exe @args | |
| } | |
| } else { | |
| if (-not `$env:_RUST_OLD_PATH) { `$env:_RUST_OLD_PATH = `$env:PATH } | |
| if (`$env:RUSTUP_HOME -and -not `$env:_RUST_OLD_RUSTUP_HOME) { `$env:_RUST_OLD_RUSTUP_HOME = `$env:RUSTUP_HOME } | |
| if (`$env:CARGO_HOME -and -not `$env:_RUST_OLD_CARGO_HOME) { `$env:_RUST_OLD_CARGO_HOME = `$env:CARGO_HOME } | |
| if (Get-Command prompt -ErrorAction SilentlyContinue) { Copy-Item -Path Function:prompt -Destination Function:_OLD_RUST_PROMPT } | |
| function global:prompt { | |
| Write-Host "(rust-env) " -NoNewline -ForegroundColor Yellow | |
| if (Get-Command _OLD_RUST_PROMPT -ErrorAction SilentlyContinue) { & _OLD_RUST_PROMPT } else { "PS " + (Get-Location) + "> " } | |
| } | |
| Write-Host "Rust environment activated (PowerShell)" -ForegroundColor Green | |
| Write-Host "Toolchain: $HostArch" -ForegroundColor Cyan | |
| Write-Host "" | |
| Write-Host "Available commands: " -NoNewline; Write-Host "rustc, cargo, rustup" -ForegroundColor White | |
| Write-Host "To deactivate, run: " -NoNewline; Write-Host "deactivate" -ForegroundColor Yellow | |
| Write-Host "" | |
| Write-Host "Quick start: " -NoNewline; Write-Host "cargo new my_project" -ForegroundColor Cyan | |
| Write-Host "" | |
| Write-Host "Command runner usage: " -NoNewline; Write-Host ".\Scripts\Activate.ps1 -- cargo --version" -ForegroundColor Gray | |
| } | |
| "@ | |
| $readmePath = Join-Path $InstallDirectory "README.txt" | |
| $currentDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss" | |
| $readmeContent = @" | |
| ╔═════════════════════════════════════════════════════════════════════╗ | |
| ║ PORTABLE RUST INSTALLER v1.4 (Architecture Fix) ║ | |
| ║ Created: $currentDate ║ | |
| ║ Toolchain: $HostArch ║ | |
| ╚═════════════════════════════════════════════════════════════════════╝ | |
| USAGE: | |
| CMD: Scripts\activate.bat [command...] | |
| PowerShell: .\Scripts\Activate.ps1 [-- command args...] | |
| EXAMPLES: | |
| .\Scripts\Activate.ps1 -- cargo --version | |
| .\Scripts\Activate.ps1 -- cargo new my_project | |
| Scripts\activate.bat cargo build | |
| DEACTIVATE: | |
| Run 'deactivate' from an activated interactive shell | |
| FEATURES: | |
| ✅ Portable, movable installation | |
| ✅ Auto-detects x86_64/ARM64/x86 architecture | |
| ✅ Virtualenv-style activation | |
| ✅ No system PATH modification | |
| ✅ Pre-configured Cargo settings | |
| "@ | |
| try { | |
| $activateBatContent | Out-File -FilePath (Join-Path $scriptsDir "activate.bat") -Encoding ASCII | |
| $deactivateBatContent | Out-File -FilePath (Join-Path $scriptsDir "deactivate.bat") -Encoding ASCII | |
| $activatePs1Content | Out-File -FilePath (Join-Path $scriptsDir "Activate.ps1") -Encoding UTF8 | |
| $readmeContent | Out-File -FilePath $readmePath -Encoding UTF8 | |
| Write-ColorMessage "Created activation scripts in: $scriptsDir" "Green" | |
| return $true | |
| } | |
| catch { | |
| Write-ColorMessage "Failed to create activation scripts: $_" "Red" | |
| exit 1 | |
| } | |
| } | |
| function Test-RustInstallation { | |
| param ( | |
| [Parameter(Mandatory=$true)] | |
| [string]$CargoDir, | |
| [Parameter(Mandatory=$true)] | |
| [string]$RustupDir | |
| ) | |
| Write-ColorMessage "Verifying Rust installation..." "Cyan" | |
| $cargoBinPath = Join-Path $CargoDir "bin\cargo.exe" | |
| $rustcBinPath = Join-Path $CargoDir "bin\rustc.exe" | |
| $rustupBinPath = Join-Path $CargoDir "bin\rustup.exe" | |
| $allTestsPassed = $true | |
| foreach ($binPath in @($cargoBinPath, $rustcBinPath, $rustupBinPath)) { | |
| $binName = Split-Path $binPath -Leaf | |
| if (Test-Path -Path $binPath) { | |
| try { | |
| $output = & $binPath --version 2>&1 | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-ColorMessage "✅ $binName`: $output" "Green" | |
| } else { | |
| Write-ColorMessage "❌ $binName test failed: exit code $LASTEXITCODE" "Red" | |
| $allTestsPassed = $false | |
| } | |
| } | |
| catch { | |
| Write-ColorMessage "❌ $binName test failed: $_" "Red" | |
| $allTestsPassed = $false | |
| } | |
| } else { | |
| Write-ColorMessage "❌ $binName not found at: $binPath" "Red" | |
| $allTestsPassed = $false | |
| } | |
| } | |
| return $allTestsPassed | |
| } | |
| function Initialize-CargoConfig { | |
| param ( | |
| [Parameter(Mandatory=$true)] | |
| [string]$CargoDir | |
| ) | |
| Write-ColorMessage "Setting up Cargo configuration..." "Cyan" | |
| $cargoConfigPath = Join-Path $CargoDir "config.toml" | |
| $cargoConfigContent = @" | |
| # Portable Rust Cargo Configuration | |
| [build] | |
| # jobs = 0 # Auto-detect cores | |
| [cargo-new] | |
| name = "Your Name" | |
| email = "[email protected]" | |
| [net] | |
| retry = 3 | |
| [term] | |
| progress.when = "auto" | |
| progress.width = 80 | |
| "@ | |
| try { | |
| $cargoConfigContent | Out-File -FilePath $cargoConfigPath -Encoding UTF8 | |
| Write-ColorMessage "Created Cargo config: $cargoConfigPath" "Green" | |
| return $true | |
| } | |
| catch { | |
| Write-ColorMessage "Warning: Could not create Cargo config: $_" "Yellow" | |
| return $false | |
| } | |
| } | |
| function Test-CargoFunctionality { | |
| param ( | |
| [Parameter(Mandatory=$true)] | |
| [string]$CargoDir, | |
| [Parameter(Mandatory=$true)] | |
| [string]$InstallDir | |
| ) | |
| Write-ColorMessage "Testing Cargo functionality..." "Cyan" | |
| $cargoBinPath = Join-Path $CargoDir "bin\cargo.exe" | |
| $testProjectDir = Join-Path $InstallDir "test_project" | |
| try { | |
| if (Test-Path -Path $testProjectDir) { | |
| Remove-Item -Path $testProjectDir -Recurse -Force | |
| } | |
| $createResult = & $cargoBinPath "new" $testProjectDir --name "test_project" 2>&1 | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-ColorMessage "⚠️ Cargo new failed: $createResult" "Yellow" | |
| return $false | |
| } | |
| Push-Location $testProjectDir | |
| try { | |
| $buildResult = & $cargoBinPath "check" 2>&1 | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-ColorMessage "✅ Cargo functionality test passed" "Green" | |
| return $true | |
| } else { | |
| Write-ColorMessage "⚠️ Cargo check failed: $buildResult" "Yellow" | |
| return $false | |
| } | |
| } | |
| finally { | |
| Pop-Location | |
| } | |
| } | |
| catch { | |
| Write-ColorMessage "⚠️ Cargo functionality test failed: $_" "Yellow" | |
| return $false | |
| } | |
| finally { | |
| if (Test-Path -Path $testProjectDir) { | |
| Remove-Item -Path $testProjectDir -Recurse -Force -ErrorAction SilentlyContinue | |
| } | |
| } | |
| } | |
| function Show-Usage { | |
| Write-ColorMessage "`n🦀 USAGE (Enhanced Dual-Mode):" "Magenta" | |
| Write-ColorMessage "`nInteractive Mode:" "Cyan" | |
| Write-ColorMessage " .\Scripts\Activate.ps1 # Activate" "Gray" | |
| Write-ColorMessage " Scripts\activate.bat # Activate (CMD)" "Gray" | |
| Write-ColorMessage " deactivate # Exit" "Gray" | |
| Write-ColorMessage "`nCommand Mode:" "Cyan" | |
| Write-ColorMessage " .\Scripts\Activate.ps1 -- cargo --version" "Gray" | |
| Write-ColorMessage " Scripts\activate.bat cargo new my_project" "Gray" | |
| Write-ColorMessage "`n📦 Examples:" "Magenta" | |
| Write-ColorMessage " .\Scripts\Activate.ps1 -- cargo new hello" "Gray" | |
| Write-ColorMessage " cd hello" "Gray" | |
| Write-ColorMessage " ..\Scripts\Activate.ps1 -- cargo run" "Gray" | |
| Write-Host "" | |
| } | |
| function Install-PortableRust { | |
| param ( | |
| [string]$InstallDir = ".PortableRust", | |
| [string]$ToolchainVersion = "stable", | |
| [ValidateSet("gnu", "msvc")] | |
| [string]$ToolchainType = "gnu" | |
| ) | |
| $ErrorActionPreference = "Stop" | |
| $Host.UI.RawUI.WindowTitle = "Portable Rust Installer" | |
| # ✅ FIXED: Now returns clean string, not docstring | |
| $HostArch = Get-SystemArchitecture | |
| Show-Banner | |
| Write-ColorMessage "Starting Portable Rust Installation" "White" | |
| Write-ColorMessage " Toolchain: $HostArch" "Yellow" | |
| Write-ColorMessage " Version: $ToolchainVersion" "Yellow" | |
| Write-ColorMessage " Target: $InstallDir" "Yellow" | |
| Write-ColorMessage "`n" | |
| $InstallDir = Initialize-InstallationDirectory -Path $InstallDir | |
| $RustupDir = Join-Path $InstallDir ".rustup" | |
| $CargoDir = Join-Path $InstallDir ".cargo" | |
| $env:RUSTUP_HOME = $RustupDir | |
| $env:CARGO_HOME = $CargoDir | |
| $env:PATH = "$CargoDir\bin;$env:PATH" | |
| $rustupInitPath = Get-RustupInitializer -InstallDirectory $InstallDir -HostArch $HostArch | |
| Install-Rust -InitializerPath $rustupInitPath -ToolchainVersion $ToolchainVersion -HostArch $HostArch | |
| $installationValid = Test-RustInstallation -CargoDir $CargoDir -RustupDir $RustupDir | |
| if (-not $installationValid) { | |
| Write-ColorMessage "⚠️ Some components failed verification" "Yellow" | |
| } | |
| Initialize-CargoConfig -CargoDir $CargoDir | |
| Test-CargoFunctionality -CargoDir $CargoDir -InstallDir $InstallDir | Out-Null | |
| Create-ActivationScripts -InstallDirectory $InstallDir -RustupDir $RustupDir -CargoDir $CargoDir -HostArch $HostArch | |
| Write-ColorMessage "`n✅ Portable Rust installation is ready!" "Green" | |
| Show-Usage | |
| } | |
| # Main execution | |
| if ($MyInvocation.InvocationName -ne '.') { | |
| $scriptParams = @{} | |
| if ($PSBoundParameters.ContainsKey('InstallDir')) { $scriptParams['InstallDir'] = $InstallDir } | |
| if ($PSBoundParameters.ContainsKey('ToolchainVersion')) { $scriptParams['ToolchainVersion'] = $ToolchainVersion } | |
| if ($PSBoundParameters.ContainsKey('ToolchainType')) { $scriptParams['ToolchainType'] = $ToolchainType } | |
| Install-PortableRust @scriptParams | |
| } | |
| if ($PSScriptRoot -and (Test-Path -Path "$PSScriptRoot\*.psm1")) { | |
| Export-ModuleMember -Function Install-PortableRust | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment