use std::path::{Path, PathBuf};
use busylib::model::updater::AutoupdateSettings;
use busylib::types::time_of_day::TimeOfDay;
use clap::Subcommand;
use crate::cli::Context;
use crate::error::{CliError, Result};
use crate::io::Io;
use crate::reporter::{OkEvent, UpdaterAutoupdateEvent, UpdaterChangelogEvent, UpdaterStatusEvent};
#[derive(Debug, Subcommand)]
pub enum UpdaterCommand {
Update {
#[arg(value_name = "FILE")]
file: PathBuf,
},
Check,
Status,
Changelog {
#[arg(value_name = "VERSION")]
version: String,
},
Install {
#[arg(value_name = "VERSION")]
version: String,
},
AbortDownload,
Autoupdate,
SetAutoupdate {
#[arg(long)]
enable: bool,
#[arg(long, conflicts_with = "enable")]
disable: bool,
#[arg(long, value_name = "HH:MM")]
start: Option<TimeOfDay>,
#[arg(long, value_name = "HH:MM")]
end: Option<TimeOfDay>,
},
}
impl UpdaterCommand {
pub async fn run(self, context: &Context) -> Result<()> {
match self {
UpdaterCommand::Update { file } => update(context, &file).await,
UpdaterCommand::Check => check(context).await,
UpdaterCommand::Status => status(context).await,
UpdaterCommand::Changelog { version } => changelog(context, &version).await,
UpdaterCommand::Install { version } => install(context, &version).await,
UpdaterCommand::AbortDownload => abort_download(context).await,
UpdaterCommand::Autoupdate => autoupdate(context).await,
UpdaterCommand::SetAutoupdate {
enable,
disable,
start,
end,
} => set_autoupdate(context, enable, disable, start, end).await,
}
}
}
async fn update(context: &Context, file: &Path) -> Result<()> {
let package = Io::read_bytes(file)?;
context.client.updater().update(package).await?;
context.reporter.report(OkEvent::new("updater update"))?;
Ok(())
}
async fn check(context: &Context) -> Result<()> {
context.client.updater().check().await?;
context.reporter.report(OkEvent::new("updater check"))?;
Ok(())
}
async fn status(context: &Context) -> Result<()> {
let status = context.client.updater().status().await?;
context.reporter.report(UpdaterStatusEvent::new(status))?;
Ok(())
}
async fn changelog(context: &Context, version: &str) -> Result<()> {
let changelog = context.client.updater().changelog(version).await?;
context
.reporter
.report(UpdaterChangelogEvent::new(changelog))?;
Ok(())
}
async fn install(context: &Context, version: &str) -> Result<()> {
context.client.updater().install(version).await?;
context.reporter.report(OkEvent::new("updater install"))?;
Ok(())
}
async fn abort_download(context: &Context) -> Result<()> {
context.client.updater().abort_download().await?;
context
.reporter
.report(OkEvent::new("updater abort-download"))?;
Ok(())
}
async fn autoupdate(context: &Context) -> Result<()> {
let settings = context.client.updater().autoupdate().await?;
context
.reporter
.report(UpdaterAutoupdateEvent::new(settings))?;
Ok(())
}
async fn set_autoupdate(
context: &Context,
enable: bool,
disable: bool,
start: Option<TimeOfDay>,
end: Option<TimeOfDay>,
) -> Result<()> {
let mut settings = AutoupdateSettings::new();
if enable || disable {
settings = settings.enabled(enable);
}
match (start, end) {
(Some(start), Some(end)) => settings = settings.window(start, end),
(Some(_), None) | (None, Some(_)) => {
return Err(CliError::Usage("--start and --end go together"));
}
(None, None) => {}
}
context.client.updater().set_autoupdate(&settings).await?;
context
.reporter
.report(OkEvent::new("updater set-autoupdate"))?;
Ok(())
}