mod build;
mod metadata;
mod new;
mod package;
mod run;
mod signing_key;
mod waos_app;
mod workspace;
use std::path::Path;
use std::process::ExitCode;
use anyhow::{Context as _, Result};
use clap::{Args, Parser, Subcommand};
use crate::build::{BuiltProgram, Profile};
use crate::metadata::WaosMetadata;
use crate::new::Template;
#[derive(Parser)]
#[command(name = "cargo", bin_name = "cargo")]
enum Cargo {
#[command(
name = "waos",
about = "cargo waos: writes a new program, and builds a program as a component, runs it in WaOS and packages it",
version
)]
Waos(WaosArgs),
}
#[derive(Args)]
struct WaosArgs {
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
New(NewArgs),
Build(BuildArgs),
Run(BuildArgs),
Package(Program),
}
#[derive(Args)]
struct NewArgs {
name: String,
#[arg(long, value_enum, default_value_t)]
template: Template,
}
#[derive(Args)]
struct Program {
#[arg(short, long, value_name = "PACKAGE")]
package: Option<String>,
}
#[derive(Args)]
struct BuildArgs {
#[command(flatten)]
program: Program,
#[arg(long)]
release: bool,
}
impl BuildArgs {
fn profile(&self) -> Profile {
if self.release {
Profile::Release
} else {
Profile::Debug
}
}
}
fn main() -> ExitCode {
let Cargo::Waos(args) = Cargo::parse();
let done = match args.command {
Command::New(new) => new_program(&new),
Command::Build(build) => build_only(&build),
Command::Run(build) => build_and_run(&build),
Command::Package(program) => package(&program),
};
done.unwrap_or_else(|error| {
eprintln!("cargo waos: {error:#}");
ExitCode::FAILURE
})
}
fn new_program(args: &NewArgs) -> Result<ExitCode> {
let folder = new::create(&args.name, args.template, Path::new("."))?;
println!("created {}", folder.display());
println!(" cd {} && cargo waos run", args.name);
Ok(ExitCode::SUCCESS)
}
fn build_only(args: &BuildArgs) -> Result<ExitCode> {
let built = build_chosen(args)?;
println!("{}", built.component.display());
Ok(ExitCode::SUCCESS)
}
fn build_and_run(args: &BuildArgs) -> Result<ExitCode> {
let metadata = workspace::metadata()?;
let package = workspace::chosen_package(&metadata, args.program.package.as_deref())?;
let id = WaosMetadata::id_of(package)?;
let built = build::build(&metadata, package, args.profile())?;
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.context("a runtime for the connection")?;
runtime.block_on(run::run(id, &built))
}
fn package(program: &Program) -> Result<ExitCode> {
let packaged = package::package(program.package.as_deref())?;
eprintln!("cargo waos: listed in {}", packaged.index.display());
println!("{}", packaged.package.display());
Ok(ExitCode::SUCCESS)
}
fn build_chosen(args: &BuildArgs) -> Result<BuiltProgram> {
let metadata = workspace::metadata()?;
let package = workspace::chosen_package(&metadata, args.program.package.as_deref())?;
build::build(&metadata, package, args.profile())
}