diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 90ce1d7e..6074ff19 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -5,6 +5,7 @@ mod clippy; mod fetch; mod generate; mod test; +mod upgrade_wasmtime; use anstyle::{AnsiColor, Color, Style}; use anyhow::Result; @@ -37,6 +38,8 @@ enum Commands { Test(Test), /// Run the WASM test suite TestWasm, + /// Upgrade the wasmtime dependency. + UpgradeWasmtime(UpgradeWasmtime), } #[derive(Args)] @@ -127,6 +130,13 @@ struct Test { nocapture: bool, } +#[derive(Args)] +struct UpgradeWasmtime { + /// The version to upgrade to. + #[arg(long, short)] + version: Version, +} + const BUILD_VERSION: &str = env!("CARGO_PKG_VERSION"); const BUILD_SHA: Option<&str> = option_env!("BUILD_SHA"); const EMSCRIPTEN_VERSION: &str = include_str!("../../cli/loader/emscripten-version"); @@ -189,6 +199,9 @@ fn run() -> Result<()> { } Commands::Test(test_options) => test::run(&test_options)?, Commands::TestWasm => test::run_wasm()?, + Commands::UpgradeWasmtime(upgrade_wasmtime_options) => { + upgrade_wasmtime::run(&upgrade_wasmtime_options)?; + } } Ok(()) diff --git a/xtask/src/upgrade_wasmtime.rs b/xtask/src/upgrade_wasmtime.rs new file mode 100644 index 00000000..f2584408 --- /dev/null +++ b/xtask/src/upgrade_wasmtime.rs @@ -0,0 +1,141 @@ +use std::{path::Path, process::Command}; + +use anyhow::{Context, Result}; +use git2::Repository; +use semver::Version; + +use crate::UpgradeWasmtime; + +const WASMTIME_RELEASE_URL: &str = "https://github.com/bytecodealliance/wasmtime/releases/download"; + +fn update_cargo(version: &Version) -> Result<()> { + let file = std::fs::read_to_string("lib/Cargo.toml")?; + let mut old_lines = file.lines(); + let mut new_lines = Vec::with_capacity(old_lines.size_hint().0); + + while let Some(line) = old_lines.next() { + new_lines.push(line.to_string()); + if line == "[dependencies.wasmtime-c-api]" { + let _ = old_lines.next(); + new_lines.push(format!("version = \"{version}\"")); + } + } + + std::fs::write("lib/Cargo.toml", new_lines.join("\n") + "\n")?; + + Ok(()) +} + +fn zig_fetch(lines: &mut Vec, version: &Version, url_suffix: &str) -> Result<()> { + let url = &format!("{WASMTIME_RELEASE_URL}/v{version}/wasmtime-v{version}-{url_suffix}"); + println!(" Fetching {url}"); + lines.push(format!(" .url = \"{url}\",")); + + let output = Command::new("zig") + .arg("fetch") + .arg(url) + .output() + .with_context(|| format!("Failed to execute zig fetch {url}"))?; + + let hash = String::from_utf8_lossy(&output.stdout); + lines.push(format!(" .hash = \"{}\",", hash.trim_end())); + + Ok(()) +} + +fn update_zig(version: &Version) -> Result<()> { + let file = std::fs::read_to_string("build.zig.zon")?; + let mut old_lines = file.lines(); + let new_lines = &mut Vec::with_capacity(old_lines.size_hint().0); + + while let Some(line) = old_lines.next() { + new_lines.push(line.to_string()); + match line { + " .wasmtime_c_api_aarch64_android = .{" => { + let (_, _) = (old_lines.next(), old_lines.next()); + zig_fetch(new_lines, version, "aarch64-android-c-api.tar.xz")?; + } + " .wasmtime_c_api_aarch64_linux = .{" => { + let (_, _) = (old_lines.next(), old_lines.next()); + zig_fetch(new_lines, version, "aarch64-linux-c-api.tar.xz")?; + } + " .wasmtime_c_api_aarch64_macos = .{" => { + let (_, _) = (old_lines.next(), old_lines.next()); + zig_fetch(new_lines, version, "aarch64-macos-c-api.tar.xz")?; + } + " .wasmtime_c_api_riscv64gc_linux = .{" => { + let (_, _) = (old_lines.next(), old_lines.next()); + zig_fetch(new_lines, version, "riscv64gc-linux-c-api.tar.xz")?; + } + " .wasmtime_c_api_s390x_linux = .{" => { + let (_, _) = (old_lines.next(), old_lines.next()); + zig_fetch(new_lines, version, "s390x-linux-c-api.tar.xz")?; + } + " .wasmtime_c_api_x86_64_android = .{" => { + let (_, _) = (old_lines.next(), old_lines.next()); + zig_fetch(new_lines, version, "x86_64-android-c-api.tar.xz")?; + } + " .wasmtime_c_api_x86_64_linux = .{" => { + let (_, _) = (old_lines.next(), old_lines.next()); + zig_fetch(new_lines, version, "x86_64-linux-c-api.tar.xz")?; + } + " .wasmtime_c_api_x86_64_macos = .{" => { + let (_, _) = (old_lines.next(), old_lines.next()); + zig_fetch(new_lines, version, "x86_64-macos-c-api.tar.xz")?; + } + " .wasmtime_c_api_x86_64_mingw = .{" => { + let (_, _) = (old_lines.next(), old_lines.next()); + zig_fetch(new_lines, version, "x86_64-mingw-c-api.zip")?; + } + " .wasmtime_c_api_x86_64_musl = .{" => { + let (_, _) = (old_lines.next(), old_lines.next()); + zig_fetch(new_lines, version, "x86_64-musl-c-api.tar.xz")?; + } + " .wasmtime_c_api_x86_64_windows = .{" => { + let (_, _) = (old_lines.next(), old_lines.next()); + zig_fetch(new_lines, version, "x86_64-windows-c-api.zip")?; + } + _ => {} + } + } + + std::fs::write("build.zig.zon", new_lines.join("\n") + "\n")?; + + Ok(()) +} + +fn create_commit(repo: &Repository, version: &Version) -> Result<()> { + let mut index = repo.index()?; + index.add_path(Path::new("lib/Cargo.toml"))?; + index.add_path(Path::new("build.zig.zon"))?; + index.write()?; + + let tree_id = index.write_tree()?; + let tree = repo.find_tree(tree_id)?; + let signature = repo.signature()?; + let parent_commit = repo.revparse_single("HEAD")?.peel_to_commit()?; + + let _ = repo.commit( + Some("HEAD"), + &signature, + &signature, + &format!("build(deps): bump wasmtime to v{version}"), + &tree, + &[&parent_commit], + )?; + + Ok(()) +} + +pub fn run(args: &UpgradeWasmtime) -> Result<()> { + println!("Upgrading wasmtime in lib/Cargo.toml"); + update_cargo(&args.version)?; + + println!("Upgrading wasmtime in build.zig.zon"); + update_zig(&args.version)?; + + let repo = Repository::open(".")?; + create_commit(&repo, &args.version)?; + + Ok(()) +}