use std::path::{Path, PathBuf};
use std::time::{SystemTime, UNIX_EPOCH};
use crate::error::Result;
pub fn backup(path: &Path) -> Result<PathBuf> {
if !path.exists() {
return Ok(PathBuf::new());
}
let epoch_ms = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("system clock before UNIX epoch")
.as_millis();
let bak = PathBuf::from(format!("{}.bak.{}", path.display(), epoch_ms));
std::fs::copy(path, &bak)?;
Ok(bak)
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
#[test]
fn backup_creates_bak_file_with_same_content() {
let tmp = TempDir::new().unwrap();
let src = tmp.path().join("test.json");
std::fs::write(&src, b"hello").unwrap();
let bak = backup(&src).unwrap();
assert!(
!bak.as_os_str().is_empty(),
"backup path should not be empty"
);
assert!(bak.exists(), "backup file should exist");
let fname = bak.file_name().unwrap().to_str().unwrap();
assert!(fname.starts_with("test.json.bak."), "got: {fname}");
let suffix = fname.trim_start_matches("test.json.bak.");
assert!(
suffix.chars().all(|c| c.is_ascii_digit()),
"epoch part must be digits, got: {suffix}"
);
let content = std::fs::read(&bak).unwrap();
assert_eq!(content, b"hello");
}
#[test]
fn backup_nonexistent_returns_empty_path() {
let tmp = TempDir::new().unwrap();
let missing = tmp.path().join("does_not_exist.json");
let result = backup(&missing).unwrap();
assert!(result.as_os_str().is_empty(), "should return empty PathBuf");
}
}