This commit is contained in:
naskya 2024-06-21 11:05:27 +09:00
parent eae540e3e7
commit 6840a34d90
Signed by: naskya
GPG key ID: 712D413B3A9FED5C
2 changed files with 42 additions and 46 deletions

View file

@ -6,7 +6,11 @@ mod validate;
use crate::config::{Revision, CLIENT_CONFIG_PATH, OLD_CONFIG_PATH, SERVER_CONFIG_PATH}; use crate::config::{Revision, CLIENT_CONFIG_PATH, OLD_CONFIG_PATH, SERVER_CONFIG_PATH};
use clap::Subcommand; use clap::Subcommand;
use serde::Deserialize; use serde::Deserialize;
use std::{fs, io::Read, path::Path}; use std::{
fs,
io::{self, Read},
path::Path,
};
#[derive(Subcommand)] #[derive(Subcommand)]
pub(crate) enum Commands { pub(crate) enum Commands {
@ -30,9 +34,37 @@ pub(crate) enum RevisionCheckError {
#[error("failed to determine the current config revision ({0})")] #[error("failed to determine the current config revision ({0})")]
UnknownRevision(&'static str), UnknownRevision(&'static str),
#[error(transparent)] #[error(transparent)]
InvalidConfig(#[from] toml::de::Error), ReadFile(#[from] ReadError),
}
#[derive(thiserror::Error, Debug)]
pub(crate) enum ReadError {
#[error(transparent)] #[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<String, ReadError> {
let mut file = fs::File::open(path)?;
let mut result = String::new();
file.read_to_string(&mut result)?;
Ok(result)
}
fn read_server_config<T>() -> Result<T, ReadError>
where
T: serde::de::DeserializeOwned,
{
toml::from_str(&read_file_string(SERVER_CONFIG_PATH)?).map_err(ReadError::InvalidFormat)
}
fn read_client_config<T>() -> Result<T, ReadError>
where
T: serde::de::DeserializeOwned,
{
toml::from_str(&read_file_string(CLIENT_CONFIG_PATH)?).map_err(ReadError::InvalidFormat)
} }
fn current_revision() -> Result<Revision, RevisionCheckError> { fn current_revision() -> Result<Revision, RevisionCheckError> {
@ -65,19 +97,8 @@ fn current_revision() -> Result<Revision, RevisionCheckError> {
config_revision: Revision, config_revision: Revision,
} }
let mut buffer = String::new(); let server_config_revision = read_server_config::<Config>()?.config_revision;
let client_config_revision = read_server_config::<Config>()?.config_revision;
let mut server_toml = fs::File::open(SERVER_CONFIG_PATH)?;
server_toml.read_to_string(&mut buffer)?;
let server_config_revision = toml::from_str::<Config>(&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::<Config>(&buffer)?.config_revision;
if server_config_revision != client_config_revision { if server_config_revision != client_config_revision {
return Err(RevisionCheckError::UnknownRevision( return Err(RevisionCheckError::UnknownRevision(

View file

@ -1,12 +1,13 @@
//! `config validate` subcommand //! `config validate` subcommand
use crate::{ 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}, config::{client, server, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH},
}; };
use color_print::cprintln; use color_print::cprintln;
use enum_iterator::Sequence; use enum_iterator::Sequence;
use std::{fs, io::Read};
use validator::Validate; use validator::Validate;
/// Errors that can happen in `config validate` subcommand /// Errors that can happen in `config validate` subcommand
@ -22,21 +23,13 @@ pub(crate) enum ValidationError {
InvalidConfig, 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> { pub(super) fn run() -> Result<(), ValidationError> {
if current_revision()?.next().is_some() { if current_revision()?.next().is_some() {
cprintln!("Please first run `<bold>fishctl config update</>` to update your config files."); cprintln!("Please first run `<bold>fishctl config update</>` to update your config files.");
return Err(ValidationError::OutOfDate); return Err(ValidationError::OutOfDate);
} }
let server_validation_result = match read_server_toml() { let server_validation_result = match read_server_config::<server::Config>() {
Ok(config) => config.validate().map_err(|err| { Ok(config) => config.validate().map_err(|err| {
cprintln!("<r!><bold>config/server.toml is invalid.</></>\n{}", err); cprintln!("<r!><bold>config/server.toml is invalid.</></>\n{}", err);
ValidationError::InvalidConfig ValidationError::InvalidConfig
@ -48,7 +41,7 @@ pub(super) fn run() -> Result<(), ValidationError> {
Err(ReadError::ReadFile(err)) => Err(ValidationError::ReadFile(err)), Err(ReadError::ReadFile(err)) => Err(ValidationError::ReadFile(err)),
}; };
let client_validation_result = match read_client_toml() { let client_validation_result = match read_client_config::<client::Config>() {
Ok(config) => config.validate().map_err(|err| { Ok(config) => config.validate().map_err(|err| {
cprintln!( cprintln!(
"<r!><bold>{} is invalid.</></>\n{}", "<r!><bold>{} is invalid.</></>\n{}",
@ -79,21 +72,3 @@ pub(super) fn run() -> Result<(), ValidationError> {
server_validation_result.and(client_validation_result) server_validation_result.and(client_validation_result)
} }
fn read_server_toml() -> Result<server::Config, ReadError> {
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<client::Config, ReadError> {
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)
}