//! Shared fixture copies and builds. A mutex protects cwd-init and the brush checkout. use std::{ path::{Path, PathBuf}, process::{Command, ExitStatus}, sync::{Mutex, OnceLock}, }; pub static BUILD: Mutex<()> = Mutex::new(()); pub fn copy_tree(source: &Path, destination: &Path) -> anyhow::Result<()> { std::fs::create_dir_all(destination)?; for entry in std::fs::read_dir(source)? { let entry = entry?; let target = destination.join(entry.file_name()); if entry.file_type()?.is_dir() { copy_tree(&entry.path(), &target)?; } else { std::fs::copy(entry.path(), target)?; } } Ok(()) } pub fn target_dir() -> PathBuf { std::env::var_os("CARGO_TARGET_DIR") .map(PathBuf::from) .unwrap_or_else(|| { Path::new(env!("CARGO_TARGET_TMPDIR")) .parent() .unwrap() .to_owned() }) } pub fn cwd_init() { static INIT: OnceLock<()> = OnceLock::new(); INIT.get_or_init(|| { let _guard = BUILD.lock().unwrap(); let userland = Path::new(env!("CARGO_MANIFEST_DIR")).join("../userland"); if !userland.join("cwd-init/init.o").is_file() { assert!( Command::new("nu") .args(["--no-config-file", "cwd-init/build.nu"]) .current_dir(userland) .status() .unwrap() .success() ); } }); } pub fn build_brush() -> std::io::Result { let _guard = BUILD.lock().unwrap(); Command::new("nu") .args(["--no-config-file", "brush/build.nu"]) .env("CARGO_TARGET_DIR", target_dir()) .current_dir(Path::new(env!("CARGO_MANIFEST_DIR")).join("../userland")) .status() } pub fn build_git() -> &'static Path { static GIT: OnceLock = OnceLock::new(); GIT.get_or_init(|| { let userland = Path::new(env!("CARGO_MANIFEST_DIR")).join("../userland"); let target = target_dir(); cwd_init(); assert!( Command::new("cargo") .args(["build", "--release", "-p", "git", "--manifest-path"]) .arg(userland.join("Cargo.toml")) .args(["--target", "wasm32-wasip2", "--target-dir"]) .arg(&target) .args(["-j", "2", "--locked"]) .current_dir(&userland) .status() .unwrap() .success() ); target }) }