use crate::server::ServerType; use clap::{Args, Parser, Subcommand}; use std::error::Error; use std::fmt; use std::path::PathBuf; use std::str::FromStr; #[derive(Clone, Debug)] pub struct ManagerConfig { name: String, frequency: u32, chain_len: u64, chains: u64, } #[derive(Debug)] pub struct ParseManagerConfigErr; impl Error for ParseManagerConfigErr {} impl fmt::Display for ParseManagerConfigErr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "parse manager config err") } } impl FromStr for ManagerConfig { type Err = ParseManagerConfigErr; fn from_str(s: &str) -> Result { let splits: Vec<&str> = s.split(',').collect(); if let [name, frequency, chains, chain_len] = splits[..] { let name: String = name.parse().map_err(|_| ParseManagerConfigErr)?; let frequency: u32 = frequency.parse().map_err(|_| ParseManagerConfigErr)?; let chains: u64 = chains.parse().map_err(|_| ParseManagerConfigErr)?; let chain_len: u64 = chain_len.parse().map_err(|_| ParseManagerConfigErr)?; Ok(ManagerConfig { name, chains, chain_len, frequency, }) } else { Err(ParseManagerConfigErr) } } } #[derive(Parser)] #[command(author, version, about, long_about = None)] pub struct Cli { #[command(subcommand)] pub command: Commands, /// Directory where configs are stored, and where the server will run #[arg( long, value_name = "CONFIG_DIR", default_value = ".", env = "ALEX_CONFIG_DIR", global = true )] pub config: PathBuf, /// Directory where world files will be saved #[arg( long, value_name = "WORLD_DIR", default_value = "../worlds", env = "ALEX_WORLD_DIR", global = true )] pub world: PathBuf, /// Directory where backups will be stored #[arg( long, value_name = "BACKUP_DIR", default_value = "../backups", env = "ALEX_BACKUP_DIR", global = true )] pub backup: PathBuf, /// What backup layers to employ, provided as a list of tuples name,frequency,chain_len,chains /// delimited by semicolons (;). #[arg(long, env = "ALEX_LAYERS", global = true, value_delimiter = ';')] pub layers: Vec, /// Length of a backup chain #[arg( short = 'l', long, default_value_t = 4, env = "ALEX_CHAIN_LEN", global = true )] pub chain_len: u64, /// How many backup chains to keep #[arg( short = 'n', long, default_value_t = 7, env = "ALEX_CHAINS", global = true )] pub chains: u64, /// How frequently to perform a backup, in minutes; 0 to disable. #[arg( short = 't', long, default_value_t = 0, env = "ALEX_FREQUENCY", global = true )] pub frequency: u32, /// Type of server #[arg(long, default_value = "unknown", env = "ALEX_SERVER", global = true)] pub server: ServerType, /// Version string for the server, e.g. 1.19.4-545 #[arg(long, default_value = "", env = "ALEX_SERVER_VERSION", global = true)] pub server_version: String, } #[derive(Subcommand)] pub enum Commands { /// Run the server Run(RunArgs), /// Create a new backup of the server. This command should only be used when the server is not /// running. Backup(BackupArgs), } #[derive(Args)] pub struct RunArgs { /// Server jar to execute #[arg( long, value_name = "JAR_PATH", default_value = "server.jar", env = "ALEX_JAR" )] pub jar: PathBuf, /// Java command to run the server jar with #[arg(long, value_name = "JAVA_CMD", default_value_t = String::from("java"), env = "ALEX_JAVA")] pub java: String, /// XMS value in megabytes for the server instance #[arg(long, default_value_t = 1024, env = "ALEX_XMS")] pub xms: u64, /// XMX value in megabytes for the server instance #[arg(long, default_value_t = 2048, env = "ALEX_XMX")] pub xmx: u64, /// Don't actually run the server, but simply output the server configuration that would have /// been ran #[arg(short, long, default_value_t = false)] pub dry: bool, } #[derive(Args)] pub struct BackupArgs {}