merge: restore.rs

This commit is contained in:
Omar Sobh
2026-06-16 03:53:19 +00:00
+54
View File
@@ -0,0 +1,54 @@
use crate::zfs::ZfsOps;
use anyhow::Result;
use std::path::PathBuf;
pub fn find_snapshot(zfs: &dyn ZfsOps, dataset: &str, tag: &str) -> Result<Option<String>> {
let full = format!("{}@{}", dataset, tag);
let snaps = zfs.list_snapshots(dataset)?;
Ok(snaps.into_iter().find(|s| *s == full))
}
pub fn restore_project(
zfs: &dyn ZfsOps,
project_name: &str,
snapshot_full_name: &str,
warm_dataset: &str,
) -> Result<PathBuf> {
let ts = snapshot_full_name.split('@').nth(1).unwrap_or("restore");
let dest_dataset = format!("{}/{}-restore-{}", warm_dataset, project_name, ts);
zfs.clone_snapshot(snapshot_full_name, &dest_dataset)?;
let mount_path = format!("/{}", dest_dataset.replace('/', "/"));
Ok(PathBuf::from(mount_path))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::zfs::MockZfs;
#[test]
fn test_restore_clones_snapshot() {
let zfs = MockZfs::default();
zfs.snapshot("slab/projects", "hourly-2026-06-16-0300").unwrap();
let dest = restore_project(
&zfs,
"kitchen-cash",
"slab/projects@hourly-2026-06-16-0300",
"slab/projects",
).unwrap();
assert!(dest.to_string_lossy().contains("kitchen-cash-restore"));
}
#[test]
fn test_restore_errors_on_missing_snapshot() {
let zfs = MockZfs::default();
let result = find_snapshot(
&zfs,
"slab/projects",
"nonexistent-snap",
);
assert!(result.unwrap().is_none());
}
}