diff --git a/src/command/config.rs b/src/command/config.rs index f77598a..7ff7620 100644 --- a/src/command/config.rs +++ b/src/command/config.rs @@ -3,8 +3,10 @@ mod migrate; mod validate; -use crate::config::Revision; +use crate::config::{Revision, CLIENT_CONFIG_PATH, OLD_CONFIG_PATH, SERVER_CONFIG_PATH}; use clap::Subcommand; +use serde::Deserialize; +use std::{fs, io::Read, path::Path}; #[derive(Subcommand)] pub(crate) enum Commands { @@ -22,6 +24,71 @@ pub(crate) enum Error { Validate(#[from] validate::ValidationError), } +#[derive(thiserror::Error, Debug)] +pub(crate) enum RevisionCheckError { + #[error("failed to determine the current config revision ({0})")] + UnknownRevision(&'static str), + #[error(transparent)] + InvalidConfig(#[from] toml::de::Error), + #[error(transparent)] + ReadFile(#[from] std::io::Error), +} + +fn next_revision() -> Result, RevisionCheckError> { + let old_config_exists = Path::new(OLD_CONFIG_PATH).is_file(); + let server_config_exists = Path::new(SERVER_CONFIG_PATH).is_file(); + let client_config_exists = Path::new(CLIENT_CONFIG_PATH).is_file(); + + if server_config_exists && !client_config_exists { + return Err(RevisionCheckError::UnknownRevision( + "client config file does not exist", + )); + } + if !server_config_exists && client_config_exists { + return Err(RevisionCheckError::UnknownRevision( + "server config file does not exist", + )); + } + if !old_config_exists && !server_config_exists && !client_config_exists { + return Err(RevisionCheckError::UnknownRevision( + "config file does not exist", + )); + } + + if old_config_exists && !server_config_exists && !client_config_exists { + return Ok(Some(Revision::V20240701)); + } + + #[derive(Deserialize)] + struct Config { + config_revision: Revision, + } + + let mut buffer = String::new(); + + let mut server_toml = fs::File::open(SERVER_CONFIG_PATH)?; + server_toml.read_to_string(&mut buffer)?; + + let server_config_revision = toml::from_str::(&buffer)?.config_revision; + + let mut client_toml = fs::File::open(CLIENT_CONFIG_PATH)?; + client_toml.read_to_string(&mut buffer)?; + + let client_config_revision = toml::from_str::(&buffer)?.config_revision; + + if server_config_revision != client_config_revision { + return Err(RevisionCheckError::UnknownRevision( + "server config revision and client config revision are different", + )); + } + + let next_revision = match server_config_revision { + Revision::V20240701 => None, + }; + + Ok(next_revision) +} + pub(crate) async fn run(command: Commands) -> Result<(), Error> { match command { Commands::Migrate { revision } => migrate::run(revision).await?, diff --git a/src/command/config/migrate.rs b/src/command/config/migrate.rs index 000e605..252a3f5 100644 --- a/src/command/config/migrate.rs +++ b/src/command/config/migrate.rs @@ -2,77 +2,19 @@ mod v20240701; -use crate::config::{Revision, CLIENT_CONFIG_PATH, OLD_CONFIG_PATH, SERVER_CONFIG_PATH}; -use serde::Deserialize; -use std::{fs, io::Read, path::Path}; +use crate::{ + command::config::{next_revision, RevisionCheckError}, + config::Revision, +}; #[derive(thiserror::Error, Debug)] pub(crate) enum MigrationError { - #[error("failed to determine the current config revision ({0})")] - UnknownRevision(&'static str), #[error(transparent)] - ReadFile(#[from] std::io::Error), - #[error(transparent)] - InvalidConfig(#[from] toml::de::Error), + UnknownRevision(#[from] RevisionCheckError), #[error(transparent)] V20240701(#[from] v20240701::Error), } -fn next_revision() -> Result, MigrationError> { - let old_config_exists = Path::new(OLD_CONFIG_PATH).is_file(); - let server_config_exists = Path::new(SERVER_CONFIG_PATH).is_file(); - let client_config_exists = Path::new(CLIENT_CONFIG_PATH).is_file(); - - if server_config_exists && !client_config_exists { - return Err(MigrationError::UnknownRevision( - "client config file does not exist", - )); - } - if !server_config_exists && client_config_exists { - return Err(MigrationError::UnknownRevision( - "server config file does not exist", - )); - } - if !old_config_exists && !server_config_exists && !client_config_exists { - return Err(MigrationError::UnknownRevision( - "config file does not exist", - )); - } - - if old_config_exists && !server_config_exists && !client_config_exists { - return Ok(Some(Revision::V20240701)); - } - - #[derive(Deserialize)] - struct Config { - config_revision: Revision, - } - - let mut buffer = String::new(); - - let mut server_toml = fs::File::open(SERVER_CONFIG_PATH)?; - server_toml.read_to_string(&mut buffer)?; - - let server_config_revision = toml::from_str::(&buffer)?.config_revision; - - let mut client_toml = fs::File::open(CLIENT_CONFIG_PATH)?; - client_toml.read_to_string(&mut buffer)?; - - let client_config_revision = toml::from_str::(&buffer)?.config_revision; - - if server_config_revision != client_config_revision { - return Err(MigrationError::UnknownRevision( - "server config revision and client config revision are different", - )); - } - - let next_revision = match server_config_revision { - Revision::V20240701 => None, - }; - - Ok(next_revision) -} - async fn update_to_latest() -> Result<(), MigrationError> { if next_revision()?.is_none() { println!("Your config files are already up-to-date! (as of this fishctl release)"); diff --git a/src/config/mod.rs b/src/config/mod.rs index e303dfb..b5a44f0 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -4,7 +4,7 @@ pub mod server; use clap::ValueEnum; use serde::{Deserialize, Serialize}; -#[derive(Deserialize, Serialize, PartialEq, PartialOrd, Clone, ValueEnum, Debug)] +#[derive(Deserialize, Serialize, PartialEq, Clone, ValueEnum, Debug)] pub enum Revision { #[clap(name = "20240701")] #[serde(rename = "20240701")]