diff options
Diffstat (limited to 'utils')
| -rw-r--r-- | utils/.gitignore | 1 | ||||
| -rw-r--r-- | utils/Cargo.lock | 459 | ||||
| -rw-r--r-- | utils/Cargo.toml | 19 | ||||
| -rw-r--r-- | utils/default.nix | 8 | ||||
| -rw-r--r-- | utils/src/shim.rs | 129 | ||||
| -rw-r--r-- | utils/src/split_path.rs | 142 |
6 files changed, 758 insertions, 0 deletions
diff --git a/utils/.gitignore b/utils/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/utils/.gitignore @@ -0,0 +1 @@ +target diff --git a/utils/Cargo.lock b/utils/Cargo.lock new file mode 100644 index 0000000..3c8c369 --- /dev/null +++ b/utils/Cargo.lock @@ -0,0 +1,459 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +dependencies = [ + "backtrace", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" +dependencies = [ + "bitflags", + "clap_derive", + "clap_lex", + "is-terminal", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "gimli" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] +name = "kernlog" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dd79b6ea06a97c93bc5587fba4c2ed6d723b939d35d5e3fb3c6870d12e6d17" +dependencies = [ + "libc", + "log", +] + +[[package]] +name = "libc" +version = "0.2.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +dependencies = [ + "adler", +] + +[[package]] +name = "nix" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if", + "libc", + "memoffset", + "pin-utils", +] + +[[package]] +name = "nixos-wsl-utils" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "kernlog", + "log", + "nix", +] + +[[package]] +name = "object" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "rustix" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" diff --git a/utils/Cargo.toml b/utils/Cargo.toml new file mode 100644 index 0000000..9e43816 --- /dev/null +++ b/utils/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "nixos-wsl-utils" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = { version = "1.0.75", features = ["backtrace"] } +nix = { version = "0.25.0", features = ["process"] } +log = "0.4.20" +kernlog = "0.3.1" +clap = { version = "4.1.4", features = ["derive"] } + +[[bin]] +name = "systemd-shim" +path = "src/shim.rs" + +[[bin]] +name = "split-path" +path = "src/split_path.rs" diff --git a/utils/default.nix b/utils/default.nix new file mode 100644 index 0000000..838aa39 --- /dev/null +++ b/utils/default.nix @@ -0,0 +1,8 @@ +{ rustPlatform }: +rustPlatform.buildRustPackage { + pname = "nixos-wsl-utils"; + version = "1.0.0"; + + src = ./.; + cargoLock.lockFile = ./Cargo.lock; +} diff --git a/utils/src/shim.rs b/utils/src/shim.rs new file mode 100644 index 0000000..504335c --- /dev/null +++ b/utils/src/shim.rs @@ -0,0 +1,129 @@ +use anyhow::Context; +use nix::errno::Errno; +use nix::mount::{mount, MsFlags}; +use nix::sys::wait::{waitid, Id, WaitPidFlag}; +use nix::unistd::Pid; +use std::env; +use std::fs::{create_dir_all, metadata, remove_dir_all, remove_file, OpenOptions}; +use std::os::unix::io::{FromRawFd, IntoRawFd}; +use std::os::unix::process::CommandExt; +use std::path::Path; +use std::process::{Command, Stdio}; + +fn unscrew_dev_shm() -> anyhow::Result<()> { + log::trace!("Unscrewing /dev/shm..."); + + let dev_shm = Path::new("/dev/shm"); + + if dev_shm.is_symlink() { + remove_file(dev_shm).context("When removing /dev/shm symlink")?; + } else if dev_shm.is_dir() { + remove_dir_all(dev_shm).context("When removing old /dev/shm")?; + } + + create_dir_all("/dev/shm").context("When creating new /dev/shm")?; + mount( + Some("/run/shm"), + "/dev/shm", + None::<&str>, + MsFlags::MS_MOVE, + None::<&str>, + ) + .context("When relocating /dev/shm")?; + mount( + Some("/dev/shm"), + "/run/shm", + None::<&str>, + MsFlags::MS_BIND, + None::<&str>, + ) + .context("When bind mounting /run/shm to /dev/shm")?; + + Ok(()) +} + +fn real_main() -> anyhow::Result<()> { + if metadata("/dev/shm") + .context("When checking /dev/shm")? + .is_symlink() + { + unscrew_dev_shm()?; + } else { + log::trace!("/dev/shm is not a symlink, leaving as-is..."); + }; + + log::trace!("Remounting / shared..."); + + mount( + None::<&str>, + "/", + None::<&str>, + MsFlags::MS_REC | MsFlags::MS_SHARED, + None::<&str>, + ) + .context("When remounting /")?; + + log::trace!("Remounting /nix/store read-only..."); + + mount( + Some("/nix/store"), + "/nix/store", + None::<&str>, + MsFlags::MS_BIND, + None::<&str>, + ) + .context("When bind mounting /nix/store")?; + + mount( + Some("/nix/store"), + "/nix/store", + None::<&str>, + MsFlags::MS_BIND | MsFlags::MS_REMOUNT | MsFlags::MS_RDONLY, + None::<&str>, + ) + .context("When remounting /nix/store read-only")?; + + log::trace!("Running activation script..."); + + let kmsg_fd = OpenOptions::new() + .write(true) + .open("/dev/kmsg") + .context("When opening /dev/kmsg")? + .into_raw_fd(); + + let child = Command::new("/nix/var/nix/profiles/system/activate") + .env("LANG", "C.UTF-8") + // SAFETY: we just opened this + .stdout(unsafe { Stdio::from_raw_fd(kmsg_fd) }) + .stderr(unsafe { Stdio::from_raw_fd(kmsg_fd) }) + .spawn() + .context("When activating")?; + + let pid = Pid::from_raw(child.id() as i32); + + // If the child catches SIGCHLD, `waitid` will wait for it to exit, then return ECHILD. + // Why? Because POSIX is terrible. + let result = waitid(Id::Pid(pid), WaitPidFlag::WEXITED); + match result { + Ok(_) | Err(Errno::ECHILD) => {} + Err(e) => return Err(e).context("When waiting"), + }; + + log::trace!("Spawning real systemd..."); + + // if things go right, we will never return from here + Err( + Command::new("/nix/var/nix/profiles/system/systemd/lib/systemd/systemd") + .arg0(env::args_os().next().expect("arg0 missing")) + .args(env::args_os().skip(1)) + .exec() + .into(), + ) +} + +fn main() { + env::set_var("RUST_BACKTRACE", "1"); + kernlog::init().expect("Failed to set up logger..."); + let result = real_main(); + log::error!("Error: {:?}", result); +} diff --git a/utils/src/split_path.rs b/utils/src/split_path.rs new file mode 100644 index 0000000..16063ab --- /dev/null +++ b/utils/src/split_path.rs @@ -0,0 +1,142 @@ +use std::{ + env, + ffi::{OsStr, OsString}, + io::{self, Write}, + os::unix::prelude::{OsStrExt, OsStringExt}, + path::{Path, PathBuf}, +}; + +use clap::Parser; + +#[derive(Parser, Debug)] +struct Args { + #[arg(long)] + automount_root: PathBuf, + + #[arg(long)] + include_interop: bool, +} + +const SINGLE_QUOTE: u8 = b'\''; +const DOUBLE_QUOTE: u8 = b'"'; + +fn shell_escape(s: &OsStr) -> OsString { + // a shameless ripoff of the Python algorithm: + // https://github.com/python/cpython/blob/f1f3af7b8245e61a2e0abef03b2c6c5902ed7df8/Lib/shlex.py#L323 + let mut result = Vec::new(); + + result.push(SINGLE_QUOTE); + + for &byte in s.as_bytes() { + result.push(byte); + if byte == SINGLE_QUOTE { + result.push(DOUBLE_QUOTE); + result.push(SINGLE_QUOTE); + result.push(DOUBLE_QUOTE); + result.push(SINGLE_QUOTE); + } + } + + result.push(SINGLE_QUOTE); + + OsString::from_vec(result) +} + +fn build_export(var: &str, paths: &[PathBuf]) -> OsString { + let mut result = OsString::new(); + result.push("export "); + result.push(var); + result.push("="); + result.push(shell_escape( + &env::join_paths(paths).expect("paths must be valid"), + )); + result.push("\n"); + result +} + +fn do_split_paths(path: &OsStr, automount_root: &Path, include_interop: bool) -> OsString { + let mut native = vec![]; + let mut interop = vec![]; + + for part in env::split_paths(&path) { + if part.starts_with(automount_root) { + interop.push(part); + } else { + native.push(part); + } + } + + if include_interop { + native.extend(interop.clone()); + }; + + let mut result = OsString::new(); + result.push(build_export("PATH", &native)); + result.push(build_export("WSLPATH", &interop)); + result +} + +fn main() -> anyhow::Result<()> { + let args = Args::parse(); + + let path = env::var_os("PATH").expect("PATH is not set, aborting"); + + io::stdout() + .lock() + .write_all(do_split_paths(&path, &args.automount_root, args.include_interop).as_bytes())?; + + Ok(()) +} + +#[cfg(test)] +mod tests { + use std::{ffi::OsString, path::Path}; + + use crate::do_split_paths; + + #[test] + fn simple() { + assert_eq!( + do_split_paths( + &OsString::from("/good/foo:/bad/foo"), + Path::new("/bad"), + false + ), + OsString::from("export PATH='/good/foo'\nexport WSLPATH='/bad/foo'\n") + ); + } + + #[test] + fn exactly_one() { + assert_eq!( + do_split_paths(&OsString::from("/good/foo"), Path::new("/bad"), true), + OsString::from("export PATH='/good/foo'\nexport WSLPATH=''\n") + ); + } + + #[test] + fn include_interop() { + assert_eq!( + do_split_paths( + &OsString::from("/good/foo:/bad/foo"), + Path::new("/bad"), + true + ), + OsString::from("export PATH='/good/foo:/bad/foo'\nexport WSLPATH='/bad/foo'\n") + ); + } + + #[test] + fn spicy_escapes() { + assert_eq!( + do_split_paths( + &OsString::from("/good/foo'bar:/bad/foo"), + Path::new("/bad"), + true + ), + OsString::from( + "export PATH='/good/foo'\"'\"'bar:/bad/foo'\nexport WSLPATH='/bad/foo'\n" + ) + ); + } +} |
