use std::path::PathBuf; use clap::{Parser, Subcommand}; use crate::{cmd, config::ConfigBuilder}; #[derive(Parser)] #[command( author = "boltless.me", version, disable_version_flag = true, about = "Knot cli" )] pub struct Cli { /// Print version #[arg(short = 'v', long, action = clap::builder::ArgAction::Version)] version: (), /// config file path #[arg(short = 'c', long)] config: Option, #[command(subcommand)] command: Commands, } #[derive(Subcommand, Clone)] enum Commands { /// run a knot server Daemon, /// fetch public keys from the knot server Keys { /// output format #[arg(long, default_value_t, value_enum)] output: cmd::keys::KeysOutputFormat, }, /// role-based access control for git over ssh (not for manual use) Guard { /// possible users accessing the repo #[arg(short = 'u', long, required = true)] users: Vec, }, /// run git hooks #[command(subcommand)] Hook(HookCommands), } #[derive(Subcommand, Clone)] enum HookCommands { /// sends a post-recieve hook to the knot (waits for stdin) PostReceive { /// git user's did #[arg(long, required = true)] user: String, /// any push option from git #[arg(long)] push_options: Vec, }, } pub async fn run() -> anyhow::Result<()> { let cli = Cli::parse(); let config_path = cli.config.unwrap_or("config.toml".into()); let config = ConfigBuilder::new(config_path)?.build()?; match cli.command { Commands::Daemon => cmd::daemon::daemon(config).await?, Commands::Keys { output } => cmd::keys::keys(output).await?, Commands::Guard { users } => cmd::guard::guard(users).await?, Commands::Hook(command) => match command { HookCommands::PostReceive { user, push_options } => { cmd::hook::post_receive(user, push_options).await? } }, } Ok(()) }