fishctl/src/command/config/update.rs
2024-06-21 10:48:05 +09:00

77 lines
2.2 KiB
Rust

//! `config update` subcommand
mod v1;
use crate::{
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
#[derive(thiserror::Error, Debug)]
pub(crate) enum UpdateError {
#[error(transparent)]
RevisionCheck(#[from] RevisionCheckError),
#[error(transparent)]
FileOperation(#[from] io::Error),
#[error(transparent)]
V1(#[from] v1::Error),
}
fn take_backup() -> Result<(), UpdateError> {
let current_time = Local::now().format("%Y%m%d%H%M%S").to_string();
let server_backup_filename = format!("{}-backup-{}", SERVER_CONFIG_PATH, current_time);
let client_backup_filename = format!("{}-backup-{}", CLIENT_CONFIG_PATH, current_time);
cprintln!(
"Saving server config backup as <bold>{}</>...",
server_backup_filename
);
fs::copy(SERVER_CONFIG_PATH, server_backup_filename)?;
cprintln!(
"Saving client config backup as <bold>{}</>...",
client_backup_filename
);
fs::copy(CLIENT_CONFIG_PATH, client_backup_filename)?;
Ok(())
}
async fn update_to_latest_from(mut current_revision: Revision) -> Result<(), UpdateError> {
while let Some(next_revision) = current_revision.next() {
update_to(next_revision.clone()).await?;
current_revision = next_revision;
}
Ok(())
}
/// Updates config files to the specified revision.
async fn update_to(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 current_revision = current_revision()?;
if current_revision.next().is_none() {
println!("Your config files are already up-to-date! (as of this fishctl release)");
return Ok(());
}
if current_revision != Revision::V0 {
take_backup()?;
}
match revision {
Some(revision) => update_to(revision).await,
None => update_to_latest_from(current_revision).await,
}
}