ic-backup 0.60.1

Host-side snapshot backup and same-release recovery for Internet Computer canisters
Documentation
//! Exact native fixture byte retention; callers own suspension timing.

use std::{
    fs::File,
    io::{self, Write},
    path::Path,
};

// Preserve create/truncate policy and permissions; sync the containing directory.
// Callers retain the synced descriptor
// for the original qualification lifetime.
pub(crate) fn write_synced(path: &Path, bytes: &[u8]) -> io::Result<File> {
    let mut file = File::create(path)?;
    file.write_all(bytes)?;
    file.sync_all()?;
    File::open(path.parent().expect("fixture reply has a parent"))?.sync_all()?;
    Ok(file)
}

/// Retain exact originals selected by a failure scenario, with path-specific diagnostics.
pub(crate) struct OriginalFiles(Vec<(std::path::PathBuf, Vec<u8>)>);
impl OriginalFiles {
    pub fn capture(paths: impl IntoIterator<Item = impl AsRef<Path>>) -> Self {
        Self(
            paths
                .into_iter()
                .map(|path| {
                    let path = path.as_ref().to_owned();
                    let bytes = std::fs::read(&path)
                        .unwrap_or_else(|error| panic!("capture {}: {error}", path.display()));
                    (path, bytes)
                })
                .collect(),
        )
    }
    pub fn assert_unchanged(&self) {
        for (path, bytes) in &self.0 {
            assert_eq!(
                &std::fs::read(path).unwrap(),
                bytes,
                "original changed: {}",
                path.display()
            );
        }
    }
}