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 clap::{Parser, Subcommand, ValueEnum};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
const SERVERS_ENV_VAR: &str = "MSSH_SERVERS";
|
const SERVERS_ENV_VAR: &str = "MSSH_SERVERS";
|
||||||
|
|
||||||
@ -20,8 +22,8 @@ struct Args {
|
|||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: Command,
|
command: Command,
|
||||||
/// The ssh names and optionally home directories of the servers to perform the action on
|
/// The ssh names and optionally home directories of the servers to perform the action on
|
||||||
#[arg(num_args = 1..)]
|
#[arg(num_args = 1.., value_parser = ServerReference::from_str)]
|
||||||
servers: Vec<String>, //TODO directly parse servers and their directories
|
servers: Vec<ServerReference>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
@ -54,12 +56,81 @@ enum OldVersionPolicy {
|
|||||||
Delete,
|
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)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
struct Server {
|
struct Server {
|
||||||
pub ssh_name: String,
|
pub ssh_name: String,
|
||||||
pub server_directory_path: PathBuf,
|
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)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
struct PluginInfo {
|
struct PluginInfo {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -73,19 +144,6 @@ fn main() -> Result<(), String> {
|
|||||||
let configured_servers = parse_server_configuration_from_env()?;
|
let configured_servers = parse_server_configuration_from_env()?;
|
||||||
dbg!(&configured_servers);
|
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(())
|
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> {
|
fn parse_server_configuration(config_str: &str) -> Result<Vec<Server>, String> {
|
||||||
config_str.split(',').map(|server_entry| {
|
config_str
|
||||||
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))?;
|
.split(',')
|
||||||
Ok(Server {
|
.map(|server_entry| {
|
||||||
ssh_name: name.to_string(),
|
Server::from_str(server_entry)
|
||||||
server_directory_path: PathBuf::from(server_directory),
|
.map_err(|e| format!("Invalid server entry '{server_entry}': {e}"))
|
||||||
})
|
})
|
||||||
}).collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user