fishctl/src/command/config.rs

101 lines
3 KiB
Rust
Raw Normal View History

2024-06-20 08:17:13 +09:00
//! `config` subcommand
2024-06-21 05:00:46 +09:00
mod update;
2024-06-20 02:07:34 +09:00
mod validate;
2024-06-21 04:36:44 +09:00
use crate::config::{Revision, CLIENT_CONFIG_PATH, OLD_CONFIG_PATH, SERVER_CONFIG_PATH};
2024-06-21 03:41:48 +09:00
use clap::Subcommand;
2024-06-21 04:36:44 +09:00
use serde::Deserialize;
use std::{fs, io::Read, path::Path};
2024-06-20 02:07:34 +09:00
#[derive(Subcommand)]
pub(crate) enum Commands {
2024-06-21 05:00:46 +09:00
/// Convert old config files to the new format
Update { revision: Option<Revision> },
2024-06-21 05:01:57 +09:00
/// Validate the config files
2024-06-20 02:07:34 +09:00
Validate,
}
2024-06-21 09:10:28 +09:00
/// Errors that can happen in `config` subcommand
2024-06-20 02:07:34 +09:00
#[derive(thiserror::Error, Debug)]
2024-06-21 09:10:28 +09:00
pub(crate) enum ConfigError {
2024-06-20 02:07:34 +09:00
#[error(transparent)]
2024-06-21 05:00:46 +09:00
Update(#[from] update::UpdateError),
2024-06-20 02:07:34 +09:00
#[error(transparent)]
2024-06-21 03:13:58 +09:00
Validate(#[from] validate::ValidationError),
2024-06-20 02:07:34 +09:00
}
2024-06-21 04:36:44 +09:00
#[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<Option<Revision>, 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 {
2024-06-21 06:49:10 +09:00
return Ok(Some(Revision::V1));
2024-06-21 04:36:44 +09:00
}
#[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::<Config>(&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::<Config>(&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 {
2024-06-21 06:49:10 +09:00
Revision::V1 => None,
2024-06-21 04:36:44 +09:00
};
Ok(next_revision)
}
2024-06-21 09:10:28 +09:00
pub(crate) async fn run(command: Commands) -> Result<(), ConfigError> {
2024-06-20 02:07:34 +09:00
match command {
2024-06-21 05:00:46 +09:00
Commands::Update { revision } => update::run(revision).await?,
2024-06-20 02:07:34 +09:00
Commands::Validate => validate::run()?,
}
Ok(())
}