//! Commit snapshots and last-good recovery with world git and a faux model. use sausage::{ exec::{Command, Exec, Options, Stream}, world::World, }; use std::{path::Path, sync::Arc}; const BUNDLE: &str = include_str!("../../js/extensions-test-bundle.js"); struct Author(Arc); #[async_trait::async_trait] impl Exec for Author { async fn exec( &self, command: Command, mut options: Options, output: &mut (dyn for<'a> FnMut(Stream, &'a [u8]) + Send), ) -> anyhow::Result { for (key, value) in [ ("GIT_AUTHOR_NAME", "Test"), ("GIT_AUTHOR_EMAIL", "test@example.com"), ("GIT_COMMITTER_NAME", "Test"), ("GIT_COMMITTER_EMAIL", "test@example.com"), ] { options.env.push((key.into(), value.into())); } self.0.exec(command, options, output).await } } #[tokio::test(flavor = "current_thread")] async fn commits_and_restart() -> anyhow::Result<()> { let userland = Path::new(env!("CARGO_MANIFEST_DIR")).join("../userland"); let target = Path::new(env!("CARGO_TARGET_TMPDIR")).parent().unwrap(); if !userland.join("cwd-init/init.o").is_file() { crate::common::cwd_init(); } assert!( std::process::Command::new("cargo") .args([ "build", "--release", "-p", "git", "-p", "sausage-exec-tools", "--manifest-path" ]) .arg(userland.join("Cargo.toml")) .args(["--target", "wasm32-wasip2", "--target-dir"]) .arg(target) .args(["-j", "2", "--locked"]) .current_dir(&userland) .status()? .success() ); let dir = tempfile::tempdir()?; let world = World::open(dir.path())?; let disk = dir.path().join("world"); std::fs::create_dir_all(disk.join("bin"))?; std::fs::copy( target.join("wasm32-wasip2/release/git.wasm"), disk.join("bin/git.wasm"), )?; for name in ["extensions-revert", "env"] { std::fs::copy( target.join(format!("wasm32-wasip2/release/{name}.wasm")), disk.join(format!("bin/{name}.wasm")), )?; } let repo = disk.join("src/sausage"); std::fs::create_dir_all(&repo)?; assert!( std::process::Command::new("git") .args(["init", "-b", "main"]) .arg(&repo) .status()? .success() ); assert!( std::process::Command::new("git") .args([ "-c", "user.name=Test", "-c", "user.email=test@example.com", "commit", "--no-gpg-sign", "--allow-empty", "-m", "empty" ]) .current_dir(&repo) .status()? .success() ); let exec: Arc = Arc::new(Author(sausage::process::exec(World { root: world.root.clone(), host_dir: world.host_dir.clone(), processes: world.processes.clone(), })?)); sausage::harness::run_module(world, exec, BUNDLE).await?; let good = std::fs::read_to_string(repo.join("good.txt"))?; let world = World::open(dir.path())?; let exec: Arc = Arc::new(Author(sausage::process::exec(World { root: world.root.clone(), host_dir: world.host_dir.clone(), processes: world.processes.clone(), })?)); sausage::harness::run_module( world, exec, &format!("globalThis.extensionRestart=true;globalThis.extensionGood={good:?};\n{BUNDLE}"), ) .await?; Ok(()) }