Skip to main content

skilllite_fs/
backup.rs

1//! 备份与清理
2
3use std::path::{Path, PathBuf};
4
5use anyhow::Result;
6
7use crate::dir;
8
9/// 备份文件到 backup_dir,返回备份路径
10pub 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
27/// 清理目录中最老的条目,保留 keep 个
28pub 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}