use crate::Result;
use std::path::{Path, PathBuf};
pub struct BackupManager {
backup_dir: PathBuf,
}
impl BackupManager {
pub fn new(backup_dir: PathBuf) -> Result<Self> {
std::fs::create_dir_all(&backup_dir)
.map_err(|e| crate::Error::BackupError(format!("Failed to create backup directory: {}", e)))?;
Ok(Self { backup_dir })
}
pub fn create_backup(&self, file_path: &Path, job_id: &str) -> Result<PathBuf> {
if !file_path.exists() {
return Err(crate::Error::BackupError("File does not exist".to_string()));
}
let backup_path = self
.backup_dir
.join(job_id)
.join(
file_path
.file_name()
.ok_or_else(|| crate::Error::BackupError("Invalid filename".to_string()))?,
);
let parent = backup_path.parent()
.ok_or_else(|| crate::Error::BackupError("Invalid backup path".to_string()))?;
std::fs::create_dir_all(parent)
.map_err(|e| crate::Error::BackupError(format!("Failed to create backup directory: {}", e)))?;
std::fs::copy(file_path, &backup_path)
.map_err(|e| crate::Error::BackupError(e.to_string()))?;
Ok(backup_path)
}
pub fn restore(&self, backup_path: &Path, target_path: &Path) -> Result<()> {
if !backup_path.exists() {
return Err(crate::Error::BackupError(
"Backup does not exist".to_string(),
));
}
std::fs::copy(backup_path, target_path)
.map_err(|e| crate::Error::BackupError(e.to_string()))?;
Ok(())
}
pub fn cleanup(&self, older_than_secs: u64) -> Result<()> {
use std::time::{SystemTime, UNIX_EPOCH};
let cutoff = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs()
.saturating_sub(older_than_secs);
if !self.backup_dir.exists() {
return Ok(());
}
for entry in std::fs::read_dir(&self.backup_dir)
.map_err(|e| crate::Error::BackupError(e.to_string()))?
{
let entry = entry.map_err(|e| crate::Error::BackupError(e.to_string()))?;
let path = entry.path();
if !path.is_dir() {
continue;
}
let mtime = path
.metadata()
.map_err(|e| crate::Error::BackupError(e.to_string()))?
.modified()
.map_err(|e| crate::Error::BackupError(e.to_string()))?
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
if mtime < cutoff {
std::fs::remove_dir_all(&path)
.map_err(|e| crate::Error::BackupError(e.to_string()))?;
}
}
Ok(())
}
}