pub(crate) mod commands;
pub(crate) mod config;
pub(crate) mod state;
pub(crate) mod store;
pub(crate) mod utils;
use anyhow::Result;
use clap::Parser;
use commands::update::version_notice;
use commands::{handle_command, Commands};
use config::{ARCH, PLATFORM, VERSION};
use state::{State, StateOptions};
#[derive(Debug, Parser)]
#[clap(
name = "hop",
about = "🐇 Interact with Hop via command line",
version,
author
)]
pub struct CLI {
#[clap(subcommand)]
pub commands: Commands,
#[clap(
short,
long,
help = "Namespace or ID of the project to use",
global = true
)]
pub project: Option<String>,
#[clap(short = 'D', long, help = "Enable debug mode", global = true)]
pub debug: bool,
}
pub async fn run() -> Result<()> {
let cli = CLI::parse();
utils::set_hook();
utils::logs(cli.debug);
log::debug!("Hop-CLI v{VERSION} build for {ARCH}-{PLATFORM}");
utils::sudo::fix().await?;
let state = State::new(StateOptions {
override_project: std::env::var("PROJECT_ID").ok().or(cli.project),
override_token: std::env::var("TOKEN").ok(),
debug: cli.debug,
})
.await?;
match cli.commands {
#[cfg(feature = "update")]
Commands::Update(_) => {}
Commands::Completions(_) => {}
_ if cfg!(debug_assertions) || state.is_ci => {}
_ => {
let ctx = state.ctx.clone();
tokio::spawn(async move {
if let Err(e) = version_notice(ctx).await {
log::debug!("Failed to check for updates: {e}");
}
});
}
};
if let Err(error) = handle_command(cli.commands, state).await {
log::error!("{error}");
log::debug!("{error:#?}");
std::process::exit(1);
}
utils::clean_term();
Ok(())
}
#[cfg(test)]
mod test {
#[test]
fn test_cli() {
use clap::CommandFactory;
use super::*;
CLI::command().debug_assert();
}
}