Skip to content

Commit 8e7fdee

Browse files
author
Lochlan Wansbrough
committed
add wit command and improve template help
1 parent f3d4816 commit 8e7fdee

4 files changed

Lines changed: 95 additions & 4 deletions

File tree

src/app.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ impl App {
115115
// .await?
116116
// }
117117
// Some(CliCommand::Publish) => crate::commands::publish::publish().await?,
118+
Some(CliCommand::Wit) => crate::commands::wit::wit().await?,
118119
Some(CliCommand::Upgrade) => crate::commands::upgrade::upgrade().await?,
119120
Some(CliCommand::Docs) => crate::commands::docs::docs(&self.config, &self.mode).await?,
120121
None => {}

src/cli.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,35 @@
11
use std::path::PathBuf;
22

3+
use clap::builder::PossibleValuesParser;
34
use clap::{Parser, Subcommand};
45

56
use crate::utils::version;
67

8+
/// Distinct template names embedded under `src/templates/<category>/` (e.g.
9+
/// `game` -> `hello-rust`, `cube-python`, ...). Drives both `--help` listing and
10+
/// validation, so it always matches the templates actually shipped in the binary.
11+
fn template_names(category: &str) -> Vec<String> {
12+
let prefix = format!("{category}/");
13+
let mut names: Vec<String> = crate::assets::Templates::iter()
14+
.filter_map(|p| {
15+
p.strip_prefix(&prefix)
16+
.and_then(|rest| rest.split('/').next())
17+
.map(|name| name.to_string())
18+
})
19+
.collect();
20+
names.sort();
21+
names.dedup();
22+
names
23+
}
24+
25+
fn game_templates() -> PossibleValuesParser {
26+
PossibleValuesParser::new(template_names("game"))
27+
}
28+
29+
fn package_templates() -> PossibleValuesParser {
30+
PossibleValuesParser::new(template_names("package"))
31+
}
32+
733
#[derive(Parser)]
834
#[command(author, version = version(), about)]
935
pub struct Cli {
@@ -88,6 +114,8 @@ pub enum CliCommand {
88114
// #[clap(long, short = 'v', value_name = "VERSION")]
89115
// version: Option<String>,
90116
// },
117+
/// Re-sync the project's staged WIT to this CLI's embedded runtime definitions
118+
Wit,
91119
/// Upgrade the Jumpjet CLI to the latest version
92120
Upgrade,
93121
}
@@ -100,17 +128,17 @@ pub enum NewSubcommand {
100128
identifier: Option<String>,
101129
#[clap(long, short = 'n', value_name = "NAME")]
102130
name: Option<String>,
103-
/// One of: hello-js, hello-rust, cube-rust
104-
#[clap(long, short = 't', value_name = "TEMPLATE")]
131+
/// Game template to scaffold from
132+
#[clap(long, short = 't', value_name = "TEMPLATE", value_parser = game_templates())]
105133
template: String,
106134
},
107135
/// New package (library) that other games or packages can depend on
108136
Package {
109137
/// Package name in `namespace:name` form (e.g. `acme:physics`)
110138
#[clap(long, short = 'n', value_name = "NAME")]
111139
name: String,
112-
/// One of: lib-rust
113-
#[clap(long, short = 't', value_name = "TEMPLATE")]
140+
/// Package template to scaffold from
141+
#[clap(long, short = 't', value_name = "TEMPLATE", value_parser = package_templates())]
114142
template: String,
115143
},
116144
}

src/commands.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub mod new;
1010
pub mod publish;
1111
pub mod run;
1212
pub mod serve;
13+
pub mod wit;
1314
// Temporarily disabled commands — kept in the tree but not exposed via the CLI
1415
#[allow(dead_code)]
1516
pub mod update;

src/commands/wit.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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

Comments
 (0)