use figment::{Figment, Provider}; use std::path::PathBuf; use std::process::Command; use crate::{Config, Error, FileSystem, Result}; #[derive(Default, Debug)] pub struct ZFS { pub config: Config, } impl ZFS { pub fn new() -> Result { Self::custom(Config::figment()) } pub fn custom(provider: T) -> Result { Config::from(Figment::from(provider)) .map_err(Error::from) .map(|config| Self { config }) } #[cfg(feature = "chrono")] pub fn clone_from_latest(&self, name: PathBuf, parent: PathBuf) -> Result { self.get_file_system(parent)? .get_latest_snapshot()? .ok_or_else(|| Error::Snapshot("No snapshot found".into()))? .clone_new(name) } pub fn get_file_systems(&self) -> Result> { Command::new("zfs") .arg("list") .arg("-H") .arg("-o") .arg("name") .output() .map(|o| String::from_utf8(o.stdout))? .map_err(Error::from) .map(|s| { s.lines() .into_iter() .filter_map(|l| l.split_once(' ').map(|s| (s.0.trim(), s.1.trim()))) .filter_map(|(dataset, mountpoint)| { let mountpoint = if mountpoint == "none" { PathBuf::from(mountpoint) } else { self.config.mountpoint.to_owned() }; FileSystem::builder() .mountpoint(mountpoint) .dataset(dataset) .quota(self.config.quota) .to_file_system() .ok() }) .collect() }) } pub fn get_file_system(&self, name: PathBuf) -> Result { self.get_file_systems()? .into_iter() .find(|fs| fs.dataset().ends_with(&name)) .ok_or_else(|| Error::FileSystem("No file system found".into())) } } #[cfg(test)] mod tests { #[test] fn get_file_systems() { use super::*; assert!(ZFS::new().unwrap().get_file_systems().is_ok()); } }