|
| 1 | +use std::env; |
| 2 | +use std::path::Path; |
| 3 | + |
| 4 | +use color_eyre::eyre::{Result, eyre}; |
| 5 | +use toml_edit::{DocumentMut, Item, Table, value}; |
| 6 | + |
| 7 | +use crate::pkg::manifest::Manifest; |
| 8 | +use crate::pkg::stage; |
| 9 | + |
| 10 | +/// `jumpjet wit` — re-sync the project's staged WIT to the runtime WIT embedded in |
| 11 | +/// *this* CLI build, then re-stage dependency WIT and regenerate the world. |
| 12 | +/// |
| 13 | +/// The runtime WIT is only copied into a project at `jumpjet new` time, so after a |
| 14 | +/// `jumpjet upgrade` an existing project's staged runtime WIT |
| 15 | +/// (`.jumpjet/wit/deps/runtime` for games, `wit/deps/jumpjet-runtime` for libs) |
| 16 | +/// drifts from the host the CLI actually implements. This command refreshes it from |
| 17 | +/// the embedded definitions and pins `[runtime] version` to match, so guest bindgen |
| 18 | +/// generates against the runtime the installed CLI will run. |
| 19 | +pub async fn wit() -> Result<()> { |
| 20 | + let dir = env::current_dir()?; |
| 21 | + let manifest = Manifest::load_from(&dir)?; |
| 22 | + |
| 23 | + // 1. Refresh the embedded runtime WIT into the consumer's deps dir. Games key it |
| 24 | + // as `runtime`, libs as `jumpjet-runtime` — matching `jumpjet new`. |
| 25 | + let wit_root = stage::wit_root(&dir, &manifest); |
| 26 | + let runtime_dest = if manifest.is_lib() { |
| 27 | + wit_root.join("deps").join("jumpjet-runtime") |
| 28 | + } else { |
| 29 | + wit_root.join("deps").join("runtime") |
| 30 | + }; |
| 31 | + crate::commands::new::package::copy_runtime_wit(&runtime_dest)?; |
| 32 | + |
| 33 | + // 2. Re-resolve dependencies and re-stage their WIT, regenerating the game world. |
| 34 | + let resolution = crate::pkg::resolve::resolve(&dir, false).await?; |
| 35 | + stage::stage_wit(&dir, &manifest, &resolution)?; |
| 36 | + |
| 37 | + // 3. Pin `[runtime] version` to this CLI, since the staged WIT now matches it. |
| 38 | + let cli_version = env!("CARGO_PKG_VERSION"); |
| 39 | + set_runtime_version(&dir, cli_version)?; |
| 40 | + |
| 41 | + println!("Synced WIT to runtime v{cli_version}"); |
| 42 | + Ok(()) |
| 43 | +} |
| 44 | + |
| 45 | +/// Sets `[runtime] version` in `jumpjet.toml` to `version`, preserving the rest of |
| 46 | +/// the file's formatting and comments. |
| 47 | +fn set_runtime_version(dir: &Path, version: &str) -> Result<()> { |
| 48 | + let toml_path = dir.join(Manifest::FILE_NAME); |
| 49 | + let text = std::fs::read_to_string(&toml_path)?; |
| 50 | + let mut doc: DocumentMut = text |
| 51 | + .parse() |
| 52 | + .map_err(|e| eyre!("parsing jumpjet.toml: {e}"))?; |
| 53 | + |
| 54 | + if doc.get("runtime").is_none() { |
| 55 | + doc["runtime"] = Item::Table(Table::new()); |
| 56 | + } |
| 57 | + doc["runtime"]["version"] = value(version); |
| 58 | + |
| 59 | + std::fs::write(&toml_path, doc.to_string())?; |
| 60 | + Ok(()) |
| 61 | +} |
0 commit comments