Add DistroLauncher

This commit is contained in:
nzbr
2024-01-11 18:17:35 +01:00
parent 567b40066d
commit 2aacfeaa90
54 changed files with 1393 additions and 20 deletions
+4 -3
View File
@@ -1,11 +1,12 @@
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
+7
View File
@@ -0,0 +1,7 @@
runs:
using: 'composite'
steps:
- name: Setup MSBuild 🧰
uses: microsoft/setup-msbuild@v1.1
with:
vs-version: '[17.2,'
+21
View File
@@ -0,0 +1,21 @@
outputs:
version:
description: 'The generated version number'
value: ${{ steps.version.outputs.version }}
runs:
using: 'composite'
steps:
- name: Generate/Set Version 🏷️
id: version
shell: pwsh
run: |
$LATEST_TAG = git describe --tags --abbrev=0 # Get the latest tag name
$COMMIT_COUNT = git rev-list --use-bitmap-index --count "$(git rev-list --tags --no-walk --max-count=1)..HEAD" # Count all commits since the last tag
$NIXOS_WSL_VERSION = "$($LATEST_TAG -replace '(.+)\.(.+)\.(.+)\..+', '$1.$2.$3').${COMMIT_COUNT}" # Compose the NixOS-WSL version number
Write-Output "version=${NIXOS_WSL_VERSION}" >> $env:GITHUB_OUTPUT
Write-Output $NIXOS_WSL_VERSION > ./VERSION
Write-Output $(git rev-parse HEAD) >> ./VERSION
((Get-Content -path ./Launcher/Launcher/Launcher.csproj -Raw) -replace '1.3.3.7',$NIXOS_WSL_VERSION) | Set-Content -Path ./Launcher/Launcher/Launcher.csproj
((Get-Content -path ./Launcher/Launcher-Appx/Package.appxmanifest -Raw) -replace '1.3.3.7',$NIXOS_WSL_VERSION) | Set-Content -Path ./Launcher/Launcher-Appx/Package.appxmanifest
+11 -2
View File
@@ -2,14 +2,23 @@ name: "Push"
on:
push:
branches: [main]
branches: [main, distro-launcher]
pull_request: {}
jobs:
build:
name: Build Tarballs 🛠️
name: Build 🛠️
uses: ./.github/workflows/run_build.yml
package:
name: Package 📦
uses: ./.github/workflows/run_package.yml
needs:
- build
secrets:
APPX_SIGNING_CERT: ${{ secrets.APPX_SIGNING_CERT }}
CERT_ALGORITHM: ${{ secrets.CERT_ALGORITHM }}
checks:
name: Flake Checks 📋
uses: ./.github/workflows/run_checks.yml
+22 -2
View File
@@ -6,23 +6,41 @@ on:
jobs:
build:
name: Build Tarballs 🛠️
name: Build 🛠️
uses: ./.github/workflows/run_build.yml
package:
name: Package 📦
uses: ./.github/workflows/run_package.yml
needs:
- build
secrets:
APPX_SIGNING_CERT: ${{ secrets.APPX_SIGNING_CERT }}
CERT_ALGORITHM: ${{ secrets.CERT_ALGORITHM }}
release:
needs:
- build
- package
name: Create Release 📢
runs-on: ubuntu-latest
steps:
- name: Download Tarball 📥
uses: actions/download-artifact@v4
- name: Download appx 📥
uses: actions/download-artifact@v4
with:
name: appx
- name: Rename appx ✏️
run: mv */*.msixbundle NixOS-WSL.msixbundle
- name: Generate Checksums 🔑
run: |
mv tarball-modern/nixos-wsl.tar.gz nixos-wsl.tar.gz
mv tarball-legacy/nixos-wsl.tar.gz nixos-wsl-legacy.tar.gz
for x in *.tar.gz; do
for x in *.{tar.gz,msixbundle}; do
sha256sum $x > ${x}.sha256
done
@@ -34,5 +52,7 @@ jobs:
nixos-wsl.tar.gz.sha256
nixos-wsl-legacy.tar.gz
nixos-wsl-legacy.tar.gz.sha256
NixOS-WSL.msixbundle
NixOS-WSL.msixbundle.sha256
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+35 -12
View File
@@ -1,11 +1,11 @@
name: Build Tarballs
name: Build Tarball
on:
workflow_call: {}
jobs:
build:
name: Build 🛠️
tar:
name: Tarball 🛠️
runs-on: ubuntu-latest
strategy:
matrix:
@@ -22,17 +22,12 @@ jobs:
- name: Install Nix ❄️
uses: ./.github/actions/install-nix
- name: Generate Version 🏷️
- name: Set Version 🏷️
uses: ./.github/actions/version
id: version
shell: pwsh
run: |
$LATEST_TAG = git describe --tags --abbrev=0 # Get the latest tag name
$COMMIT_COUNT = git rev-list --use-bitmap-index --count "$(git rev-list --tags --no-walk --max-count=1)..HEAD" # Count all commits since the last tag
$NIXOS_WSL_VERSION = "$($LATEST_TAG -replace '(.+)\.(.+)\.(.+)\..+', '$1.$2.$3').${COMMIT_COUNT}" # Compose the NixOS-WSL version number
echo "version=$NIXOS_WSL_VERSION" >> $env:GITHUB_OUTPUT
echo $NIXOS_WSL_VERSION > ./VERSION
echo $(git rev-parse HEAD) >> ./VERSION
- name: Summary Headline 📝
run: echo '## NixOS-WSL ${{ steps.version.outputs.version }}' >> $GITHUB_STEP_SUMMARY
- name: Build Tarball 🛠️
uses: ./.github/actions/build-wsl-tarball
@@ -45,3 +40,31 @@ jobs:
with:
name: tarball-${{ matrix.config }}
path: nixos-wsl.tar.gz
launcher:
name: Launcher 🛠️
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup MSBuild 🧰
uses: ./.github/actions/setup-msbuild
- name: Set Versions 🏷️
uses: ./.github/actions/version
- name: Build Launcher
run: |
cd Launcher
dotnet publish --self-contained -r win-x64 -c Release -p:ContinuousIntegrationBuild=true -p:Deterministic=true --output Launcher\pkg Launcher
- name: Upload Launcher 📤
uses: actions/upload-artifact@v4
with:
name: launcher-bin
path: |
Launcher/Launcher/obj
Launcher/Launcher/pkg
+91
View File
@@ -0,0 +1,91 @@
name: Build Tarball
on:
workflow_call:
secrets:
APPX_SIGNING_CERT: {}
CERT_ALGORITHM: {}
jobs:
launcher-bundle:
name: ZIP 📦
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download tarball 📥
uses: actions/download-artifact@v4
with:
name: tarball-modern
- name: Download launcher binaries 📥
uses: actions/download-artifact@v4
with:
name: launcher-bin
path: Launcher/Launcher/
- name: Bundle tarball with launcher 📦
run: |
Copy-Item nixos-wsl.tar.gz Launcher\Launcher\pkg\
- name: Upload Launcher 📤
uses: actions/upload-artifact@v4
with:
name: launcher-bundle
path: Launcher/Launcher/pkg
launcher-msix:
name: MSIX 📦
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download tarball 📥
uses: actions/download-artifact@v4
with:
name: tarball-modern
- name: Download launcher binaries 📥
uses: actions/download-artifact@v4
with:
name: launcher-bin
path: Launcher/Launcher/
- name: Bundle tarball with launcher 📦
run: |
Copy-Item nixos-wsl.tar.gz Launcher\Launcher-Appx\
- name: Setup MSBuild 🧰
uses: ./.github/actions/setup-msbuild
- name: Set Versions 🏷️
uses: ./.github/actions/version
- name: Build MSIX package 📦
run: |
cd Launcher
nuget restore
msbuild Launcher-Appx\Launcher-Appx.wapproj /p:Configuration=Release /p:Platform=x64 /p:ContinuousIntegrationBuild=true /p:Deterministic=true
- name: Sign package ✒️
env:
APPX_SIGNING_CERT: ${{ secrets.APPX_SIGNING_CERT }}
CERT_ALGORITHM: ${{ secrets.CERT_ALGORITHM }}
if: env.APPX_SIGNING_CERT != ''
run: |
Write-Output $env:APPX_SIGNING_CERT > appx-cert.b64
certutil -decode appx-cert.b64 appx-cert.pfx
&"C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\signtool.exe" sign /fd $env:CERT_ALGORITHM /a /f appx-cert.pfx $(Get-ChildItem -Recurse -Filter "*.msixbundle")[0].FullName
Get-PfxCertificate appx-cert.pfx | Export-Certificate -FilePath "$($(Get-ChildItem -Recurse -Filter "*.msixbundle")[0].Directory.FullName)\certificate.cer" -Type CERT
- name: Upload MSIX 📤
uses: actions/upload-artifact@v4
with:
name: launcher-msix
path: Launcher/Launcher-Appx/AppPackages/
+8
View File
@@ -0,0 +1,8 @@
[*.cs]
indent_size = 4
csharp_new_line_before_open_brace = none
csharp_style_var_when_type_is_apparent = true
csharp_style_var_for_built_in_types = true
csharp_new_line_before_else = false
csharp_new_line_before_catch = false
csharp_new_line_before_finally = false
+12
View File
@@ -0,0 +1,12 @@
bin/
*.dll
*.exe
*.appx
*.cache
.vs/
.idea/
*.DotSettings.user
obj/
AppPackages/
BundleArtifacts/
*.pfx
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '15.0'">
<VisualStudioVersion>15.0</VisualStudioVersion>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup>
<WapProjPath Condition="'$(WapProjPath)'==''">$(MSBuildExtensionsPath)\Microsoft\DesktopBridge\</WapProjPath>
</PropertyGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.props" />
<PropertyGroup>
<ProjectGuid>b2533ea5-9dd5-41bb-bf00-a1d0fdba58b7</ProjectGuid>
<TargetPlatformVersion>10.0.22000.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.18362.0</TargetPlatformMinVersion>
<DefaultLanguage>de-DE</DefaultLanguage>
<AppxPackageSigningEnabled>False</AppxPackageSigningEnabled>
<NoWarn>$(NoWarn);NU1702</NoWarn>
<PackageCertificateKeyFile>Launcher-Appx_TemporaryKey.pfx</PackageCertificateKeyFile>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
<GenerateTestArtifacts>True</GenerateTestArtifacts>
<AppxBundlePlatforms>x64</AppxBundlePlatforms>
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
<EntryPointProjectUniqueName>..\Launcher\Launcher.csproj</EntryPointProjectUniqueName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DefaultLanguage>en-US</DefaultLanguage>
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<DefaultLanguage>en-US</DefaultLanguage>
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<Content Include="Images\SplashScreen.scale-200.png" />
<Content Include="Images\LockScreenLogo.scale-200.png" />
<Content Include="Images\Square150x150Logo.scale-200.png" />
<Content Include="Images\Square44x44Logo.scale-200.png" />
<Content Include="Images\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Images\StoreLogo.png" />
<Content Include="Images\Wide310x150Logo.scale-200.png" />
<Content Include="nixos-wsl.tar.gz" />
</ItemGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
<ItemGroup>
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22000.197" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Launcher\Launcher.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebuggerFlavor>AppHostLocalDebugger</DebuggerFlavor>
<RemoteDebugEnabled>False</RemoteDebugEnabled>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebuggerFlavor>AppHostLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup>
<UapAppxPackageBuildMode>SideloadOnly</UapAppxPackageBuildMode>
<AppxShowAllApps>False</AppxShowAllApps>
<AppxBuildConfigurationSelection>x64</AppxBuildConfigurationSelection>
<PackageOptionalProjectsInIdeBuilds>False</PackageOptionalProjectsInIdeBuilds>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>AppHostLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>AppHostLocalDebugger</DebuggerFlavor>
<RemoteDebugEnabled>False</RemoteDebugEnabled>
<DebuggerType>Mixed</DebuggerType>
</PropertyGroup>
</Project>
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp uap2 uap3 rescap desktop">
<Identity
Name="NixOS"
Publisher="CN=nzbr"
Version="1.3.3.7"
ProcessorArchitecture="x64"/>
<Properties>
<DisplayName>NixOS</DisplayName>
<PublisherDisplayName>nzbr</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0"/>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0"/>
</Dependencies>
<Capabilities>
<rescap:Capability Name="runFullTrust"/>
</Capabilities>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="NixOS"
Executable="Launcher\NixOS.exe"
EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements
Description="NixOS WSL Distro Launcher"
BackgroundColor="#FFFFFF"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png" DisplayName="NixOS">
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Images\SplashScreen.png"/>
</uap:VisualElements>
<Extensions>
<uap3:Extension Category="windows.appExecutionAlias" Executable="Launcher\NixOS.exe"
EntryPoint="Windows.FullTrustApplication">
<uap3:AppExecutionAlias>
<desktop:ExecutionAlias Alias="NixOS.exe"/>
</uap3:AppExecutionAlias>
</uap3:Extension>
</Extensions>
</Application>
</Applications>
</Package>
+52
View File
@@ -0,0 +1,52 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32407.343
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Launcher", "Launcher\Launcher.csproj", "{8EB5612C-BFFA-43EF-AAC6-68AB01DA30CA}"
EndProject
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Launcher-Appx", "Launcher-Appx\Launcher-Appx.wapproj", "{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{86D47DB8-0919-4929-9841-EC9B8FCB282F}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
default.nix = default.nix
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8EB5612C-BFFA-43EF-AAC6-68AB01DA30CA}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{8EB5612C-BFFA-43EF-AAC6-68AB01DA30CA}.Debug|ARM64.Build.0 = Debug|Any CPU
{8EB5612C-BFFA-43EF-AAC6-68AB01DA30CA}.Debug|x64.ActiveCfg = Debug|Any CPU
{8EB5612C-BFFA-43EF-AAC6-68AB01DA30CA}.Debug|x64.Build.0 = Debug|Any CPU
{8EB5612C-BFFA-43EF-AAC6-68AB01DA30CA}.Release|ARM64.ActiveCfg = Release|Any CPU
{8EB5612C-BFFA-43EF-AAC6-68AB01DA30CA}.Release|ARM64.Build.0 = Release|Any CPU
{8EB5612C-BFFA-43EF-AAC6-68AB01DA30CA}.Release|x64.ActiveCfg = Release|Any CPU
{8EB5612C-BFFA-43EF-AAC6-68AB01DA30CA}.Release|x64.Build.0 = Release|Any CPU
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Debug|ARM64.ActiveCfg = Release|ARM64
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Debug|ARM64.Build.0 = Release|ARM64
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Debug|ARM64.Deploy.0 = Release|ARM64
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Debug|x64.ActiveCfg = Release|x64
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Debug|x64.Build.0 = Release|x64
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Debug|x64.Deploy.0 = Release|x64
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Release|ARM64.ActiveCfg = Release|ARM64
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Release|ARM64.Build.0 = Release|ARM64
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Release|ARM64.Deploy.0 = Release|ARM64
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Release|x64.ActiveCfg = Release|x64
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Release|x64.Build.0 = Release|x64
{B2533EA5-9DD5-41BB-BF00-A1D0FDBA58B7}.Release|x64.Deploy.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6515FF51-7BEF-41B2-A3ED-1D5025A3BFA4}
EndGlobalSection
EndGlobal
+8
View File
@@ -0,0 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_CATCH_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ELSE_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_FINALLY_ON_NEW_LINE/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
+23
View File
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<AssemblyName>NixOS</AssemblyName>
<Version>1.3.3.7</Version>
<ApplicationIcon>nixos.ico</ApplicationIcon>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Content Include="nixos.ico" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.CommandLine" Version="2.0.0-beta3.22114.1" />
</ItemGroup>
</Project>
Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

+30
View File
@@ -0,0 +1,30 @@
using System.CommandLine;
using Launcher.Helpers;
namespace Launcher.Commands;
public static class Install {
public static Command GetCommand() {
var command = new Command("install") {
Description = $"Install {DistributionInfo.DisplayName} if it has not been installed already"
};
var reinstallOpt = new Option<bool>("--reinstall") {
Description = "Delete the existing installation and install a fresh copy"
};
command.Add(reinstallOpt);
command.SetHandler((bool reinstall) => {
if (reinstall) {
var result = InstallationHelper.Uninstall();
if (result != 0) {
Program.result = result;
return;
}
}
Program.result = InstallationHelper.Install();
}, reinstallOpt);
return command;
}
}
@@ -0,0 +1,31 @@
using System.CommandLine;
using WSL;
namespace Launcher.Commands;
public static class Registered {
public static Command GetCommand() {
var command = new Command("registered") {
Description = "Check whether or not the distribution is registered"
};
var quietOpt = new Option<bool>(new[] { "--quiet", "-q" }) {
Description = "Only return the appropriate exit code, dont write to the console"
};
command.Add(quietOpt);
command.SetHandler((bool quiet) => {
var registered = WslApiLoader.WslIsDistributionRegistered(DistributionInfo.Name);
if (!quiet) {
if (registered)
Console.WriteLine($"{DistributionInfo.Name} is registered");
else
Console.WriteLine($"{DistributionInfo.Name} is not registered");
}
Program.result = registered ? 0 : 1;
}, quietOpt);
return command;
}
}
+40
View File
@@ -0,0 +1,40 @@
using System.CommandLine;
using Launcher.Helpers;
using WSL;
namespace Launcher.Commands;
public static class Run {
public static Command GetCommand() {
var command = new Command("run") {
Description =
"Run a command in the current directory. If no command is specified, the default shell is launched"
};
var argCmd = new Argument<string>("command") {
Arity = ArgumentArity.ZeroOrOne
};
command.AddArgument(argCmd);
command.SetHandler((string? cmd) => {
uint exitCode;
if (!WslApiLoader.WslIsDistributionRegistered(DistributionInfo.Name)) {
Console.Error.WriteLine($"{DistributionInfo.DisplayName} is not installed!");
Program.result = 1;
return;
}
try {
WslApiLoader.WslLaunchInteractive(DistributionInfo.Name, cmd, true, out exitCode);
} catch (WslApiException e) {
Console.Error.WriteLine("An error occured when starting the command!");
Program.result = e.HResult;
return;
}
Program.result = (int)exitCode;
}, argCmd);
return command;
}
}
@@ -0,0 +1,16 @@
using System.CommandLine;
using Launcher.Helpers;
namespace Launcher.Commands;
public static class Uninstall {
public static Command GetCommand() {
var command = new Command("uninstall") {
Description = $"Uninstall {DistributionInfo.DisplayName}"
};
command.SetHandler(() => { Program.result = InstallationHelper.Uninstall(); });
return command;
}
}
@@ -0,0 +1,9 @@
namespace Launcher;
internal static class DistributionInfo {
public const string DisplayName = "NixOS";
public const string WindowTitle = "NixOS";
// Name that the distro is registered as in WSL. Can be overridden with --distro-name
public static string Name = "NixOS";
}
@@ -0,0 +1,92 @@
using System.Reflection;
using WSL;
namespace Launcher.Helpers;
public static class InstallationHelper {
/// <summary>
/// Registers the distribution and runs first-time setup
/// </summary>
/// <returns>0 on success, an error code otherwise</returns>
public static int Install() {
Console.WriteLine($"Registering {DistributionInfo.DisplayName}...");
if (WslApiLoader.WslIsDistributionRegistered(DistributionInfo.Name)) {
Console.Error.WriteLine($"{DistributionInfo.DisplayName} is already installed!");
return 0;
}
// Determine tarball location
var tarPath = FindTarball();
if (tarPath == null) {
Console.Error.WriteLine("Could not find distro tarball");
return 1;
}
try {
WslApiLoader.WslRegisterDistribution(
DistributionInfo.Name,
tarPath
);
} catch (WslApiException e) {
Console.Error.WriteLine("There was an error registering the distribution");
return e.HResult;
}
Console.WriteLine("Installation finished successfully");
return 0;
}
/// <summary>
/// Unregister the distribution
/// </summary>
/// <returns>0 on success and an error code otherwise</returns>
public static int Uninstall() {
Console.WriteLine($"Uninstalling {DistributionInfo.DisplayName}...");
if (!WslApiLoader.WslIsDistributionRegistered(DistributionInfo.Name)) {
Console.Error.WriteLine($"{DistributionInfo.DisplayName} is not installed!");
return 1;
}
try {
WslApiLoader.WslUnregisterDistribution(DistributionInfo.Name);
} catch (WslApiException e) {
Console.Error.WriteLine("An error occured when unregistering the distribution!");
return e.HResult;
}
Console.WriteLine("Uninstall completed");
return 0;
}
/// <summary>
/// Find the path of the installer tarball
/// </summary>
/// <returns>the full path to the tarball or null</returns>
public static string? FindTarball() {
const string tarFileName = "nixos-wsl.tar.gz";
// Accept a tarball in the current directory when running a debug build
#if (DEBUG)
var pwd = Directory.GetCurrentDirectory();
var debugTarPath = Path.Combine(pwd, tarFileName);
if (File.Exists(debugTarPath)) return debugTarPath;
#endif
// Look for the tarball in the same directory as the executable
var assemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
if (assemblyPath == null) return null;
var tarPath = Path.Combine(assemblyPath, tarFileName);
if (File.Exists(tarPath)) return tarPath;
// In the APPX package, the tarball is in the parent directory
var parentDirectory = Directory.GetParent(assemblyPath)?.FullName;
if (parentDirectory == null) return null;
tarPath = Path.Combine(parentDirectory, tarFileName);
return File.Exists(tarPath)
? tarPath
: null;
}
}
@@ -0,0 +1,29 @@
using WSL;
namespace Launcher.Helpers;
public static class StartupHelper {
private static bool booted;
public static bool BootDistro() {
if (booted) return true;
try {
WslApiLoader.WslLaunchInteractive(
DistributionInfo.Name,
"/bin/sh -c \"exit\"", // Don't run anything, exit after we get a shell
false,
out var exitCode
);
if (exitCode != 0) {
Console.Error.WriteLine("An error occured during the distro's startup process");
return false;
}
} catch (WslApiException) {
Console.Error.WriteLine("An error occured while trying to run a command in the distro");
return false;
}
booted = true;
return true;
}
}
@@ -0,0 +1,60 @@
using System.Reflection;
using System.Text.Json;
using WSL;
namespace Launcher.Helpers;
public static class VersionHelper {
public static Version? LauncherVersion => typeof(VersionHelper).Assembly.GetName().Version;
public static NixosWslVersion? InstalledVersion {
get {
try {
if (StartupHelper.BootDistro()) {
var output = WslApiLoader.WslLaunchGetOutput(
DistributionInfo.Name,
"/bin/sh --login -c \"nixos-wsl-version --json\"",
false,
out var exitCode,
true
).Trim();
var json = JsonSerializer.Deserialize<Dictionary<string, string>>(output);
var version = json!["release"];
if (exitCode == 0) return new NixosWslVersion(version);
}
} catch (Exception) {
// ignored
}
return null;
}
}
public class NixosWslVersion {
private readonly Version _version;
private readonly string _versionString;
internal NixosWslVersion(string versionString) {
_versionString = versionString;
if (Version.TryParse(versionString, out var ver)) {
_version = ver;
return;
}
_version = versionString == "DEV_BUILD"
? new Version(int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue)
: new Version(0, 0, 0, 0);
}
public Version AsVersion() {
return _version;
}
public override string ToString() {
return _versionString;
}
}
}
+102
View File
@@ -0,0 +1,102 @@
using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Invocation;
using System.CommandLine.IO;
using System.CommandLine.Parsing;
using Launcher.Commands;
using Launcher.Helpers;
using WSL;
namespace Launcher;
internal static class Program {
public static int result;
public static async Task<int> Main(string[] args) {
// Set title of the console
Console.Title = DistributionInfo.WindowTitle;
// Argparse docs: https://github.com/dotnet/command-line-api
var rootCommand = new RootCommand(
$"Manage the {DistributionInfo.DisplayName} WSL distribution"
) {
Run.GetCommand(),
Install.GetCommand(),
Registered.GetCommand(),
Uninstall.GetCommand(),
};
var distroNameOption = new Option<string>("--distro-name") {
Description = "WSL distribution name",
Arity = ArgumentArity.ZeroOrOne
};
distroNameOption.SetDefaultValue(DistributionInfo.Name);
var versionOption = new Option<bool>("--version") {
Description = "Show version information"
};
// Add the global options to the root command and all subcommands
rootCommand.AddOption(distroNameOption);
rootCommand.AddOption(versionOption);
foreach (var subcommand in rootCommand.Subcommands) {
subcommand.AddOption(distroNameOption);
subcommand.AddOption(versionOption);
}
rootCommand.SetHandler(() => {
if (!WslApiLoader.WslIsDistributionRegistered(DistributionInfo.Name)) {
result = InstallationHelper.Install();
if (result != 0) return;
}
try {
WslApiLoader.WslLaunchInteractive(DistributionInfo.Name, null, true, out var exitCode);
result = (int)exitCode;
} catch (WslApiException e) {
Console.Error.WriteLine("An error occured when starting the shell");
result = e.HResult;
}
});
var commandLineBuilder = new CommandLineBuilder(rootCommand)
.UseHelp()
.UseEnvironmentVariableDirective()
.UseParseDirective()
.UseSuggestDirective()
.RegisterWithDotnetSuggest()
.UseTypoCorrections()
.UseParseErrorReporting()
.UseExceptionHandler()
.CancelOnProcessTermination();
// Implement --distro-name option
commandLineBuilder.AddMiddleware(async (context, next) => {
var distroNameResult = context.ParseResult.FindResultFor(distroNameOption);
if (distroNameResult is { Tokens.Count: > 0 }) DistributionInfo.Name = distroNameResult.Tokens[0].ToString();
await next(context);
}, (MiddlewareOrder)(-1300)); // Run before --version
// Implement --version option
commandLineBuilder.AddMiddleware(async (context, next) => {
var versionResult = context.ParseResult.FindResultFor(versionOption);
if (versionResult != null) {
var vl = VersionHelper.LauncherVersion?.ToString();
var vi = VersionHelper.InstalledVersion?.ToString() ?? "UNKNOWN";
context.Console.Out.WriteLine($"Launcher: {vl}");
context.Console.Out.WriteLine($"Module: {vi}");
} else {
await next(context);
}
}, (MiddlewareOrder)(-1200)); // Internal value for the builtin version option
await commandLineBuilder.Build().InvokeAsync(args);
return result;
}
}
@@ -0,0 +1,12 @@
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
namespace WSL.Kernel32;
public static partial class Kernel32Loader {
[DllImport("kernel32.dll", SetLastError = true)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
}
@@ -0,0 +1,13 @@
using System.Runtime.InteropServices;
namespace WSL.Kernel32;
public static partial class Kernel32Loader {
[DllImport("kernel32.dll")]
public static extern bool CreatePipe(
out IntPtr hReadPipe,
out IntPtr hWritePipe,
ref SECURITY_ATTRIBUTES lpPipeAttributes,
uint nSize
);
}
@@ -0,0 +1,9 @@
using System.Runtime.InteropServices;
namespace WSL.Kernel32;
public static partial class Kernel32Loader {
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
}
@@ -0,0 +1,8 @@
using System.Runtime.InteropServices;
namespace WSL.Kernel32;
public static partial class Kernel32Loader {
[DllImport("kernel32.dll")]
public static extern int GetProcessId(IntPtr handle);
}
@@ -0,0 +1,12 @@
using System.Runtime.InteropServices;
namespace WSL.Kernel32;
public static partial class Kernel32Loader {
public static int STD_INPUT_HANDLE = -10;
public static int STD_OUTPUT_HANDLE = -11;
public static int STD_ERROR_HANDLE = -12;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
}
@@ -0,0 +1,14 @@
using System.Runtime.InteropServices;
namespace WSL.Kernel32;
public static partial class Kernel32Loader {
[DllImport(@"kernel32.dll", SetLastError = true)]
public static extern unsafe bool ReadFile(
IntPtr hFile,
IntPtr pBuffer,
int NumberOfBytesToRead,
out int pNumberOfBytesRead,
IntPtr lpOverlapped
);
}
@@ -0,0 +1,12 @@
using System.Runtime.InteropServices;
namespace WSL.Kernel32;
public static partial class Kernel32Loader {
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES {
public int nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
}
@@ -0,0 +1,28 @@
using System.Runtime.InteropServices;
namespace WSL.Kernel32;
public static partial class Kernel32Loader {
public const UInt32 INFINITE = 0xFFFFFFFF;
const UInt32 WAIT_ABANDONED = 0x00000080;
const UInt32 WAIT_OBJECT_0 = 0x00000000;
const UInt32 WAIT_TIMEOUT = 0x00000102;
public static void WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds) {
[DllImport("kernel32.dll", SetLastError = true)]
// ReSharper disable once LocalFunctionHidesMethod
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
var result = WaitForSingleObject(hHandle, dwMilliseconds);
if (result == WAIT_OBJECT_0) {
return;
}
if (result == WAIT_TIMEOUT) {
throw new TimeoutException();
}
if (result == WAIT_ABANDONED) {
throw new AbandonedMutexException();
}
throw new Exception("WaitForSingleObject failed");
}
}
@@ -0,0 +1,17 @@
namespace WSL;
public class WslApiException : Exception {
private long hresult;
WslApiException(long hresult) {
this.hresult = hresult;
}
public static void checkResult(long hresult) {
if (hresult != 0) {
throw new WslApiException(hresult);
}
}
public override string Message => $"WSL API Error {hresult}";
}
@@ -0,0 +1,20 @@
using System.Runtime.InteropServices;
namespace WSL;
public static partial class WslApiLoader {
public static void WslConfigureDistribution(
string distributionName,
ulong defaultUID,
WSL_DISTRIBUTION_FLAGS wslDistributionFlags
) {
[DllImport("wslapi.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
// ReSharper disable once LocalFunctionHidesMethod
static extern long WslConfigureDistribution(
string distributionName,
ulong defaultUID,
WSL_DISTRIBUTION_FLAGS wslDistributionFlags
);
WslApiException.checkResult(WslConfigureDistribution(distributionName, defaultUID, wslDistributionFlags));
}
}
@@ -0,0 +1,21 @@
namespace WSL;
public static partial class WslApiLoader {
[Flags]
public enum WSL_DISTRIBUTION_FLAGS {
WSL_DISTRIBUTION_FLAGS_NONE = 0x0,
WSL_DISTRIBUTION_FLAGS_ENABLE_INTEROP = 0x1,
WSL_DISTRIBUTION_FLAGS_APPEND_NT_PATH = 0x2,
WSL_DISTRIBUTION_FLAGS_ENABLE_DRIVE_MOUNTING = 0x4
}
public static WSL_DISTRIBUTION_FLAGS WSL_DISTRIBUTION_FLAGS_VALID =
WSL_DISTRIBUTION_FLAGS.WSL_DISTRIBUTION_FLAGS_ENABLE_INTEROP |
WSL_DISTRIBUTION_FLAGS.WSL_DISTRIBUTION_FLAGS_APPEND_NT_PATH |
WSL_DISTRIBUTION_FLAGS.WSL_DISTRIBUTION_FLAGS_ENABLE_DRIVE_MOUNTING;
public static WSL_DISTRIBUTION_FLAGS WSL_DISTRIBUTION_FLAGS_DEFAULT =
WSL_DISTRIBUTION_FLAGS.WSL_DISTRIBUTION_FLAGS_ENABLE_INTEROP |
WSL_DISTRIBUTION_FLAGS.WSL_DISTRIBUTION_FLAGS_APPEND_NT_PATH |
WSL_DISTRIBUTION_FLAGS.WSL_DISTRIBUTION_FLAGS_ENABLE_DRIVE_MOUNTING;
}
@@ -0,0 +1,63 @@
using System.Data;
using System.Runtime.InteropServices;
namespace WSL;
public static partial class WslApiLoader {
// Wrap this method, so that we can get a managed string array out of it instead of char***
public static unsafe void WslGetDistributionConfiguration(
string distributionName,
out ulong distributionVersion,
out ulong defaultUID,
out WslApiLoader.WSL_DISTRIBUTION_FLAGS wslDistributionFlags,
out string[] defaultEnvironmentVariables
) {
[DllImport("wslapi.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
// ReSharper disable once LocalFunctionHidesMethod
static extern long WslGetDistributionConfiguration(
string distributionName,
out ulong distributionVersion,
out ulong defaultUID,
out WslApiLoader.WSL_DISTRIBUTION_FLAGS wslDistributionFlags,
out byte** defaultEnvironmentVariables,
out ulong defaultEnvironmentVariableCount
);
byte** envv;
ulong envc;
WslApiException.checkResult(
WslGetDistributionConfiguration(
distributionName,
out distributionVersion,
out defaultUID,
out wslDistributionFlags,
out envv,
out envc)
);
defaultEnvironmentVariables = new string[envc];
var anyNull = false;
for (ulong i = 0; i < envc; i++) {
var ptr = new IntPtr(*(envv + i)); // Get the pointer to the string at offset i and dereference it
var str = Marshal
.PtrToStringAnsi(ptr); // Create a managed string from the char* pointer (_needs_ to be ANSI)
if (str == null) {
anyNull = true;
continue;
}
Marshal.FreeHGlobal(ptr); // Free the string
defaultEnvironmentVariables[i] = str;
}
Marshal.FreeHGlobal(new IntPtr(envv)); // Free the array
if (anyNull)
throw new NoNullAllowedException(
"One of the strings in the environment array returned by wslapi.dll is null");
}
}
@@ -0,0 +1,8 @@
using System.Runtime.InteropServices;
namespace WSL;
public static partial class WslApiLoader {
[DllImport("wslapi.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
public static extern bool WslIsDistributionRegistered(string distributionName);
}
+41
View File
@@ -0,0 +1,41 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using WSL.Kernel32;
namespace WSL;
public static partial class WslApiLoader {
public static void WslLaunch(
string distributionName,
string? command,
bool useCurrentWorkingDirectory,
IntPtr stdIn,
IntPtr stdOut,
IntPtr stdErr,
out IntPtr process
) {
[DllImport("wslapi.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
// ReSharper disable once LocalFunctionHidesMethod
static extern long WslLaunch(
string distributionName,
string? command,
bool useCurrentWorkingDirectory,
IntPtr stdIn,
IntPtr stdOut,
IntPtr stdErr,
out IntPtr process
);
WslApiException.checkResult(
WslLaunch(
distributionName,
command,
useCurrentWorkingDirectory,
stdIn,
stdOut,
stdErr,
out process
)
);
}
}
@@ -0,0 +1,84 @@
using System.Runtime.InteropServices;
using System.Text;
using WSL.Kernel32;
namespace WSL;
public static partial class WslApiLoader {
// Contains code from https://github.com/wslhub/wsl-sdk-dotnet/blob/892e8b5564170eae9944649cf8ab424ce0fbce52/src/Wslhub.Sdk/Wsl.cs#L364
public static unsafe string WslLaunchGetOutput(
string distributionName,
string command,
bool useCurrentWorkingDirectory,
out uint exitCode,
bool noStderr = false
) {
var stdin = Kernel32Loader.GetStdHandle(Kernel32Loader.STD_INPUT_HANDLE);
var stderr = Kernel32Loader.GetStdHandle(Kernel32Loader.STD_ERROR_HANDLE);
var attributes = new Kernel32Loader.SECURITY_ATTRIBUTES {
lpSecurityDescriptor = IntPtr.Zero,
bInheritHandle = true,
};
attributes.nLength = Marshal.SizeOf(attributes);
if (!Kernel32Loader.CreatePipe(out IntPtr readPipe, out IntPtr writePipe, ref attributes, 0))
throw new Exception("Cannot create stdout pipe");
var stderrRead = IntPtr.Zero;
var stderrWrite = IntPtr.Zero;
if (noStderr) {
if (!Kernel32Loader.CreatePipe(out stderrRead, out stderrWrite, ref attributes, 0))
throw new Exception("Cannot create stderr pipe");
stderr = stderrWrite;
}
try {
WslLaunch(distributionName, command, useCurrentWorkingDirectory, stdin, writePipe, stderr,
out var hProcess);
Kernel32Loader.WaitForSingleObject(hProcess, Kernel32Loader.INFINITE);
if (!Kernel32Loader.GetExitCodeProcess(hProcess, out exitCode)) {
Kernel32Loader.CloseHandle(hProcess);
throw new Exception("Could not get exit code of WSL process");
}
Kernel32Loader.CloseHandle(hProcess);
Kernel32Loader.CloseHandle(writePipe); // Make sure the pipe is closed if the spawned process has not done that
const int bufferLength = 65536;
var bufferPointer = Marshal.AllocHGlobal(bufferLength);
var outputContents = new StringBuilder();
var encoding = new UTF8Encoding(false);
var read = 0;
do {
if (!Kernel32Loader.ReadFile(readPipe, bufferPointer, bufferLength, out read, IntPtr.Zero)) {
var lastError = Marshal.GetLastWin32Error();
if (lastError != 0) {
Marshal.FreeHGlobal(bufferPointer);
throw new Exception("Could not read from pipe");
}
break;
}
outputContents.Append(encoding.GetString((byte*)bufferPointer.ToPointer(), read));
} while (read == bufferLength);
Marshal.FreeHGlobal(bufferPointer);
return outputContents.ToString();
} finally {
Kernel32Loader.CloseHandle(readPipe);
Kernel32Loader.CloseHandle(writePipe);
if (noStderr) {
Kernel32Loader.CloseHandle(stderrRead);
Kernel32Loader.CloseHandle(stderrWrite);
}
}
}
}
@@ -0,0 +1,31 @@
using System.Runtime.InteropServices;
namespace WSL;
public static partial class WslApiLoader {
public static unsafe void WslLaunchInteractive(
string distributionName,
string? command,
bool useCurrentWorkingDirectory,
out uint exitCode
) {
[DllImport("wslapi.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = true)]
// ReSharper disable once LocalFunctionHidesMethod
static extern long WslLaunchInteractive(
[In] string distributionName,
[In] string? command,
[In] bool useCurrentWorkingDirectory,
[Out, MarshalAs(UnmanagedType.U4)] out uint exitCode
);
WslApiException.checkResult(
WslLaunchInteractive(
distributionName,
command,
useCurrentWorkingDirectory,
out exitCode
)
);
Console.WriteLine(exitCode);
}
}
@@ -0,0 +1,24 @@
using System.Runtime.InteropServices;
namespace WSL;
public static partial class WslApiLoader {
public static void WslRegisterDistribution(
string distributionName,
string tarGzFilename
) {
[DllImport("wslapi.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
// ReSharper disable once LocalFunctionHidesMethod
static extern long WslRegisterDistribution(
string distributionName,
string tarGzFilename
);
WslApiException.checkResult(
WslRegisterDistribution(
distributionName,
tarGzFilename
)
);
}
}
@@ -0,0 +1,19 @@
using System.Runtime.InteropServices;
namespace WSL;
public static partial class WslApiLoader {
public static void WslUnregisterDistribution(
string distributionName
) {
[DllImport("wslapi.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
// ReSharper disable once LocalFunctionHidesMethod
static extern long WslUnregisterDistribution(string distributionName);
WslApiException.checkResult(
WslUnregisterDistribution(
distributionName
)
);
}
}
+95
View File
@@ -0,0 +1,95 @@
{ pkgs ? import <nixpkgs> { }
, stdenv ? pkgs.stdenv
, lib ? pkgs.lib
, dotnet-sdk ? pkgs.dotnet-sdk
, dotnetPackages ? pkgs.dotnetPackages
, fetchurl ? pkgs.fetchurl
, linkFarmFromDrvs ? pkgs.linkFarmFromDrvs
}:
let
fetchNuGet = { pname, version, hash }: fetchurl {
name = "${pname}-${version}.nupkg";
url = "https://www.nuget.org/api/v2/package/${pname}/${version}";
inherit hash;
};
in
stdenv.mkDerivation rec {
name = "NixOS-WSL-Launcher";
src = ./.;
nativeBuildInputs = [
dotnet-sdk
dotnetPackages.Nuget
];
nugetDeps = linkFarmFromDrvs "${name}-nuget-deps" (map fetchNuGet [
{ pname = "Microsoft.AspNetCore.App.Runtime.win-x64"; version = "6.0.25"; hash = "sha256-njOrSWL+YJJvnywJ0clMzYdaANYl3rcVaZeZAki1erk="; }
{ pname = "Microsoft.AspNetCore.App.Runtime.win-arm64"; version = "6.0.25"; hash = "sha256-Jnt9WIxGvvejtBW5mjWCXlYmsUj6fxVI4Xs3WWsr8YE="; }
{ pname = "Microsoft.NETCore.App.Host.win-x64"; version = "6.0.25"; hash = "sha256-ATiO6e8xcDPrRngmT9k//7Z2Mx07hJhxgmdwUvMYJA0="; }
{ pname = "Microsoft.NETCore.App.Host.win-arm64"; version = "6.0.25"; hash = "sha256-xvj8CZHY4PyXKroniWj0JIoksKf4pcbberfMf5XZYaE="; }
{ pname = "Microsoft.NETCore.App.Runtime.win-x64"; version = "6.0.25"; hash = "sha256-Lk6cn0cSQVp4QVf6IznE7UnZ9tYxZmRMYrsTIHq9Vg8="; }
{ pname = "Microsoft.NETCore.App.Runtime.win-arm64"; version = "6.0.25"; hash = "sha256-eCoXKCHkrteypFVOUctV3ReQk/lFjJ7cI/CVk2tNrZY="; }
{ pname = "System.CommandLine"; version = "2.0.0-beta3.22114.1"; hash = "sha256-lcqMVesbt2E189e6KfG8HVmJc3hjo2ht48WnH1UaMkY="; }
]);
unpackPhase = ''
cp -r --no-preserve=mode $src/. .
'';
configurePhase = ''
runHook preConfigure
mkdir .home
export HOME=$PWD/.home
export DOTNET_NOLOGO=1
export DOTNET_CLI_TELEMETRY_OPTOUT=1
nuget sources Add -Name nix -Source "$PWD/nix"
nuget init "$nugetDeps" "$PWD/nix"
dotnet nuget disable source nuget.org
mkdir -p $HOME/.nuget/NuGet
cp $HOME/.config/NuGet/NuGet.Config $HOME/.nuget/NuGet
dotnet restore --ignore-failed-sources
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
mkdir -p $out
${lib.concatStringsSep "\n" (
map (runtime: ''
dotnet publish \
--self-contained \
-p:ContinuousIntegrationBuild=true \
-p:Deterministic=true \
--packages "$HOME/nuget_pkgs" \
-r ${runtime} \
-c Release \
--output $out/${runtime} \
Launcher
'') [ "win-x64" "win-arm64" ]
)}
runHook postBuild
'';
dontInstall = true;
dontStrip = true; # strip breaks the assemblies
meta = with lib; {
description = "WSL Distribution Launcher for NixOS-WSL";
homepage = "https://github.com/nix-community/NixOS-WSL";
license = licenses.asl20;
maintainers = with maintainers; [ nzbr ];
platforms = [ "x86_64-linux" "x86_64-windows" ];
};
}
+8
View File
@@ -0,0 +1,8 @@
{ runCommand
, dotnet-sdk
, ...
}:
runCommand "check-dotnet-format" { nativeBuildInputs = [ dotnet-sdk ]; } ''
cd "${./../Launcher}"
dotnet format --verbosity detailed --no-restore --verify-no-changes && touch $out
''
+1
View File
@@ -89,6 +89,7 @@
args = { inherit inputs; };
in
{
dotnet-format = pkgs.callPackage ./checks/dotnet-format.nix args;
nixpkgs-fmt = pkgs.callPackage ./checks/nixpkgs-fmt.nix args;
shfmt = pkgs.callPackage ./checks/shfmt.nix args;
rustfmt = pkgs.callPackage ./checks/rustfmt.nix args;
+1 -1
View File
@@ -63,7 +63,7 @@ with lib;
'') config.wsl.version
)}
--json)
echo '${generators.toJSON {} config.wsl.version}' | ${pkgs.jq}/bin/jq # Use jq to pretty-print the JSON
echo '${generators.toJSON {} config.wsl.version}' | ${pkgs.jq}/bin/jq -M # Use jq to pretty-print the JSON
exit 0
;;
*)