diff options
author | HimbeerserverDE <himbeerserverde@gmail.com> | 2024-02-14 18:35:05 +0100 |
---|---|---|
committer | HimbeerserverDE <himbeerserverde@gmail.com> | 2024-02-14 18:35:05 +0100 |
commit | be3e8bc51930913732a5b9c7e514635eb2a75745 (patch) | |
tree | 67a5466415b0841e0e4fae8f8b3341c0f8a8ea9b /hbak_common | |
parent | 90ee9e99e0ea2caf8f016ad527c2abf51af10312 (diff) |
hbak: restore subcommand: restore latest snapshot to subvolume (opt-out)
Diffstat (limited to 'hbak_common')
-rw-r--r-- | hbak_common/src/proto.rs | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/hbak_common/src/proto.rs b/hbak_common/src/proto.rs index 573de6e..2da1a39 100644 --- a/hbak_common/src/proto.rs +++ b/hbak_common/src/proto.rs @@ -432,6 +432,18 @@ impl LocalNode { .ok_or(LocalNodeError::NoIncrementalSnapshot(subvol)) } + /// Returns the latest snapshot, full or incremental, of the specified subvolume of this node. + pub fn latest_snapshot(&self, subvol: String) -> Result<Snapshot, LocalNodeError> { + [ + Some(self.latest_snapshot_full(subvol.clone())?), + self.latest_snapshot_incremental(subvol.clone()).ok(), + ] + .into_iter() + .flatten() + .max_by_key(|snapshot| snapshot.taken()) + .ok_or(LocalNodeError::NoFullSnapshot(subvol)) + } + /// Returns all full snapshots of the specified subvolume of this node /// taken after the provided timestamp. pub fn snapshot_full_after( @@ -686,6 +698,41 @@ impl LocalNode { ), )) } + + /// Restores the latest full or incremental snapshot, whichever is later, + /// of the specified subvolume. Only uses locally stored snapshots, remote recovery + /// with the help of [`LocalNode::recover`] may be necessary. + pub fn restore(&self, subvol: String) -> Result<(), LocalNodeError> { + let subvol_path = Path::new(self.mode.mountpoint()).join(&subvol); + + if subvol_path.exists() + && !Command::new("btrfs") + .arg("subvolume") + .arg("delete") + .arg(&subvol_path) + .spawn()? + .wait()? + .success() + { + return Err(LocalNodeError::BtrfsCmd); + } + + let snapshot = self.latest_snapshot(subvol)?; + + if !Command::new("btrfs") + .arg("subvolume") + .arg("snapshot") + .arg(snapshot.snapshot_path(self.mode)) + .arg(&subvol_path) + .spawn()? + .wait()? + .success() + { + return Err(LocalNodeError::BtrfsCmd); + } + + Ok(()) + } } impl Node for LocalNode { |