[WIP] tangled knot rust implementation
1use std::path::PathBuf;
2
3use clap::{Parser, Subcommand};
4
5use crate::{cmd, config::ConfigBuilder};
6
7#[derive(Parser)]
8#[command(
9 author = "boltless.me",
10 version,
11 disable_version_flag = true,
12 about = "Knot cli"
13)]
14pub struct Cli {
15 /// Print version
16 #[arg(short = 'v', long, action = clap::builder::ArgAction::Version)]
17 version: (),
18
19 /// config file path
20 #[arg(short = 'c', long)]
21 config: Option<PathBuf>,
22
23 #[command(subcommand)]
24 command: Commands,
25}
26
27#[derive(Subcommand, Clone)]
28enum Commands {
29 /// run a knot server
30 Daemon,
31 /// fetch public keys from the knot server
32 Keys {
33 /// output format
34 #[arg(long, default_value_t, value_enum)]
35 output: cmd::keys::KeysOutputFormat,
36 },
37 /// role-based access control for git over ssh (not for manual use)
38 Guard {
39 /// possible users accessing the repo
40 #[arg(short = 'u', long, required = true)]
41 users: Vec<String>,
42 },
43 /// run git hooks
44 #[command(subcommand)]
45 Hook(HookCommands),
46}
47
48#[derive(Subcommand, Clone)]
49enum HookCommands {
50 /// sends a post-recieve hook to the knot (waits for stdin)
51 PostReceive {
52 /// git user's did
53 #[arg(long, required = true)]
54 user: String,
55 /// any push option from git
56 #[arg(long)]
57 push_options: Vec<String>,
58 },
59}
60
61pub async fn run() -> anyhow::Result<()> {
62 let cli = Cli::parse();
63
64 let config_path = cli.config.unwrap_or("config.toml".into());
65 let config = ConfigBuilder::new(config_path)?.build()?;
66
67 match cli.command {
68 Commands::Daemon => cmd::daemon::daemon(config).await?,
69 Commands::Keys { output } => cmd::keys::keys(output).await?,
70 Commands::Guard { users } => cmd::guard::guard(users).await?,
71 Commands::Hook(command) => match command {
72 HookCommands::PostReceive { user, push_options } => {
73 cmd::hook::post_receive(user, push_options).await?
74 }
75 },
76 }
77 Ok(())
78}