use std::fs;
use std::io::Write;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use tempfile::TempDir;
use crate::backup::BackupOptions;
use crate::*;
pub struct ScratchArchive {
#[allow(dead_code)]
tempdir: TempDir, archive: Archive,
archive_path: PathBuf,
}
impl ScratchArchive {
pub fn new() -> ScratchArchive {
let tempdir = TempDir::new().unwrap();
let archive_path = tempdir.path().join("archive");
let archive = Archive::create_path(&archive_path).unwrap();
ScratchArchive {
tempdir,
archive,
archive_path,
}
}
pub fn path(&self) -> &Path {
&self.archive_path
}
pub fn setup_incomplete_empty_band(&self) {
Band::create(&self.archive).unwrap();
}
pub fn store_two_versions(&self) {
let srcdir = TreeFixture::new();
srcdir.create_file("hello");
srcdir.create_dir("subdir");
srcdir.create_file("subdir/subfile");
if SYMLINKS_SUPPORTED {
srcdir.create_symlink("link", "target");
}
let options = &BackupOptions::default();
backup(&self.archive, &srcdir.live_tree(), options).unwrap();
srcdir.create_file("hello2");
backup(&self.archive, &srcdir.live_tree(), options).unwrap();
}
pub fn transport(&self) -> &dyn Transport {
self.archive.transport()
}
}
impl Deref for ScratchArchive {
type Target = Archive;
fn deref(&self) -> &Archive {
&self.archive
}
}
impl AsRef<Archive> for ScratchArchive {
fn as_ref(&self) -> &Archive {
&self.archive
}
}
impl Default for ScratchArchive {
fn default() -> Self {
Self::new()
}
}
pub struct TreeFixture {
pub root: PathBuf,
_tempdir: TempDir, }
impl TreeFixture {
pub fn new() -> TreeFixture {
let tempdir = TempDir::new().unwrap();
let root = tempdir.path().to_path_buf();
TreeFixture {
_tempdir: tempdir,
root,
}
}
pub fn path(&self) -> &Path {
&self.root
}
pub fn create_file(&self, relative_path: &str) -> PathBuf {
self.create_file_with_contents(relative_path, b"contents")
}
pub fn create_file_with_contents(&self, relative_path: &str, contents: &[u8]) -> PathBuf {
let full_path = self.root.join(relative_path);
let mut f = fs::File::create(&full_path).unwrap();
f.write_all(contents).unwrap();
full_path
}
pub fn create_file_of_length_with_prefix(
&self,
relative_path: &str,
length: u64,
prefix: &[u8],
) -> PathBuf {
let full_path = self.root.join(relative_path);
let mut f = fs::File::create(&full_path).unwrap();
f.write_all(prefix).unwrap();
f.set_len(length).expect("set file length");
full_path
}
pub fn create_dir(&self, relative_path: &str) -> PathBuf {
let full_path: PathBuf = self.root.join(relative_path);
fs::create_dir(&full_path).unwrap();
full_path
}
#[cfg(unix)]
pub fn create_symlink(&self, relative_path: &str, target: &str) {
use std::os::unix::fs as unix_fs;
unix_fs::symlink(target, self.root.join(relative_path)).unwrap();
}
#[cfg(windows)]
pub fn create_symlink(&self, _relative_path: &str, _target: &str) {}
pub fn live_tree(&self) -> LiveTree {
LiveTree::open(self.path()).unwrap()
}
#[cfg(unix)]
pub fn make_file_unreadable(&self, relative_path: &str) {
use std::fs::File;
use std::os::unix::fs::PermissionsExt;
let p = self.root.join(relative_path);
let f = File::open(&p).unwrap();
let mut perms = f.metadata().unwrap().permissions();
perms.set_mode(0o0);
fs::set_permissions(&p, perms).unwrap();
}
}
impl Default for TreeFixture {
fn default() -> Self {
Self::new()
}
}