diff options
| author | Hermes Agent <hermes@localhost> | 2026-08-12 00:03:21 +0000 |
|---|---|---|
| committer | Hermes Agent <hermes@localhost> | 2026-08-12 00:03:21 +0000 |
| commit | 191e2b7429ff4547b5fdd0fbfcff943ce96c2d68 (patch) | |
| tree | a7f989330ac0d2f2de13f67d4c897943391c5a55 | |
| parent | 25f39c857da591c665865b77483b79495caf5e00 (diff) | |
Add explicit image builder CLI commands
| -rw-r--r-- | src/cli.rs | 58 | ||||
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/main.rs | 9 | ||||
| -rw-r--r-- | tests/cli.rs | 71 |
4 files changed, 137 insertions, 2 deletions
diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..de9404a --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,58 @@ +use std::path::PathBuf; + +use anyhow::{bail, Result}; +use clap::{Parser, Subcommand}; + +use crate::{BuildPlan, ImageSpec}; + +#[derive(Debug, Parser)] +#[command(name = "alt-controller-image", about = "Native ALT image builder")] +pub struct Cli { + #[command(subcommand)] + pub command: Command, +} + +#[derive(Debug, Subcommand)] +pub enum Command { + /// Validate an image specification and render its build intent. + Plan { + #[arg(long)] + spec: PathBuf, + }, + /// Build an image from a specification. + Build { + #[arg(long)] + spec: PathBuf, + #[arg(long)] + workspace: PathBuf, + #[arg(long)] + output: PathBuf, + }, + /// Inspect a built artifact. + Inspect { + #[arg(long)] + artifact: PathBuf, + }, + /// Compare two built artifacts semantically. + Compare { + #[arg(long)] + left: PathBuf, + #[arg(long)] + right: PathBuf, + }, +} + +pub fn run(cli: Cli) -> Result<()> { + match cli.command { + Command::Plan { spec } => { + let plan = BuildPlan::compile(ImageSpec::load(&spec)?)?; + println!("target: {}", plan.spec().target.name); + println!("architecture: {}", plan.spec().target.architecture.as_str()); + println!("format: tar"); + Ok(()) + } + Command::Build { .. } => bail!("build execution is not available yet"), + Command::Inspect { .. } => bail!("artifact inspection is not available yet"), + Command::Compare { .. } => bail!("artifact comparison is not available yet"), + } +} @@ -1,3 +1,4 @@ +pub mod cli; pub mod model; pub mod plan; diff --git a/src/main.rs b/src/main.rs index 1ca0cab..1e06263 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,9 @@ +use alt_controller_image::cli::{run, Cli}; +use clap::Parser; + fn main() { - eprintln!("The command-line interface is not available yet. Use the library to load an ImageSpec."); - std::process::exit(2); + if let Err(error) = run(Cli::parse()) { + eprintln!("error: {error:#}"); + std::process::exit(1); + } } diff --git a/tests/cli.rs b/tests/cli.rs new file mode 100644 index 0000000..b800e68 --- /dev/null +++ b/tests/cli.rs @@ -0,0 +1,71 @@ +use std::path::PathBuf; + +use alt_controller_image::cli::{Cli, Command}; +use clap::Parser; + +#[test] +fn parses_plan_with_an_explicit_spec_path() { + let cli = Cli::try_parse_from(["alt-controller-image", "plan", "--spec", "image.toml"]) + .expect("plan command parses"); + + assert!(matches!( + cli.command, + Command::Plan { spec } if spec == PathBuf::from("image.toml") + )); +} + +#[test] +fn parses_build_with_explicit_workspace_and_output_paths() { + let cli = Cli::try_parse_from([ + "alt-controller-image", + "build", + "--spec", + "image.toml", + "--workspace", + "work", + "--output", + "out/image.tar", + ]) + .expect("build command parses"); + + assert!(matches!( + cli.command, + Command::Build { + spec, + workspace, + output + } if spec == PathBuf::from("image.toml") + && workspace == PathBuf::from("work") + && output == PathBuf::from("out/image.tar") + )); +} + +#[test] +fn parses_inspect_with_an_explicit_artifact_path() { + let cli = Cli::try_parse_from(["alt-controller-image", "inspect", "--artifact", "out/image.tar"]) + .expect("inspect command parses"); + + assert!(matches!( + cli.command, + Command::Inspect { artifact } if artifact == PathBuf::from("out/image.tar") + )); +} + +#[test] +fn parses_compare_with_explicit_artifact_paths() { + let cli = Cli::try_parse_from([ + "alt-controller-image", + "compare", + "--left", + "legacy.tar", + "--right", + "native.tar", + ]) + .expect("compare command parses"); + + assert!(matches!( + cli.command, + Command::Compare { left, right } + if left == PathBuf::from("legacy.tar") && right == PathBuf::from("native.tar") + )); +} |