Add ServerReference and parse methods for Server
This commit is contained in:
parent
9e0bf8c8c4
commit
03b7a6f67f
102
src/main.rs
102
src/main.rs
@ -1,7 +1,9 @@
|
||||
use clap::builder::Str;
|
||||
use clap::{Parser, Subcommand, ValueEnum};
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
const SERVERS_ENV_VAR: &str = "MSSH_SERVERS";
|
||||
|
||||
@ -20,8 +22,8 @@ struct Args {
|
||||
#[command(subcommand)]
|
||||
command: Command,
|
||||
/// The ssh names and optionally home directories of the servers to perform the action on
|
||||
#[arg(num_args = 1..)]
|
||||
servers: Vec<String>, //TODO directly parse servers and their directories
|
||||
#[arg(num_args = 1.., value_parser = ServerReference::from_str)]
|
||||
servers: Vec<ServerReference>,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
@ -54,12 +56,81 @@ enum OldVersionPolicy {
|
||||
Delete,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum ServerReference {
|
||||
Resolved(Server),
|
||||
Name(String),
|
||||
}
|
||||
|
||||
impl ServerReference {
|
||||
//TODO lazy resolve method which gets a provider for configured servers
|
||||
pub fn resolve(self, configured_servers: &[Server]) -> Option<Server> {
|
||||
match self {
|
||||
ServerReference::Resolved(server) => Some(server),
|
||||
ServerReference::Name(name) => configured_servers
|
||||
.iter()
|
||||
.find(|server| server.ssh_name == name)
|
||||
.cloned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for ServerReference {
|
||||
type Err = ServerParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Server::from_str(s)
|
||||
.map(Self::Resolved)
|
||||
.or_else(|_| Ok(Self::Name(s.to_string())))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
struct Server {
|
||||
pub ssh_name: String,
|
||||
pub server_directory_path: PathBuf,
|
||||
}
|
||||
|
||||
impl FromStr for Server {
|
||||
type Err = ServerParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
s.split_once(':')
|
||||
.ok_or(ServerParseError::MissingServerDirectory)
|
||||
.map(|(name, directory)| Self {
|
||||
ssh_name: name.to_string(),
|
||||
server_directory_path: PathBuf::from(directory),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Server {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}:{:?}", self.ssh_name, self.server_directory_path)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ServerParseError {
|
||||
MissingServerDirectory,
|
||||
}
|
||||
|
||||
impl Display for ServerParseError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ServerParseError::MissingServerDirectory => {
|
||||
write!(
|
||||
f,
|
||||
"String is not specifying a server directory. Please use an empty string after a \
|
||||
double colon to point to the home directory, e.g: 'lobby:'"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ServerParseError {}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
struct PluginInfo {
|
||||
pub name: String,
|
||||
@ -73,19 +144,6 @@ fn main() -> Result<(), String> {
|
||||
let configured_servers = parse_server_configuration_from_env()?;
|
||||
dbg!(&configured_servers);
|
||||
|
||||
let servers = args
|
||||
.servers
|
||||
.iter()
|
||||
.map(|server_name| {
|
||||
configured_servers
|
||||
.iter()
|
||||
.find(|server| server.ssh_name == *server_name)
|
||||
.ok_or(format!(
|
||||
"no server with the name '{server_name}' has been configured"
|
||||
))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -96,13 +154,13 @@ fn parse_server_configuration_from_env() -> Result<Vec<Server>, String> {
|
||||
}
|
||||
|
||||
fn parse_server_configuration(config_str: &str) -> Result<Vec<Server>, String> {
|
||||
config_str.split(',').map(|server_entry| {
|
||||
let (name, server_directory) = server_entry.split_once(':').ok_or(format!("Server entry doesn't specify a server directory (separate name and directory via double colon) for entry '{}'", server_entry))?;
|
||||
Ok(Server {
|
||||
ssh_name: name.to_string(),
|
||||
server_directory_path: PathBuf::from(server_directory),
|
||||
config_str
|
||||
.split(',')
|
||||
.map(|server_entry| {
|
||||
Server::from_str(server_entry)
|
||||
.map_err(|e| format!("Invalid server entry '{server_entry}': {e}"))
|
||||
})
|
||||
}).collect()
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user