use integer revision

This commit is contained in:
naskya 2024-06-21 09:47:24 +09:00
parent e807488471
commit 1b2a8463bb
Signed by: naskya
GPG key ID: 712D413B3A9FED5C
6 changed files with 68 additions and 28 deletions

33
Cargo.lock generated
View file

@ -420,6 +420,26 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "enum-iterator"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c280b9e6b3ae19e152d8e31cf47f18389781e119d4013a2a2bb0180e5facc635"
dependencies = [
"enum-iterator-derive",
]
[[package]]
name = "enum-iterator-derive"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.66",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@ -466,7 +486,9 @@ dependencies = [
"chrono", "chrono",
"clap", "clap",
"color-print", "color-print",
"enum-iterator",
"serde", "serde",
"serde_repr",
"sqlx", "sqlx",
"thiserror", "thiserror",
"tokio", "tokio",
@ -1218,6 +1240,17 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_repr"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.66",
]
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.6" version = "0.6.6"

View file

@ -13,8 +13,10 @@ path = "src/main.rs"
chrono = "0.4" chrono = "0.4"
clap = { version = "4.5", features = ["derive"] } clap = { version = "4.5", features = ["derive"] }
color-print = "0.3" color-print = "0.3"
enum-iterator = "2.1"
thiserror = "1.0" thiserror = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_repr = "0.1"
sqlx = { version = "0.7", features = ["runtime-tokio", "postgres"] } sqlx = { version = "0.7", features = ["runtime-tokio", "postgres"] }
tokio = { version = "1.38", features = ["full"] } tokio = { version = "1.38", features = ["full"] }
toml = "0.8" toml = "0.8"

View file

@ -35,7 +35,7 @@ pub(crate) enum RevisionCheckError {
ReadFile(#[from] std::io::Error), ReadFile(#[from] std::io::Error),
} }
fn next_revision() -> Result<Option<Revision>, RevisionCheckError> { fn current_revision() -> Result<Revision, RevisionCheckError> {
let old_config_exists = Path::new(OLD_CONFIG_PATH).is_file(); let old_config_exists = Path::new(OLD_CONFIG_PATH).is_file();
let server_config_exists = Path::new(SERVER_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(); let client_config_exists = Path::new(CLIENT_CONFIG_PATH).is_file();
@ -57,7 +57,7 @@ fn next_revision() -> Result<Option<Revision>, RevisionCheckError> {
} }
if old_config_exists && !server_config_exists && !client_config_exists { if old_config_exists && !server_config_exists && !client_config_exists {
return Ok(Some(Revision::V1)); return Ok(Revision::V0);
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -83,11 +83,7 @@ fn next_revision() -> Result<Option<Revision>, RevisionCheckError> {
)); ));
} }
let next_revision = match server_config_revision { Ok(server_config_revision)
Revision::V1 => None,
};
Ok(next_revision)
} }
pub(crate) async fn run(command: Commands) -> Result<(), ConfigError> { pub(crate) async fn run(command: Commands) -> Result<(), ConfigError> {

View file

@ -3,11 +3,12 @@
mod v1; mod v1;
use crate::{ use crate::{
command::config::{next_revision, RevisionCheckError}, command::config::{current_revision, RevisionCheckError},
config::{Revision, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH}, config::{Revision, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH},
}; };
use chrono::Local; use chrono::Local;
use color_print::cprintln; use color_print::cprintln;
use enum_iterator::Sequence;
use std::{fs, io}; use std::{fs, io};
/// Errors that happen in `config update` subcommand /// Errors that happen in `config update` subcommand
@ -41,34 +42,36 @@ fn take_backup() -> Result<(), UpdateError> {
Ok(()) Ok(())
} }
async fn update_to_latest() -> Result<(), UpdateError> { async fn update_to_latest(mut revision: Revision) -> Result<(), UpdateError> {
while let Some(next_revision) = next_revision()? { while let Some(next_revision) = revision.next() {
run_impl(next_revision).await?; run_impl(&next_revision).await?;
revision = next_revision.clone();
} }
Ok(()) Ok(())
} }
/// Updates config files to the specified revision. /// Updates config files to the specified revision.
async fn run_impl(revision: Revision) -> Result<(), UpdateError> { async fn run_impl(revision: &Revision) -> Result<(), UpdateError> {
match revision { match revision {
Revision::V0 => unreachable!(),
Revision::V1 => v1::run().await?, Revision::V1 => v1::run().await?,
} }
Ok(()) Ok(())
} }
pub(super) async fn run(revision: Option<Revision>) -> Result<(), UpdateError> { pub(super) async fn run(revision: Option<Revision>) -> Result<(), UpdateError> {
let next_revision = next_revision()?; let current_revision = current_revision()?;
if next_revision.is_none() { if current_revision == Revision::last().unwrap() {
println!("Your config files are already up-to-date! (as of this fishctl release)"); println!("Your config files are already up-to-date! (as of this fishctl release)");
return Ok(()); return Ok(());
} }
if next_revision.unwrap() != Revision::V1 { if current_revision != Revision::V0 {
take_backup()?; take_backup()?;
} }
match revision { match revision {
Some(revision) => run_impl(revision).await, Some(revision) => run_impl(&revision).await,
None => update_to_latest().await, None => update_to_latest(current_revision).await,
} }
} }

View file

@ -1,10 +1,11 @@
//! `config validate` subcommand //! `config validate` subcommand
use crate::{ use crate::{
command::config::{next_revision, RevisionCheckError}, command::config::{current_revision, RevisionCheckError},
config::{client, server, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH}, config::{client, server, Revision, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH},
}; };
use color_print::cprintln; use color_print::cprintln;
use enum_iterator::Sequence;
use std::{fs, io::Read}; use std::{fs, io::Read};
use validator::Validate; use validator::Validate;
@ -30,7 +31,7 @@ enum ReadError {
} }
pub(super) fn run() -> Result<(), ValidationError> { pub(super) fn run() -> Result<(), ValidationError> {
if next_revision()?.is_some() { if current_revision()? != Revision::last().unwrap() {
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);
} }

View file

@ -2,15 +2,20 @@ pub mod client;
pub mod server; pub mod server;
use clap::ValueEnum; use clap::ValueEnum;
use serde::{Deserialize, Serialize}; use enum_iterator::Sequence;
use serde_repr::{Deserialize_repr, Serialize_repr};
#[derive(Deserialize, Serialize, PartialEq, Clone, ValueEnum, Debug)]
#[clap(rename_all = "lowercase")]
pub enum Revision {
#[serde(rename = "1")]
V1,
}
pub const SERVER_CONFIG_PATH: &str = "config/server.toml"; pub const SERVER_CONFIG_PATH: &str = "config/server.toml";
pub const CLIENT_CONFIG_PATH: &str = "config/client.toml"; pub const CLIENT_CONFIG_PATH: &str = "config/client.toml";
pub const OLD_CONFIG_PATH: &str = ".config/default.yml"; pub const OLD_CONFIG_PATH: &str = ".config/default.yml";
#[derive(Deserialize_repr, Serialize_repr, PartialEq, Clone, ValueEnum, Sequence, Debug)]
#[clap(rename_all = "lowercase")]
#[repr(u8)]
pub enum Revision {
#[clap(skip)]
/// Misskey-style config (`.config/default.yml`)
V0 = 0,
/// The first revision number for `config/{server,client}.toml`
V1,
}