summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorK900 <me@0upti.me>2023-09-29 20:51:59 +0300
committerK900 <me@0upti.me>2023-09-29 21:53:26 +0300
commite6b1129f9d3c2010fba981307c72ad7d15717d3d (patch)
tree3b9665fb65d89186696bf042341989f4a2a72b70
parent65ba7e6fb468fe67bff3751d205926bb05e0baff (diff)
feat: rewrite tarball generation to use proper nixos-install + nixos-enter
Supersedes #243.
-rw-r--r--.github/workflows/main.yml22
-rw-r--r--.github/workflows/release.yml12
-rw-r--r--.gitignore2
-rw-r--r--README.md61
-rw-r--r--checks/username.nix4
-rw-r--r--configuration.nix32
-rw-r--r--flake.nix40
-rw-r--r--modules/build-tarball.nix177
-rw-r--r--modules/wsl-distro.nix5
-rw-r--r--tests/README.md8
-rw-r--r--tests/basic-functionality.Tests.ps12
-rw-r--r--tests/docker/docker.Tests.ps11
-rw-r--r--tests/lib/Dockerfile2
-rw-r--r--tests/lib/lib.ps113
14 files changed, 171 insertions, 210 deletions
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 7baaef1..4ae011d 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -50,6 +50,12 @@ jobs:
needs:
- prepare
runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ config:
+ - modern
+ - legacy
+ - test
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -66,15 +72,17 @@ jobs:
echo ${{ needs.prepare.outputs.version }} > ./VERSION
echo $(git rev-parse HEAD) >> ./VERSION
- - name: Build installer ๐Ÿ› ๏ธ
+ - name: Build tarballs ๐Ÿ› ๏ธ
+ # We can't just nix run here because nix is not on root's PATH in the container
run: |
- nix build '.#nixosConfigurations.mysystem.config.system.build.installer'
+ nix build .#nixosConfigurations.${{ matrix.config }}.config.system.build.tarballBuilder
+ sudo ./result/bin/nixos-wsl-tarball-builder nixos-wsl.tar.gz
- - name: Upload installer ๐Ÿ“ค
+ - name: Upload tarball ๐Ÿ“ค
uses: actions/upload-artifact@v3
with:
- name: installer
- path: result/tarball/nixos-wsl-installer.tar.gz
+ name: tarball-${{ matrix.config }}
+ path: nixos-wsl.tar.gz
checks:
name: Flake Check ๐Ÿ“‹
@@ -117,10 +125,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- - name: Download installer ๐Ÿ“ฅ
+ - name: Download tarball ๐Ÿ“ฅ
uses: actions/download-artifact@v3
with:
- name: installer
+ name: tarball-test
- name: Execute test ๐Ÿงช
shell: pwsh
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 72ba873..ab862ea 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -14,13 +14,13 @@ jobs:
name: Create Release ๐Ÿ“ข
runs-on: ubuntu-latest
steps:
- - name: Download installer ๐Ÿ“ฅ
+ - name: Download tarball ๐Ÿ“ฅ
uses: actions/download-artifact@v3
- with:
- name: installer
- 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
sha256sum $x > ${x}.sha256
done
@@ -29,7 +29,9 @@ jobs:
uses: softprops/action-gh-release@v1
with:
files: |
- nixos-wsl-installer.tar.gz
- nixos-wsl-installer.tar.gz.sha256
+ nixos-wsl.tar.gz
+ nixos-wsl.tar.gz.sha256
+ nixos-wsl-legacy.tar.gz
+ nixos-wsl-legacy.tar.gz.sha256
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index c798a58..d6835c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
result
result-*
-nixos-wsl-installer.tar.gz
+nixos-wsl*.tar.gz
diff --git a/README.md b/README.md
index e2dad8f..695b858 100644
--- a/README.md
+++ b/README.md
@@ -9,18 +9,23 @@ A minimal root filesystem for running NixOS on WSL. It can be used with
[DistroLauncher](https://github.com/microsoft/WSL-DistroLauncher) as
`install.tar.gz` or as input to `wsl --import --version 2`.
+## System requirements
+
+NixOS-WSL is tested with the Windows Store version of WSL 2, which is now available on all supported Windows releases (both 10 and 11).
+Support for older "inbox" versions is best-effort.
+
## Quick start
-First, [download the latest release\'s installer](https://github.com/nix-community/NixOS-WSL/releases/latest).
+First, [download the latest release](https://github.com/nix-community/NixOS-WSL/releases/latest).
Then open up a Terminal, PowerShell or Command Prompt and run:
```sh
-wsl --import NixOS .\NixOS\ nixos-wsl-installer.tar.gz --version 2
+wsl --import NixOS .\NixOS\ nixos-wsl.tar.gz --version 2
```
This sets up a new WSL distribution `NixOS` that is installed under
-`.\NixOS`. `nixos-wsl-installer.tar.gz` is the path to the file you
+`.\NixOS`. `nixos-wsl.tar.gz` is the path to the file you
downloaded earlier. You might need to change this path or change to the download directory first.
You can now run NixOS:
@@ -29,11 +34,6 @@ You can now run NixOS:
wsl -d NixOS
```
-The installer will unpack the file system and subsequently start NixOS.
-A few warnings about file systems and locales will pop up. You can
-safely ignore them. After systemd has started, you should be greeted
-with a bash prompt inside your fresh NixOS installation.
-
If you want to make NixOS your default distribution, you can do so with
```sh
@@ -68,57 +68,34 @@ If you have a flakes-enabled Nix, you can use the following command to
build your own tarball instead of relying on a prebuilt one:
```cmd
-nix build github:nix-community/NixOS-WSL#nixosConfigurations.mysystem.config.system.build.installer
+sudo nix run github:nix-community/NixOS-WSL#nixosConfigurations.modern.config.system.build.tarballBuilder
```
Or, if you want to build with local changes, run inside your checkout:
```cmd
-nix build .#nixosConfigurations.mysystem.config.system.build.installer
+sudo nix run .#nixosConfigurations.your-hostname.config.system.build.tarballBuilder
```
Without a flakes-enabled Nix, you can build a tarball using:
```cmd
-nix-build -A nixosConfigurations.mysystem.config.system.build.installer
-```
+nix-build -A nixosConfigurations.mysystem.config.system.build.tarballBuilder && sudo ./result/bin/nixos-wsl-tarball-builder
-The resulting installer tarball can then be found under
-`./result/tarball/nixos-wsl-installer.tar.gz`.
+```
-You can also build a rootfs tarball without wrapping it in the installer
-by replacing `installer` with `tarball` in the above commands. The
-rootfs tarball can then be found under
-`./result/tarball/nixos-wsl-x86_64-linux.tar.gz`.
+The resulting tarball can then be found under `nixos-wsl.tar.gz`.
## Design
Getting NixOS to run under WSL requires some workarounds:
-### systemd support
-
-WSL comes with its own (non-substitutable) init system while NixOS uses
-systemd. Simply starting systemd later on does not work out of the box,
-because systemd as system instance refuses to start if it is not PID 1.
-This unfortunate combination is resolved in two ways:
-
-- the user\'s default shell is replaced by a wrapper script that acts
- is init system and then drops to the actual shell
-- systemd is started in its own PID namespace; therefore, it is PID 1.
- The shell wrapper (see above) enters the systemd namespace before
- dropping to the shell.
-
-### Installer
-
-Usually WSL distributions ship as a tarball of their root file system.
-These tarballs however, can not contain any hard-links due to the way
-they are unpacked by WSL, resulting in an \"Unspecified Error\". By
-default some Nix-derivations will contain hard-links when they are
-built. This results in system tarballs that can not be imported into
-WSL. To circumvent this problem, the rootfs tarball is wrapped in that
-of a minimal distribution (the installer), that is packaged without any
-hard-links. When the installer system is started for the first time, it
-overwrites itself with the contents of the rootfs tarball.
+- instead of directly loading systemd, we use a small shim that runs the NixOS activation scripts first
+- some additional binaries required by WSL's internal tooling are symlinked to FHS paths on activation
+
+Running on older WSL versions also requires a workaround to spawn systemd by hijacking the root shell and
+spawning a container with systemd inside. This method of running things is deprecated and not recommended,
+however still available as `nixos-wsl-legacy.tar.gz` or via `wsl.nativeSystemd = false`.
## License
diff --git a/checks/username.nix b/checks/username.nix
index 53337c7..2da4418 100644
--- a/checks/username.nix
+++ b/checks/username.nix
@@ -6,9 +6,9 @@
let
baseModule = { ... }: {
- imports = [ ../configuration.nix ];
-
+ imports = [ ../modules ];
wsl.enable = true;
+ wsl.defaultUser = "nixos";
};
changedUsername = { lib, ... }: {
wsl.defaultUser = lib.mkForce "different";
diff --git a/configuration.nix b/configuration.nix
deleted file mode 100644
index 789cf59..0000000
--- a/configuration.nix
+++ /dev/null
@@ -1,32 +0,0 @@
-{ pkgs, ... }:
-
-let
- nixos-wsl = import ./default.nix;
-in
-{
- imports = [
- nixos-wsl.nixosModules.wsl
- ];
-
- wsl = {
- enable = true;
- wslConf.automount.root = "/mnt";
- defaultUser = "nixos";
- startMenuLaunchers = true;
-
- # Enable native Docker support
- # docker-native.enable = true;
-
- # Enable integration with Docker Desktop (needs to be installed)
- # docker-desktop.enable = true;
-
- };
-
- # Enable nix flakes
- nix.package = pkgs.nixFlakes;
- nix.extraOptions = ''
- experimental-features = nix-command flakes
- '';
-
- system.stateVersion = "23.05";
-}
diff --git a/flake.nix b/flake.nix
index 66397e8..f3243f4 100644
--- a/flake.nix
+++ b/flake.nix
@@ -26,11 +26,41 @@
};
nixosModules.default = self.nixosModules.wsl;
- nixosConfigurations.mysystem = nixpkgs.lib.nixosSystem {
- system = "x86_64-linux";
- modules = [
- ./configuration.nix
- ];
+ nixosConfigurations = {
+ modern = nixpkgs.lib.nixosSystem {
+ system = "x86_64-linux";
+ modules = [
+ self.nixosModules.default
+ { wsl.enable = true; }
+ ];
+ };
+
+ legacy = nixpkgs.lib.nixosSystem {
+ system = "x86_64-linux";
+ modules = [
+ self.nixosModules.default
+ {
+ wsl.enable = true;
+ wsl.nativeSystemd = false;
+ }
+ ];
+ };
+
+ test = nixpkgs.lib.nixosSystem {
+ system = "x86_64-linux";
+ modules = [
+ self.nixosModules.default
+ ({ config, ... }: {
+ wsl.enable = true;
+ wsl.nativeSystemd = false;
+
+ system.activationScripts.create-test-entrypoint.text = ''
+ mkdir -p /bin
+ ln -sfn ${config.users.users.root.shell} /bin/syschdemd
+ '';
+ })
+ ];
+ };
};
} //
diff --git a/modules/build-tarball.nix b/modules/build-tarball.nix
index d2e5231..f48c9ce 100644
--- a/modules/build-tarball.nix
+++ b/modules/build-tarball.nix
@@ -1,112 +1,95 @@
{ config, pkgs, lib, ... }:
with builtins; with lib;
let
- cfg = config.wsl.tarball;
-
- pkgs2storeContents = l: map (x: { object = x; symlink = "none"; }) l;
-
- nixpkgs = lib.cleanSource pkgs.path;
-
- channelSources = pkgs.runCommand "nixos-${config.system.nixos.version}"
- { preferLocalBuild = true; }
- ''
- mkdir -p $out
- cp -prd ${nixpkgs.outPath} $out/nixos
- chmod -R u+w $out/nixos
- if [ ! -e $out/nixos/nixpkgs ]; then
- ln -s . $out/nixos/nixpkgs
- fi
- echo -n ${toString config.system.nixos.revision} > $out/nixos/.git-revision
- echo -n ${toString config.system.nixos.versionSuffix} > $out/nixos/.version-suffix
- echo ${toString config.system.nixos.versionSuffix} | sed -e s/pre// > $out/nixos/svn-revision
- '';
-
- preparer = pkgs.writeShellScriptBin "wsl-prepare" (''
- set -e
-
- mkdir -m 0755 ./bin ./etc
- mkdir -m 1777 ./tmp
-
- # WSL requires a /bin/sh - only temporary, NixOS's activate will overwrite
- ln -s ${config.users.users.root.shell} ./bin/sh
-
- # WSL also requires a /bin/mount, otherwise the host fs isn't accessible
- ln -s /nix/var/nix/profiles/system/sw/bin/mount ./bin/mount
-
- # Set system profile
- system=${config.system.build.toplevel}
- ./$system/sw/bin/nix-store --store `pwd` --load-db < ./nix-path-registration
- rm ./nix-path-registration
- ./$system/sw/bin/nix-env --store `pwd` -p ./nix/var/nix/profiles/system --set $system
-
- # Set channel
- mkdir -p ./nix/var/nix/profiles/per-user/root
- ./$system/sw/bin/nix-env --store `pwd` -p ./nix/var/nix/profiles/per-user/root/channels --set ${channelSources}
- mkdir -m 0700 -p ./root/.nix-defexpr
- ln -s /nix/var/nix/profiles/per-user/root/channels ./root/.nix-defexpr/channels
-
- # It's now a NixOS!
- touch ./etc/NIXOS
-
- # Write wsl.conf so that it is present when NixOS is started for the first time
- cp ${config.environment.etc."wsl.conf".source} ./etc/wsl.conf
-
- '' + lib.optionalString cfg.includeConfig ''
- ${if cfg.configPath == null then ''
- # Copy the system configuration
- mkdir -p ./etc/nixos/nixos-wsl
- cp -R ${lib.cleanSource ../.}/. ./etc/nixos/nixos-wsl
- mv ./etc/nixos/nixos-wsl/configuration.nix ./etc/nixos/configuration.nix
- # Patch the import path to avoid having a flake.nix in /etc/nixos
- sed -i 's|import \./default\.nix|import \./nixos-wsl|' ./etc/nixos/configuration.nix
- '' else ''
- mkdir -p ./etc/nixos
- cp -R ${lib.cleanSource cfg.configPath}/. ./etc/nixos
- ''}
- chmod -R u+w etc/nixos
- '');
+ cfg = config.wsl;
-in
-{
-
- options.wsl.tarball = {
- includeConfig = mkOption {
- type = types.bool;
- default = true;
- description = "Whether or not to copy the system configuration into the tarball";
- };
-
- configPath = mkOption {
- type = types.nullOr types.path;
- default = null;
- description = "Path to system configuration which is copied into the tarball";
- };
- };
+ defaultConfig = pkgs.writeText "default-configuration.nix" ''
+ # Edit this configuration file to define what should be installed on
+ # your system. Help is available in the configuration.nix(5) man page, on
+ # https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
+ # NixOS-WSL specific options are documented on the NixOS-WSL repository:
+ # https://github.com/nix-community/NixOS-WSL
- config = mkIf config.wsl.enable {
- # These options make no sense without the wsl-distro module anyway
+ { config, lib, pkgs, ... }:
- system.build.tarball = pkgs.callPackage "${nixpkgs}/nixos/lib/make-system-tarball.nix" {
-
- contents = [
- { source = config.users.users.root.shell; target = "/nix/nixos-wsl/entrypoint"; }
+ {
+ imports = [
+ # include NixOS-WSL modules
+ <nixos-wsl/modules>
];
- fileName = "nixos-wsl-${pkgs.hostPlatform.system}";
+ wsl.enable = true;
+ wsl.defaultUser = "nixos";
+ ${cfg.extraTarballConfig}
+
+ # This value determines the NixOS release from which the default
+ # settings for stateful data, like file locations and database versions
+ # on your system were taken. It's perfectly fine and recommended to leave
+ # this value at the release version of the first install of this system.
+ # Before changing this value read the documentation for this option
+ # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
+ system.stateVersion = "${config.system.nixos.release}"; # Did you read the comment?
+ }
+ '';
+in
+{
+ options.wsl.extraTarballConfig = mkOption {
+ type = types.str;
+ internal = true;
+ default = "";
+ };
- storeContents = pkgs2storeContents [
- config.system.build.toplevel
- channelSources
- preparer
- ];
+ # These options make no sense without the wsl-distro module anyway
+ config = mkIf cfg.enable {
+ system.build.tarballBuilder = pkgs.writeShellApplication {
+ name = "nixos-wsl-tarball-builder";
- extraCommands = "${preparer}/bin/wsl-prepare";
+ runtimeInputs = [
+ pkgs.coreutils
+ pkgs.gnutar
+ pkgs.nixos-install-tools
+ config.nix.package
+ ];
- # Use gzip
- compressCommand = "gzip";
- compressionExtension = ".gz";
+ text = ''
+ if ! [ $EUID -eq 0 ]; then
+ echo "This script must be run as root!"
+ exit 1
+ fi
+
+ out=''${1:-nixos-wsl.tar.gz}
+
+ root=$(mktemp -p "''${TMPDIR:-/tmp}" -d nixos-wsl-tarball.XXXXXXXXXX)
+ # FIXME: fails in CI for some reason, but we don't really care because it's CI
+ trap 'rm -rf "$root" || true' INT TERM EXIT
+
+ chmod o+rx "$root"
+
+ echo "[NixOS-WSL] Installing..."
+ nixos-install \
+ --root "$root" \
+ --no-root-passwd \
+ --system ${config.system.build.toplevel} \
+ --substituters ""
+
+ echo "[NixOS-WSL] Adding channel..."
+ nixos-enter --root "$root" --command 'nix-channel --add https://github.com/nix-community/NixOS-WSL/archive/refs/heads/main.tar.gz nixos-wsl'
+
+ echo "[NixOS-WSL] Adding default config..."
+ install -Dm644 ${defaultConfig} "$root/etc/nixos/configuration.nix"
+
+ echo "[NixOS-WSL] Compressing..."
+ tar -C "$root" \
+ -cz \
+ --sort=name \
+ --mtime='@1' \
+ --owner=0 \
+ --group=0 \
+ --numeric-owner \
+ . \
+ > "$out"
+ '';
};
-
};
}
diff --git a/modules/wsl-distro.nix b/modules/wsl-distro.nix
index 0a2b88b..f2279e3 100644
--- a/modules/wsl-distro.nix
+++ b/modules/wsl-distro.nix
@@ -132,11 +132,6 @@ in
config.wsl.extraBin
)}
'');
- # TODO: This is only needed for the docker tests, it can be removed when they are moved to something else
- update-entrypoint.text = ''
- mkdir -p /nix/nixos-wsl
- ln -sfn ${config.users.users.root.shell} /nix/nixos-wsl/entrypoint
- '';
};
# require people to use lib.mkForce to make it harder to brick their installation
diff --git a/tests/README.md b/tests/README.md
index d285809..d3c66d2 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -1,7 +1,7 @@
# Tests
-This directory contains tests that are executed against a built installer tarball.
-The test are written using the [Pester](https://pester.dev/) testing framework
+This directory contains tests that are executed against a built NixOS-WSL "legacy" tarball.
+The tests are written using the [Pester](https://pester.dev/) testing framework.
## Execute Tests
@@ -19,7 +19,9 @@ Running the tests requires Docker and PowerShell to be installed on your system.
### Running the Tests
If you haven't already, [install Pester](https://pester.dev/docs/introduction/installation/).
-The tests require a `nixos-wsl-installer.tar.gz` to be present in the current working directory or in `./result/tarball`. Refer to the top-level readme on how to build it.
+The tests require a "legacy" `nixos-wsl.tar.gz` to be present in the current working directory, which can be built with
+`sudo nix run .#nixosConfigurations.legacy.config.system.build.tarballBuilder -- nixos-wsl.tar.gz`.
+
Once everything is in place, run the test by running the following in PowerShell at the root of this repo:
```powershell
diff --git a/tests/basic-functionality.Tests.ps1 b/tests/basic-functionality.Tests.ps1
index d62823b..c148c79 100644
--- a/tests/basic-functionality.Tests.ps1
+++ b/tests/basic-functionality.Tests.ps1
@@ -7,7 +7,7 @@ Describe "Basic Functionality" {
$distro = Install-Distro
}
- It "is possible to run a command through the installer" {
+ It "is possible to run a command in the container" {
$distro.Launch("nixos-version")
$LASTEXITCODE | Should -Be 0
}
diff --git a/tests/docker/docker.Tests.ps1 b/tests/docker/docker.Tests.ps1
index fefff07..9ea46aa 100644
--- a/tests/docker/docker.Tests.ps1
+++ b/tests/docker/docker.Tests.ps1
@@ -27,7 +27,6 @@ Describe "Docker (native)" {
It "should be possible to connect to the internet from a container" {
$distro.Launch("docker run --rm -it alpine wget -qO- http://www.msftconnecttest.com/connecttest.txt") | Select-Object -Last 1 | Should -BeExactly "Microsoft Connect Test"
- # docker exec -it $distro.id /nix/nixos-wsl/entrypoint -c "docker run --rm -it alpine wget -qO- http://www.msftconnecttest.com/connecttest.txt" | Select-Object -Last 1 | Should -BeExactly "Microsoft Connect Test"
$LASTEXITCODE | Should -Be 0
}
diff --git a/tests/lib/Dockerfile b/tests/lib/Dockerfile
index 1fcea66..e703915 100644
--- a/tests/lib/Dockerfile
+++ b/tests/lib/Dockerfile
@@ -1,2 +1,2 @@
FROM scratch
-ADD nixos-wsl-installer.tar.gz /
+ADD nixos-wsl.tar.gz /
diff --git a/tests/lib/lib.ps1 b/tests/lib/lib.ps1
index 58b1a42..c9e9267 100644
--- a/tests/lib/lib.ps1
+++ b/tests/lib/lib.ps1
@@ -26,12 +26,9 @@ class Distro {
[string]FindTarball() {
# Check if a fresh tarball exists in result, otherwise try one in the current directory
- $tarball = "./result/tarball/nixos-wsl-installer.tar.gz"
+ $tarball = "./nixos-wsl.tar.gz"
if (!(Test-Path $tarball)) {
- $tarball = "./nixos-wsl-installer.tar.gz"
- if (!(Test-Path $tarball)) {
- throw "Could not find the installer tarball! Run nix build first, or place one in the current directory."
- }
+ throw "Could not find the tarball! Run nix build first, or place one in the current directory."
}
Write-Host "Using tarball: $tarball"
return $tarball
@@ -75,7 +72,7 @@ class DockerDistro : Distro {
$tarball = $this.FindTarball()
if (!([DockerDistro]::imageCreated)) {
- # Build docker image from the installer tarball
+ # Build docker image from the tarball
$tmpdir = $(mktemp -d)
Copy-Item $PSScriptRoot/Dockerfile $tmpdir
Copy-Item $tarball $tmpdir
@@ -96,7 +93,7 @@ class DockerDistro : Distro {
[Array]Launch([string]$command) {
Write-Host "> $command"
$result = @()
- docker exec -t $this.id /nix/nixos-wsl/entrypoint -c $command | Tee-Object -Variable result | Write-Host
+ docker exec -t $this.id /bin/syschdemd -c $command | Tee-Object -Variable result | Write-Host
return $result | Remove-Escapes
}
@@ -140,7 +137,7 @@ class WslDistro : Distro {
[Array]Launch([string]$command) {
Write-Host "> $command"
$result = @()
- & wsl.exe -d $this.id -e /nix/nixos-wsl/entrypoint -c $command | Tee-Object -Variable result | Write-Host
+ & wsl.exe -d $this.id -e /bin/syschdemd -c $command | Tee-Object -Variable result | Write-Host
return $result | Remove-Escapes
}