use crate::{Error, FileSystem, Result}; use chrono::{DateTime, Utc}; use std::{ffi::OsString, path::PathBuf, process::Command}; use tracing::warn; #[derive(Debug)] pub struct Snapshot { name: OsString, file_system: FileSystem, pub(crate) timestamp: DateTime, } impl TryFrom<&str> for Snapshot { type Error = Error; fn try_from(value: &str) -> Result { match value.split('@').collect::>()[..] { [file_system, name] => Ok(Snapshot { file_system: FileSystem::try_from(file_system)?, name: file_system.into(), timestamp: name.parse().unwrap_or_else(|_err| { warn!( "Failed to parse timestamp from `{}`, using default value.", value ); chrono::MIN_DATETIME }), }), _ => Err(Error::Snapshot(format!( "Failed to parse snapshot: {:?}", value ))), } } } impl Snapshot { pub fn clone_into_file_system(&self, new_fs: PathBuf) -> Result { let mut file_system = self.file_system.clone(); file_system.value.push(&new_fs); Command::new("zfs") .arg("clone") .arg(&self.name) .arg(&new_fs) .status()? .success() .then(|| file_system) .ok_or_else(|| Error::Snapshot(format!("Failed to clone snapshot: {:?}", self))) } }