//! clawmates-bundler: assemble and verify air-gapped install bundles. //! //! Usage: //! clawmates-bundler keygen //! clawmates-bundler assemble \ //! [ ...] //! clawmates-bundler verify use std::path::{Path, PathBuf}; use std::process::ExitCode; fn main() -> ExitCode { match run() { Ok(message) => { println!("{message}"); ExitCode::SUCCESS } Err(message) => { eprintln!("clawmates-bundler: {message}"); ExitCode::FAILURE } } } fn run() -> Result { let args: Vec = std::env::args().skip(1).collect(); match args.first().map(String::as_str) { Some("keygen") if args.len() == 3 => { clawmates_bundler::generate_keypair(Path::new(&args[1]), Path::new(&args[2])) .map_err(|e| e.to_string())?; Ok(format!("wrote {} and {}", args[1], args[2])) } Some("assemble") if args.len() >= 5 => { let artifacts: Vec<(PathBuf, String)> = args[4..] .iter() .map(|pair| { pair.split_once('=') .map(|(src, dst)| (PathBuf::from(src), dst.to_owned())) .ok_or_else(|| format!("expected src=dest, got {pair}")) }) .collect::>()?; clawmates_bundler::assemble( Path::new(&args[1]), &args[2], &artifacts, Path::new(&args[3]), ) .map_err(|e| e.to_string())?; Ok(format!( "assembled {} artifacts into {}", artifacts.len(), args[1] )) } Some("pubkey") if args.len() == 3 => { clawmates_bundler::derive_public_key(Path::new(&args[1]), Path::new(&args[2])) .map_err(|e| e.to_string())?; Ok(format!("wrote {}", args[2])) } Some("verify") if args.len() == 3 => { let verified = clawmates_bundler::verify(Path::new(&args[1]), Path::new(&args[2])) .map_err(|e| e.to_string())?; Ok(format!("bundle OK: {verified} artifacts verified offline")) } _ => Err("usage: keygen | pubkey | assemble ... | verify ".into()), } }