otter/src/cli/mod.rs

88 lines
2.1 KiB
Rust

mod db;
mod gpo;
mod serve;
use std::path::PathBuf;
use clap::{Args, Parser, Subcommand};
use figment::{
providers::{Env, Format, Serialized, Toml},
Figment,
};
use serde::Serialize;
/// Otter is a lightweight implementation of the Gpodder API, designed to be used for small
/// personal deployments.
#[derive(Parser)]
pub struct Cli {
#[command(flatten)]
pub config: ClapConfig,
#[command(subcommand)]
pub cmd: Command,
}
#[derive(Serialize, Args, Clone)]
pub struct ClapConfig {
#[arg(
short,
long = "config",
env = "OTTER_CONFIG_FILE",
value_name = "CONFIG_FILE"
)]
config_file: Option<PathBuf>,
#[serde(skip_serializing_if = "Option::is_none")]
#[arg(long = "data", value_name = "DATA_DIR")]
data_dir: Option<PathBuf>,
#[serde(skip_serializing_if = "Option::is_none")]
#[arg(short, long, value_name = "DOMAIN")]
domain: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[arg(short, long, value_name = "PORT")]
port: Option<u16>,
}
#[derive(Subcommand)]
pub enum Command {
Serve,
#[command(subcommand)]
Db(db::DbCommand),
/// Perform operations on the database through the Gpodder abstraction, allowing operations
/// identical to the ones performed by the API.
#[command(subcommand)]
Gpo(gpo::Command),
}
impl Cli {
pub fn run(&self) -> u8 {
let mut figment = Figment::new();
if let Some(config_path) = &self.config.config_file {
figment = figment.merge(Toml::file(config_path));
}
let config: crate::config::Config = match figment
.merge(Env::prefixed("OTTER_"))
.merge(Serialized::defaults(self.config.clone()))
.extract()
{
Ok(config) => config,
Err(err) => {
eprintln!("{}", err);
return 1;
}
};
match &self.cmd {
Command::Serve => serve::serve(&config),
Command::Db(cmd) => cmd.run(&config),
Command::Gpo(cmd) => cmd.run(&config),
}
}
}