commit fa7caf87e2f80ead57b536efc13dd4b7299cdea9 Author: Steppy Date: Wed Dec 11 10:42:44 2024 +0100 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..4a1142a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "plugin_uploader" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.5.23", features = ["derive"] } diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..6f2e075 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +tab_spaces = 2 \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b2b52f4 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,103 @@ +use clap::Parser; +use std::env; +use std::path::PathBuf; + +const SERVERS_ENV_VAR: &str = "PLUGIN_UPLOADER_SERVERS"; + +/// Uploads a plugin to one or multiple configured servers. +/// +/// By default, older versions of the plugin will be deleted. +/// +/// --- Server configuration --- +/// +/// Servers can be configured via environment variable `PLUGIN_UPLOADER_SERVERS`. +/// The value should be a string which contains the ssh name and the server directory path. +/// +/// --- Example --- +/// +/// export PLUGIN_UPLOADER_SERVERS="crea:server/creative2,city:city2,lobby:" +#[derive(Parser, Debug)] +#[command(version, about, long_about)] +struct Args { + /// The plugin file to upload + plugin: PathBuf, + /// The ssh names of the servers to upload to + #[arg(num_args = 1..)] + servers: Vec, + /// Whether not to delete, but to rename the previous plugin + #[arg(short, long, value_name = "archive", default_value = "false", default_missing_values = ["true"])] + archive_old_versions: bool, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +struct Server { + pub ssh_name: String, + pub server_directory_path: PathBuf, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +struct PluginInfo { + pub name: String, + pub version: Option, +} + +fn main() -> Result<(), String> { + let args = Args::parse(); + dbg!(&args); + + 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::, _>>()?; + + if !args.plugin.is_file() { + return Err("plugin is not a file".to_string()) + } + + //args.plugin.canonicalize() + + Ok(()) +} + +fn parse_server_configuration_from_env() -> Result, String> { + env::var(SERVERS_ENV_VAR) + .map_err(|_| format!("Missing environment variable {}", SERVERS_ENV_VAR)) + .and_then(|value| parse_server_configuration(&value)) +} + +fn parse_server_configuration(config_str: &str) -> Result, 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), + }) + }).collect() +} + +#[cfg(test)] +mod test { + use crate::{parse_server_configuration, Server}; + use std::path::PathBuf; + + #[test] + fn test_parse_server_configuration() { + let servers = parse_server_configuration("foo:bar,fizz:buzz/bizz").expect("valid server configuration"); + assert_eq!(vec![Server { + ssh_name: "foo".to_string(), + server_directory_path: PathBuf::from("bar"), + }, Server { + ssh_name: "fizz".to_string(), + server_directory_path: PathBuf::from("buzz/bizz"), + }], servers); + } +}