diff --git a/Cargo.lock b/Cargo.lock index 4376939..93fd635 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,8 +1,36 @@ +[[package]] +name = "autocfg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "backtrace" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bakare" version = "0.1.0" dependencies = [ "dir-diff 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -13,6 +41,11 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cc" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cfg-if" version = "0.1.6" @@ -34,6 +67,26 @@ dependencies = [ "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "failure" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -58,6 +111,22 @@ name = "libc" version = "0.2.45" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "proc-macro2" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.3.22" @@ -168,6 +237,11 @@ dependencies = [ "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-demangle" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc-serialize" version = "0.3.24" @@ -202,6 +276,27 @@ name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "syn" +version = "0.15.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tempfile" version = "3.0.5" @@ -225,6 +320,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "walkdir" version = "2.2.7" @@ -263,14 +363,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] +"checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727" +"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum dir-diff 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce6e50ca36311e494793f7629014dc78cd963ba85cd05968ae06a63b867f0b" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" +"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" +"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" @@ -283,13 +391,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "a84bcd297b87a545980a2d25a0beb72a1f490c31f0a9fde52fca35bfbb1ceb70" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)" = "734ecc29cd36e8123850d9bf21dfd62ef8300aaa8f879aabaa899721808be37c" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" "checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" diff --git a/Cargo.toml b/Cargo.toml index d20a99b..e767eb6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ license = "AGPL-3.0" walkdir = "2.2" rust-crypto = "0.2" tempfile = "3.0" +failure = "0.1" [dev-dependencies] rust-crypto = "0.2" diff --git a/src/backup.rs b/src/backup.rs index 9a1b1c1..46fe18c 100644 --- a/src/backup.rs +++ b/src/backup.rs @@ -1,93 +1,40 @@ -use crate::storage::Version; +use std::collections::HashMap; +use std::error::Error; use std::fs; use std::io; use std::path::Path; + use walkdir::DirEntry; use walkdir::WalkDir; +use crate::error::BakareError; +use crate::repository::Repository; +use crate::RepositoryRelativePath; +use crate::Version; + pub struct Engine<'a> { source_path: &'a Path, - repository_path: &'a Path, + repository: &'a Repository<'a> } -trait Index {} - -struct InMemoryIndex {} - -impl InMemoryIndex { - fn new() -> Self { - InMemoryIndex {} - } -} - -impl Index for InMemoryIndex {} impl<'a> Engine<'a> { - pub fn new(source_path: &'a Path, repository_path: &'a Path) -> Self { - let index = InMemoryIndex::new(); - Engine::new_with_index(source_path, repository_path, index) - } - - fn new_with_index(source_path: &'a Path, repository_path: &'a Path, index: impl Index) -> Self { + pub fn new(source_path: &'a Path, repository: &'a Repository) -> Self { Engine { source_path, - repository_path, + repository, } } - pub fn backup(&self) -> Result<(), io::Error> { + pub fn backup(&self) -> Result<(), BakareError> { let walker = WalkDir::new(self.source_path); for maybe_entry in walker { let entry = maybe_entry?; if entry.path() != self.source_path { - self.process_entry(&entry)?; + self.repository.store_entry(&entry)?; } } Ok(()) } - pub fn file_version(&self, path: &Path) -> Version { - Version::Newest - } - - fn process_entry(&self, entry: &DirEntry) -> Result<(), io::Error> { - // TODO: remember entry in index - - // TODO: store file data - - if entry.file_type().is_dir() { - fs::create_dir(self.repository_path.join(entry.file_name()))?; - } - if entry.file_type().is_file() { - fs::copy(entry.path(), self.repository_path.join(entry.file_name()))?; - } - Ok(()) - } -} - -#[cfg(test)] -mod should { - - use super::*; - use tempfile::tempdir; - - use crate::source::Source; - - #[test] - fn store_file_where_index_tells_it() -> Result<(), io::Error> { - let index = FakeIndex {}; - - let source = Source::new()?; - let repository = tempdir()?; - let engine = Engine::new_with_index(source.path(), repository.path(), index); - - // backup - // see if repo contains one file at the faked path - assert!(false); - Ok(()) - } - - struct FakeIndex {} - - impl Index for FakeIndex {} } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..77653ca --- /dev/null +++ b/src/error.rs @@ -0,0 +1,21 @@ +use std::io; + +use failure::Fail; + +#[derive(Debug, Fail)] +pub enum BakareError { + #[fail(display = "io error")] + IOError, +} + +impl From for BakareError { + fn from(e: io::Error) -> Self { + BakareError::IOError + } +} + +impl From for BakareError { + fn from(e: walkdir::Error) -> Self { + BakareError::IOError + } +} diff --git a/src/lib.rs b/src/lib.rs index ace8b5f..9995152 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,22 @@ +use std::collections::HashMap; +use std::fmt::Display; +use std::fmt::Formatter; +use std::io; + +use failure::Fail; + +pub mod error; pub mod backup; pub mod restore; - pub mod source; -mod storage; +pub mod repository; + +pub struct Version(String); +struct RepositoryRelativePath {} + +struct Index<'a> { + versions: HashMap<&'a RepositoryRelativePath, &'a Version>, +} + + diff --git a/src/repository.rs b/src/repository.rs new file mode 100644 index 0000000..99cec3d --- /dev/null +++ b/src/repository.rs @@ -0,0 +1,68 @@ +use std::error::Error; +use std::fs; +use std::io; +use std::path::Path; + +use walkdir::DirEntry; + +use crate::error::BakareError; +use crate::Version; + +/// represents a place where backup is stored an can be restored from. E.g. a directory, a cloud service etc +pub struct Repository<'a> { + path: &'a Path +} + +pub struct StoredItemId; +pub struct RelativePath; +impl<'a> Repository<'a> { + pub fn new(path: &Path) -> Result { + Ok(Repository { + path + }) + } + + pub fn store_entry(&self, entry: &DirEntry) -> Result<(), BakareError> { + // get file id -> contents hash + original path + time of taking notes + // get storage path for File + // store file contents + // remember File + + if entry.file_type().is_dir() { + fs::create_dir(self.path.join(entry.file_name()))?; + } + if entry.file_type().is_file() { + fs::copy(entry.path(), self.path.join(entry.file_name()))?; + } + Ok(()) + } + + pub fn newest_version_for(&self, item: &StoredItemId) -> Result { + unimplemented!() + } + + pub fn relative_path(&self, path: &str) -> RelativePath { + unimplemented!() + } + + pub fn file_id(&self, path: &RelativePath) -> Result { + unimplemented!() + } +} + +impl<'a> Iterator for Repository<'a> { + type Item = StoredItemId; + + fn next(&mut self) -> Option<::Item> { + unimplemented!() + } +} + +impl<'a> Iterator for &Repository<'a> { + type Item = StoredItemId; + + fn next(&mut self) -> Option<::Item> { + unimplemented!() + } +} + diff --git a/src/restore.rs b/src/restore.rs index eef0f67..4032eee 100644 --- a/src/restore.rs +++ b/src/restore.rs @@ -1,52 +1,47 @@ -use crate::storage::Version; +use std::error::Error; use std::fs; use std::io; use std::path::Path; + use walkdir::DirEntry; use walkdir::WalkDir; +use crate::error::BakareError; +use crate::repository::Repository; +use crate::repository::StoredItemId; +use crate::Version; + pub struct Engine<'a> { - repository_path: &'a Path, + repository: &'a Repository<'a>, target_path: &'a Path, } -pub enum WhatToRestore { - All, - SpecificPath(String), -} impl<'a> Engine<'a> { - pub fn new(repository_path: &'a Path, target_path: &'a Path) -> Self { + pub fn new(repository: &'a Repository, target_path: &'a Path) -> Self { Engine { - repository_path, + repository, target_path, } } - pub fn restore_all(&self) -> Result<(), io::Error> { - self.restore(WhatToRestore::All) - } - - fn restore(&self, what: WhatToRestore) -> Result<(), io::Error> { - self.restore_as_of_version(what, Version::Newest) - } - - pub fn restore_as_of_version(&self, what: WhatToRestore, version: Version) -> Result<(), io::Error> { - let walker = WalkDir::new(self.repository_path); - for maybe_entry in walker { - match maybe_entry { - Ok(entry) => { - if entry.path() != self.repository_path { - self.process_entry(&entry)?; - } - } - Err(error) => return Err(error.into()), - } + pub fn restore_all(&self) -> Result<(), BakareError> { + for item in self.repository { + self.restore(item)?; } Ok(()) } - fn process_entry(&self, entry: &DirEntry) -> Result<(), io::Error> { + fn restore(&self, item: StoredItemId) -> Result<(), BakareError> { + let version = self.repository.newest_version_for(&item)?; + self.restore_as_of_version(item, version) + } + + pub fn restore_as_of_version(&self, what: StoredItemId, version: Version) -> Result<(), BakareError> { + unimplemented!() + } + + fn process_entry(&self, entry: &DirEntry) -> Result<(), BakareError> { if entry.file_type().is_dir() { fs::create_dir(self.target_path.join(entry.file_name()))?; } diff --git a/src/source.rs b/src/source.rs index 997d92f..ce40ce4 100644 --- a/src/source.rs +++ b/src/source.rs @@ -2,6 +2,7 @@ use std::fs::File; use std::io::Error; use std::io::Write; use std::path::Path; + use tempfile::tempdir; use tempfile::TempDir; diff --git a/src/storage.rs b/src/storage.rs deleted file mode 100644 index 279b186..0000000 --- a/src/storage.rs +++ /dev/null @@ -1,131 +0,0 @@ -use std::collections::HashMap; -use std::collections::HashSet; - -#[derive(Copy, Clone, Debug, PartialOrd, PartialEq)] -pub enum Version { - Newest, - Specific(u64), -} - -impl Version { - fn next(self) -> Self { - match self { - Version::Newest => Version::Newest, - Version::Specific(old) => Version::Specific(old + 1), - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -struct Hash([u8; 32]); - -#[derive(Clone)] -struct IndexHashEntry { - source_paths: HashSet, - storage_path: String, -} - -#[derive(Clone)] -struct IndexPathEntry { - hash: Hash, - version: Version, - storage_path: String, -} - -struct Index<'a> { - file_hashes: HashMap, - file_paths: HashMap<&'a str, IndexPathEntry>, -} - -impl<'a> Index<'a> { - fn new() -> Self { - Self { - file_hashes: HashMap::new(), - file_paths: HashMap::new(), - } - } - - fn store(&mut self, source_path: &'a str, hash: Hash) -> (Version, String) { - let path_entry = { - self.file_paths.get(source_path).map_or_else( - || IndexPathEntry { - hash, - version: Version::Newest, - storage_path: format!("{:X?}", hash.0), - }, - |old_entry| { - if old_entry.hash == hash { - old_entry.clone() // FIXME optimise - } else { - IndexPathEntry { - hash, - version: old_entry.version.next(), - storage_path: old_entry.storage_path.clone(), - } - } - }, - ) - }; - - self.file_paths.insert(source_path, path_entry.clone()); - - let hash_entry = { - self.file_hashes.get(&hash).map_or_else( - || { - let mut source_paths = HashSet::new(); - source_paths.insert(source_path.to_string()); - IndexHashEntry { - source_paths, - storage_path: format!("{:X?}", hash.0), - } - }, - |old_entry| { - let mut source_paths = old_entry.source_paths.clone(); - source_paths.insert(source_path.to_string()); - IndexHashEntry { - source_paths, - storage_path: old_entry.storage_path.clone(), - } - }, - ) - }; - - self.file_hashes.insert(hash, hash_entry); - (path_entry.version, path_entry.storage_path.to_string()) - } - - fn latest_version_for_path(&self, path: &str) -> Option { - self.file_paths.get(path).map_or(None, |entry| Some(entry.version)) - } -} - -#[cfg(test)] -mod should { - - use super::*; - - const SOME_HASH: Hash = Hash([1; 32]); - const SOME_OTHER_HASH: Hash = Hash([2; 32]); - - #[test] - fn support_file_versions() { - let mut index = Index::new(); - let (v1, _) = index.store("/some/path", SOME_HASH); - let (v2, _) = index.store("/some/path", SOME_OTHER_HASH); - - assert_eq!(v2, index.latest_version_for_path("/some/path").unwrap()); - - assert!(v2 > v1); - } - - #[test] - fn support_deduplication() { - let mut index = Index::new(); - let (_, storage_path1) = index.store("/some/path", SOME_HASH); - let (_, storage_path2) = index.store("/some/path", SOME_HASH); - let (_, storage_path3) = index.store("/some/other/path", SOME_HASH); - - assert_eq!(storage_path1, storage_path2); - assert_eq!(storage_path1, storage_path3); - } -} diff --git a/tests/system_tests.rs b/tests/system_tests.rs index 8c85b11..cab812f 100644 --- a/tests/system_tests.rs +++ b/tests/system_tests.rs @@ -1,56 +1,60 @@ use bakare::backup; use bakare::restore; -use bakare::restore::WhatToRestore::SpecificPath; use bakare::source::Source; use dir_diff::is_different; use std::fs::File; -use std::io::Error; use std::io::Read; use std::path::Path; use tempfile::tempdir; +use bakare::error::BakareError; +use bakare::repository::Repository; #[test] -fn restore_backed_up_files() -> Result<(), Error> { +fn restore_backed_up_files() -> Result<(), BakareError> { let source = Source::new()?; - let repository = tempdir()?; + let repository_path = tempdir()?.into_path(); + let repository = Repository::new(repository_path.as_path())?; source.write_text_to_file("first", "some contents")?; source.write_text_to_file("second", "some contents")?; source.write_text_to_file("third", "some other contents")?; - assert_same_after_restore(source.path(), repository.path()) + assert_same_after_restore(source.path(), &repository) } #[test] -fn restore_older_version_of_file() -> Result<(), Error> { +fn restore_older_version_of_file() -> Result<(), BakareError> { let source = Source::new()?; - let repository = tempdir()?; - let backup_engine = backup::Engine::new(source.path(), repository.path()); - let path = "some path"; + let repository_path = tempdir()?.into_path(); + let repository = Repository::new(repository_path.as_path())?; + let backup_engine = backup::Engine::new(source.path(), &repository); + let file_path = "some path"; let new_contents = "totally new contents"; let restore_target = tempdir()?; - let restore_engine = restore::Engine::new(repository.path(), &restore_target.path()); + let restore_engine = restore::Engine::new(&repository, &restore_target.path()); let old_contents = "some old contents"; - source.write_text_to_file(path, old_contents)?; + source.write_text_to_file(file_path, old_contents)?; backup_engine.backup()?; - let old_version = backup_engine.file_version(path.as_ref()); + let repository_path = repository.relative_path(file_path); + let file_id = repository.file_id(&repository_path)?; + let old_version = repository.newest_version_for(&file_id)?; - source.write_text_to_file(path, new_contents)?; + source.write_text_to_file(file_path, new_contents)?; backup_engine.backup()?; - restore_engine.restore_as_of_version(SpecificPath(path.into()), old_version)?; + restore_engine.restore_as_of_version(file_id, old_version)?; - assert_target_file_contents(restore_target.path(), path, old_contents)?; + assert_target_file_contents(restore_target.path(), file_path, old_contents)?; Ok(()) } // TODO: restore latest version by default // TODO: deduplicate data -fn assert_target_file_contents(target: &Path, filename: &str, expected_contents: &str) -> Result<(), Error> { +fn assert_target_file_contents(target: &Path, filename: &str, expected_contents: &str) -> Result<(), BakareError> { let restored_path = target.join(filename); let mut actual_contents = String::new(); File::open(restored_path)?.read_to_string(&mut actual_contents)?; @@ -58,12 +62,12 @@ fn assert_target_file_contents(target: &Path, filename: &str, expected_contents: Ok(()) } -fn assert_same_after_restore(source_path: &Path, repository_path: &Path) -> Result<(), Error> { - let backup_engine = backup::Engine::new(source_path, repository_path); +fn assert_same_after_restore(source_path: &Path, repository: &Repository) -> Result<(), BakareError> { + let backup_engine = backup::Engine::new(source_path, repository); backup_engine.backup()?; let restore_target = tempdir()?; - let restore_engine = restore::Engine::new(repository_path, &restore_target.path()); + let restore_engine = restore::Engine::new(repository, &restore_target.path()); restore_engine.restore_all()?; let are_source_and_target_different = is_different(source_path, &restore_target.path()).unwrap();