1use std::path::{Path, PathBuf};
4
5use anyhow::Result;
6
7use crate::dir;
8
9pub fn backup_file(file_path: &Path, backup_dir: &Path) -> Result<PathBuf> {
11 dir::create_dir_all(backup_dir)?;
12 let filename = file_path
13 .file_name()
14 .ok_or_else(|| anyhow::anyhow!("Invalid file path"))?
15 .to_string_lossy()
16 .to_string();
17 let ts = std::time::SystemTime::now()
18 .duration_since(std::time::UNIX_EPOCH)
19 .unwrap_or_default()
20 .as_millis();
21 let backup_name = format!("{}_{}", ts, filename);
22 let backup_path = backup_dir.join(&backup_name);
23 dir::copy(file_path, &backup_path)?;
24 Ok(backup_path)
25}
26
27pub fn prune_oldest_files(dir_path: &Path, keep: usize) {
29 if let Ok(entries) = dir::read_dir(dir_path) {
30 let mut files: Vec<PathBuf> = entries
31 .into_iter()
32 .filter(|(_, is_dir)| !is_dir)
33 .map(|(p, _)| p)
34 .collect();
35 if files.len() <= keep {
36 return;
37 }
38 files.sort_by_key(|p| dir::modified_time(p).unwrap_or(std::time::SystemTime::UNIX_EPOCH));
39 for path in files.iter().take(files.len() - keep) {
40 let _ = dir::remove_file(path);
41 }
42 }
43}