use anyhow::Result; use crate::zfs::Snapshot; use crate::zfs::ZPool; use crate::zfs::Dataset; pub enum Todo { Absolute(Dataset, Snapshot), Incremental(Dataset, Snapshot, Snapshot), UpToDate(Dataset, Snapshot), } impl Todo { pub fn print(&self) { match self { Todo::Absolute(dataset, snapshot) => { println!(" {dataset}@{snapshot} -> [new]") } Todo::Incremental(dataset, last_common_snapshot, recent_snapshot) => { println!(" {dataset}@{last_common_snapshot} -> ...@{recent_snapshot}") } Todo::UpToDate(dataset, snapshot) => { println!(" {dataset}@{snapshot} is already backed up") } } } pub fn plan( local: &ZPool, remote: &ZPool, snapshot_tag: String, snapshot_interval: String, ) -> Result> { let mut result = vec![]; for local_dataset in &local.datasets { let last_snapshot_with_tag = local_dataset.find_last_snapshot_with_tag(&snapshot_tag, &snapshot_interval)?; let remote_dataset = local_dataset.change_pool_name(remote); if !remote.contains(&remote_dataset) { result.push(Todo::Absolute( local_dataset.clone(), last_snapshot_with_tag, )); continue; } let remote_dataset = remote.get_matching_dataset(local_dataset).unwrap(); let last_common_snapshot = Snapshot::find_last_common_snapshot_with_tag( local_dataset, &remote_dataset, &snapshot_tag, ) .unwrap(); let todo = if last_common_snapshot == last_snapshot_with_tag { Todo::UpToDate(local_dataset.clone(), last_common_snapshot) } else { Todo::Incremental( local_dataset.clone(), last_common_snapshot, last_snapshot_with_tag, ) }; result.push(todo); } Ok(result) } }