diff --git a/src/command/config.rs b/src/command/config.rs index 5895bec..4c385e1 100644 --- a/src/command/config.rs +++ b/src/command/config.rs @@ -6,7 +6,11 @@ mod validate; 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}; +use std::{ + fs, + io::{self, Read}, + path::Path, +}; #[derive(Subcommand)] pub(crate) enum Commands { @@ -30,9 +34,37 @@ pub(crate) enum RevisionCheckError { #[error("failed to determine the current config revision ({0})")] UnknownRevision(&'static str), #[error(transparent)] - InvalidConfig(#[from] toml::de::Error), + ReadFile(#[from] ReadError), +} + +#[derive(thiserror::Error, Debug)] +pub(crate) enum ReadError { #[error(transparent)] - ReadFile(#[from] std::io::Error), + ReadFile(#[from] io::Error), + #[error("the config file is not written in the correct format")] + InvalidFormat(#[from] toml::de::Error), +} + +fn read_file_string(path: &str) -> Result { + let mut file = fs::File::open(path)?; + let mut result = String::new(); + file.read_to_string(&mut result)?; + + Ok(result) +} + +fn read_server_config() -> Result +where + T: serde::de::DeserializeOwned, +{ + toml::from_str(&read_file_string(SERVER_CONFIG_PATH)?).map_err(ReadError::InvalidFormat) +} + +fn read_client_config() -> Result +where + T: serde::de::DeserializeOwned, +{ + toml::from_str(&read_file_string(CLIENT_CONFIG_PATH)?).map_err(ReadError::InvalidFormat) } fn current_revision() -> Result { @@ -65,19 +97,8 @@ fn current_revision() -> Result { 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; - - buffer.clear(); - - 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; + let server_config_revision = read_server_config::()?.config_revision; + let client_config_revision = read_server_config::()?.config_revision; if server_config_revision != client_config_revision { return Err(RevisionCheckError::UnknownRevision( diff --git a/src/command/config/validate.rs b/src/command/config/validate.rs index 43c1bf9..44b90e7 100644 --- a/src/command/config/validate.rs +++ b/src/command/config/validate.rs @@ -1,12 +1,13 @@ //! `config validate` subcommand use crate::{ - command::config::{current_revision, RevisionCheckError}, + command::config::{ + current_revision, read_client_config, read_server_config, ReadError, RevisionCheckError, + }, config::{client, server, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH}, }; use color_print::cprintln; use enum_iterator::Sequence; -use std::{fs, io::Read}; use validator::Validate; /// Errors that can happen in `config validate` subcommand @@ -22,21 +23,13 @@ pub(crate) enum ValidationError { InvalidConfig, } -#[derive(thiserror::Error, Debug)] -enum ReadError { - #[error(transparent)] - ReadFile(#[from] std::io::Error), - #[error("the config file is not written in the correct format")] - InvalidFormat(#[from] toml::de::Error), -} - pub(super) fn run() -> Result<(), ValidationError> { if current_revision()?.next().is_some() { cprintln!("Please first run `fishctl config update` to update your config files."); return Err(ValidationError::OutOfDate); } - let server_validation_result = match read_server_toml() { + let server_validation_result = match read_server_config::() { Ok(config) => config.validate().map_err(|err| { cprintln!("config/server.toml is invalid.\n{}", err); ValidationError::InvalidConfig @@ -48,7 +41,7 @@ pub(super) fn run() -> Result<(), ValidationError> { Err(ReadError::ReadFile(err)) => Err(ValidationError::ReadFile(err)), }; - let client_validation_result = match read_client_toml() { + let client_validation_result = match read_client_config::() { Ok(config) => config.validate().map_err(|err| { cprintln!( "{} is invalid.\n{}", @@ -79,21 +72,3 @@ pub(super) fn run() -> Result<(), ValidationError> { server_validation_result.and(client_validation_result) } - -fn read_server_toml() -> Result { - let mut file = fs::File::open(SERVER_CONFIG_PATH)?; - - let mut buffer = String::new(); - file.read_to_string(&mut buffer)?; - - toml::from_str(&buffer).map_err(ReadError::InvalidFormat) -} - -fn read_client_toml() -> Result { - let mut file = fs::File::open(CLIENT_CONFIG_PATH)?; - - let mut buffer = String::new(); - file.read_to_string(&mut buffer)?; - - toml::from_str(&buffer).map_err(ReadError::InvalidFormat) -}