use std::{
fs::{self, File},
io::{Read, Write},
path::Path,
};
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ActiveTask {
pub task_id: String,
pub started_at: String,
}
impl ActiveTask {
pub const fn new(task_id: String, started_at: String) -> Self {
Self {
task_id,
started_at,
}
}
}
pub fn save_active_task(file_path: &Path, active_task: &ActiveTask) -> Result<()> {
log::debug!("Saving active task to {}", file_path.display());
if let Some(parent) = file_path.parent() {
fs::create_dir_all(parent)?;
}
let toml_string = toml::to_string(active_task)?;
let mut file = File::create(file_path)?;
file.write_all(toml_string.as_bytes())?;
Ok(())
}
pub fn load_active_task(file_path: &Path) -> Result<Option<ActiveTask>> {
log::trace!("Checking for active task at {}", file_path.display());
if !file_path.exists() {
log::debug!("No active task file found");
return Ok(None);
}
let mut contents = String::new();
let mut file = File::open(file_path).context(format!(
"Failed to open active task file at {}",
file_path.display()
))?;
file.read_to_string(&mut contents)?;
let active_task: ActiveTask =
toml::from_str(&contents).context("Failed to parse active task TOML")?;
Ok(Some(active_task))
}
pub fn clear_active_task(file_path: &Path) -> Result<()> {
if !file_path.exists() {
log::debug!("No active task file to clear");
return Ok(());
}
fs::remove_file(file_path)?;
log::info!("Cleared active task");
Ok(())
}
#[cfg(test)]
mod tests {
use chrono::Local;
use tempfile::tempdir;
use super::*;
#[test]
fn test_active_task_new() {
let task_id = "test-task-id".to_string();
let started_at = Local::now().to_rfc3339();
let active_task = ActiveTask::new(task_id.clone(), started_at.clone());
assert_eq!(active_task.task_id, task_id);
assert_eq!(active_task.started_at, started_at);
}
#[test]
fn test_save_load_active_task() {
let temp_dir = tempdir().unwrap();
let active_task_file = temp_dir.path().join("active_task.toml");
let task_id = "test-task-id".to_string();
let started_at = Local::now().to_rfc3339();
let active_task = ActiveTask::new(task_id.clone(), started_at.clone());
let save_result = save_active_task(&active_task_file, &active_task);
assert!(save_result.is_ok());
assert!(active_task_file.exists());
let load_result = load_active_task(&active_task_file);
assert!(load_result.is_ok());
let loaded_task_opt = load_result.unwrap();
assert!(loaded_task_opt.is_some());
let loaded_task = loaded_task_opt.unwrap();
assert_eq!(loaded_task.task_id, task_id);
assert_eq!(loaded_task.started_at, started_at);
}
#[test]
fn test_clear_active_task() {
let temp_dir = tempdir().unwrap();
let active_task_file = temp_dir.path().join("active_task.toml");
let task_id = "test-task-id".to_string();
let started_at = Local::now().to_rfc3339();
let active_task = ActiveTask::new(task_id, started_at);
let save_result = save_active_task(&active_task_file, &active_task);
assert!(save_result.is_ok());
assert!(active_task_file.exists());
let clear_result = clear_active_task(&active_task_file);
assert!(clear_result.is_ok());
assert!(!active_task_file.exists());
}
#[test]
fn test_load_nonexistent_active_task() {
let temp_dir = tempdir().unwrap();
let nonexistent_file = temp_dir.path().join("nonexistent.toml");
let load_result = load_active_task(&nonexistent_file);
assert!(load_result.is_ok());
let loaded_task_opt = load_result.unwrap();
assert!(loaded_task_opt.is_none());
}
#[test]
fn test_clear_nonexistent_active_task() {
let temp_dir = tempdir().unwrap();
let nonexistent_file = temp_dir.path().join("nonexistent.toml");
let clear_result = clear_active_task(&nonexistent_file);
assert!(clear_result.is_ok());
}
#[test]
fn test_active_task_serialization() {
let task_id = "test-task-id".to_string();
let started_at = "2023-01-01T12:00:00+00:00".to_string();
let active_task = ActiveTask::new(task_id, started_at);
let serialize_result = toml::to_string(&active_task);
assert!(serialize_result.is_ok());
let toml_string = serialize_result.unwrap();
let deserialize_result: Result<ActiveTask, _> = toml::from_str(&toml_string);
assert!(deserialize_result.is_ok());
let deserialized_task = deserialize_result.unwrap();
assert_eq!(deserialized_task.task_id, active_task.task_id);
assert_eq!(deserialized_task.started_at, active_task.started_at);
}
}