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",
]
[[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]]
name = "equivalent"
version = "1.0.1"
@ -466,7 +486,9 @@ dependencies = [
"chrono",
"clap",
"color-print",
"enum-iterator",
"serde",
"serde_repr",
"sqlx",
"thiserror",
"tokio",
@ -1218,6 +1240,17 @@ dependencies = [
"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]]
name = "serde_spanned"
version = "0.6.6"

View file

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

View file

@ -35,7 +35,7 @@ pub(crate) enum RevisionCheckError {
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 server_config_exists = Path::new(SERVER_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 {
return Ok(Some(Revision::V1));
return Ok(Revision::V0);
}
#[derive(Deserialize)]
@ -83,11 +83,7 @@ fn next_revision() -> Result<Option<Revision>, RevisionCheckError> {
));
}
let next_revision = match server_config_revision {
Revision::V1 => None,
};
Ok(next_revision)
Ok(server_config_revision)
}
pub(crate) async fn run(command: Commands) -> Result<(), ConfigError> {

View file

@ -3,11 +3,12 @@
mod v1;
use crate::{
command::config::{next_revision, RevisionCheckError},
command::config::{current_revision, RevisionCheckError},
config::{Revision, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH},
};
use chrono::Local;
use color_print::cprintln;
use enum_iterator::Sequence;
use std::{fs, io};
/// Errors that happen in `config update` subcommand
@ -41,34 +42,36 @@ fn take_backup() -> Result<(), UpdateError> {
Ok(())
}
async fn update_to_latest() -> Result<(), UpdateError> {
while let Some(next_revision) = next_revision()? {
run_impl(next_revision).await?;
async fn update_to_latest(mut revision: Revision) -> Result<(), UpdateError> {
while let Some(next_revision) = revision.next() {
run_impl(&next_revision).await?;
revision = next_revision.clone();
}
Ok(())
}
/// 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 {
Revision::V0 => unreachable!(),
Revision::V1 => v1::run().await?,
}
Ok(())
}
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)");
return Ok(());
}
if next_revision.unwrap() != Revision::V1 {
if current_revision != Revision::V0 {
take_backup()?;
}
match revision {
Some(revision) => run_impl(revision).await,
None => update_to_latest().await,
Some(revision) => run_impl(&revision).await,
None => update_to_latest(current_revision).await,
}
}

View file

@ -1,10 +1,11 @@
//! `config validate` subcommand
use crate::{
command::config::{next_revision, RevisionCheckError},
config::{client, server, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH},
command::config::{current_revision, RevisionCheckError},
config::{client, server, Revision, CLIENT_CONFIG_PATH, SERVER_CONFIG_PATH},
};
use color_print::cprintln;
use enum_iterator::Sequence;
use std::{fs, io::Read};
use validator::Validate;
@ -30,7 +31,7 @@ enum ReadError {
}
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.");
return Err(ValidationError::OutOfDate);
}

View file

@ -2,15 +2,20 @@ pub mod client;
pub mod server;
use clap::ValueEnum;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, PartialEq, Clone, ValueEnum, Debug)]
#[clap(rename_all = "lowercase")]
pub enum Revision {
#[serde(rename = "1")]
V1,
}
use enum_iterator::Sequence;
use serde_repr::{Deserialize_repr, Serialize_repr};
pub const SERVER_CONFIG_PATH: &str = "config/server.toml";
pub const CLIENT_CONFIG_PATH: &str = "config/client.toml";
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,
}