. "$PSScriptRoot/Constants.ps1"; . "$PSScriptRoot/../Scripts/Security.ps1"; . "$PSScriptRoot/../../Common/Scripts/SoftwareManagement.ps1"; <# .SYNOPSIS Gets the name of the WSL distribution used for managing the configuration. #> function Get-WslDistributionName { return "ValhallaUbuntu"; } <# .SYNOPSIS Gets the path to the directory containing the WSL distribution. #> function Get-WslDistributionPath { Join-Path (Get-ArtifactRoot) (Get-WslDistributionName); } <# .SYNOPSIS Gets the path to the virtual hard disk of the WSL distribution. #> function Get-WslDistributionDisk { return "$(Get-WslDistributionPath)/ext4.vhdx"; } <# .SYNOPSIS Checks whether `wsl` is installed properly. #> function Test-Wsl { & { $null = wsl --status; $?; }; } <# .SYNOPSIS Checks whether any WSL distributions are installed for the current user. #> function Test-WslDistributions { & { $null = wsl -l; $?; }; } <# .SYNOPSIS Checks whether the managed distribution is installed. #> function Test-WslDistribution { & { $null = wsl -d (Get-WslDistributionName) -e true; $?; }; } <# .SYNOPSIS Installs `wsl` on the system. #> function Install-Wsl { wsl --install --no-launch; # Microsoft broke WSL - Quelle surprise! # ToDo: Remove this workaround once it's unbroken Install-SetupPackage "https://github.com/microsoft/WSL/releases/download/2.3.17/wsl.2.3.17.0.x64.msi" -ArgumentList "/Quiet"; } <# .SYNOPSIS Installs a Ubuntu distribution to a shared directory. #> function Install-WslDistribution { $dir = Get-WslDistributionPath; $root = Split-Path -Parent $dir; $ubuntuPattern = "*Ubuntu*"; $registryPath = "HKCU:/Software/Microsoft/Windows/CurrentVersion/Lxss"; $key = Get-Item $registryPath; if (-not (Get-AppxPackage $ubuntuPattern)) { Install-Wsl; } wsl --shutdown; if ($key) { $key = $key | Rename-Item -NewName "$(Split-Path -Leaf $key)_" -PassThru; } if (-not (Test-Path $root)) { $null = New-Item -ItemType Directory $root; } Copy-Item -Recurse -Force (Get-AppxPackage $ubuntuPattern).InstallLocation $dir; Set-UserPermissions $dir; & "$dir\ubuntu.exe" install --root; wsl --shutdown; Remove-Item -Recurse -Force $registryPath; if ($key) { Move-Item $key.PSPath $registryPath; } } <# .SYNOPSIS Uninstalls the managed WSL distribution. #> function Uninstall-WslDistribution { wsl --unregister (Get-WslDistributionName); } <# .SYNOPSIS Registers the managed WSL distribution. #> function Register-WslDistribution { wsl --import-in-place (Get-WslDistributionName) (Get-WslDistributionDisk); wsl --set-default (Get-WslDistributionName); } <# .SYNOPSIS Unregisters the managed WSL distribution. #> function Unregister-WslDistribution { $wslDisk = Get-WslDistributionDisk; wsl --shutdown; $tempDisk = Rename-Item -Force $wslDisk "ext4_.vhdx" -PassThru; Uninstall-WslDistribution; Move-Item $tempDisk $wslDisk; } <# .SYNOPSIS Checks whether `nix` is installed in WSL. #> function Test-Nix { wsl --shell-type login type -t nix; } <# .SYNOPSIS Installs `nix` in WSL. #> function Install-Nix { wsl -- sh `<`(curl -L https://nixos.org/nix/install`) --daemon --yes; wsl --shutdown; } <# .SYNOPSIS Execute a `nix` command in WSL. #> function Invoke-Nix { wsl --shell-type login nix --extra-experimental-features "nix-command flakes" @args; } <# .SYNOPSIS Execute a `fish` command in WSL. #> function Invoke-Fish { Invoke-Nix run nixpkgs`#fish `-- @args; } <# .SYNOPSIS Converts the specified path to linux and escapes it for the use in a script. .PARAMETER Path The path to convert. #> function ConvertTo-LinuxPath { param( [string] $Path ) & { $ErrorActionPreference = 'Continue'; $completed = $false; while (-not $completed) { $job = Start-Job { $env:Value = Resolve-Path $Using:Path; $env:WSLENV = "Value/p"; $result = wsl -- bash -c 'echo "$Value"'; wsl -e printf "%q" "$result"; }; $result = Receive-Job -Wait $job; if (-not ($result.StartsWith("/"))) { Write-Error "The result of the path conversion of ``$Path`` was unexpected: ``$result``"; continue; } if ($job.State -ne ([System.Management.Automation.JobState]::Completed)) { Write-Error "An error occurred while converting ``$Path`` to a Linux path.`nOutput: ``$result``"; continue; } $completed = $true; } $result; }; }