diff --git a/src/error.rs b/src/error.rs index 77653ca..0a358dd 100644 --- a/src/error.rs +++ b/src/error.rs @@ -6,6 +6,12 @@ use failure::Fail; pub enum BakareError { #[fail(display = "io error")] IOError, + #[fail(display = "backup source same as repository")] + SourceSameAsRepository, + #[fail(display = "repository path is not absolute")] + RepositoryPathNotAbsolute, + #[fail(display = "path to store is not absolute")] + PathToStoreNotAbsolute, } impl From for BakareError { diff --git a/src/lib.rs b/src/lib.rs index 7cc4082..81430c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,7 @@ pub mod source; pub mod repository; -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct ItemVersion<'a>(&'a str); #[derive(Copy, Clone)] diff --git a/src/repository.rs b/src/repository.rs index 6b8b19e..3ad0440 100644 --- a/src/repository.rs +++ b/src/repository.rs @@ -22,7 +22,7 @@ pub struct Repository<'a> { newest_index_version: IndexVersion, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct RepositoryItem<'a> { version: ItemVersion<'a>, relative_path: Box, @@ -55,22 +55,47 @@ impl<'a> RepositoryItem<'a> { } impl<'a> Repository<'a> { - pub fn open(path: &Path) -> Result { + fn get_all_files_recursively(path: &Path) -> Result>, BakareError> { + let path_text = path.to_string_lossy(); let walker = WalkDir::new(path); - let all_files: Result, _> = walker - .into_iter() - .filter_entry(|e| e.path() != path && !e.path().is_dir()) - .collect(); - let all_files = all_files?; + + let mut result = vec![]; + + for maybe_entry in walker { + let entry = maybe_entry?; + if entry.path() != path { + if entry.path().is_file() { + result.push(Box::from(path)); + } + if entry.path().is_dir() { + let children = Repository::get_all_files_recursively(entry.path())?; + + for child in children { + result.push(child); + } + } + } + } + + Ok(result) + } + pub fn open(path: &Path) -> Result { + if !path.is_absolute() { + return Err(BakareError::RepositoryPathNotAbsolute); + } + println!("opening repository at {}", path.display()); + + let all_files = Repository::get_all_files_recursively(path)?; let all_items: Vec = all_files .into_iter() .map(|p| RepositoryItem { version: ItemVersion(""), - relative_path: Box::from(p.path()), + relative_path: p, }) .collect(); let version = IndexVersion; + println!("opened repository at {} - {} items present", path.display(), all_items.len()); Ok(Repository { path, index: IndexViewReadonly { @@ -90,15 +115,24 @@ impl<'a> Repository<'a> { } pub fn store(&mut self, source_path: &Path) -> Result<(), BakareError> { - let destination_path = self.path.join(source_path); + if !source_path.is_absolute() { + return Err(BakareError::PathToStoreNotAbsolute); + } + let destination_path: &str = &(self.path.to_string_lossy() + source_path.to_string_lossy()); + let destination_path = Path::new(&destination_path); + if source_path == destination_path { + return Err(BakareError::SourceSameAsRepository); + } if source_path.is_dir() { - fs::create_dir(destination_path.clone())?; + fs::create_dir(destination_path)?; } if source_path.is_file() { - // TODO: copy file + println!("storing {} as {}", source_path.display(), destination_path.display()); + fs::create_dir_all(destination_path.parent().unwrap())?; + fs::copy(source_path, destination_path)?; self.index.items.push(RepositoryItem { version: ItemVersion(""), - relative_path: destination_path.into_boxed_path(), + relative_path: Box::from(destination_path), }); } Ok(()) diff --git a/src/restore.rs b/src/restore.rs index 698373f..2c84f78 100644 --- a/src/restore.rs +++ b/src/restore.rs @@ -4,9 +4,9 @@ use std::path::Path; use walkdir::DirEntry; use crate::error::BakareError; -use crate::ItemVersion; use crate::repository::Repository; use crate::repository::RepositoryItem; +use crate::ItemVersion; pub struct Engine<'a> { repository: &'a Repository<'a>, @@ -19,14 +19,15 @@ impl<'a> Engine<'a> { } pub fn restore_all(&self) -> Result<(), BakareError> { - for ref item in self.repository.iter() { + for item in self.repository.iter() { self.restore(item)?; } Ok(()) } fn restore(&self, item: &RepositoryItem) -> Result<(), BakareError> { - unimplemented!() + println!("restoring {:#?}", item); + Ok(()) } pub fn restore_as_of_version(&self, item: &RepositoryItem, version: &ItemVersion) -> Result<(), BakareError> { diff --git a/tests/system_tests.rs b/tests/system_tests.rs index 7a06586..aa40143 100644 --- a/tests/system_tests.rs +++ b/tests/system_tests.rs @@ -70,7 +70,10 @@ fn assert_target_file_contents(target: &Path, filename: &str, expected_contents: fn assert_same_after_restore(source_path: &Path) -> Result<(), BakareError> { let repository_path = tempdir()?.into_path(); - let restore_target = tempdir()?; + let restore_target = tempdir()?.into_path(); + + assert_ne!(source_path, repository_path); + assert_ne!(repository_path, restore_target); { let mut backup_repository = Repository::open(repository_path.as_path())?; @@ -78,11 +81,11 @@ fn assert_same_after_restore(source_path: &Path) -> Result<(), BakareError> { backup_engine.backup()?; } { - let mut restore_repository = Repository::open(repository_path.as_path())?; - let restore_engine = restore::Engine::new(&mut restore_repository, &restore_target.path()); + let restore_repository = Repository::open(repository_path.as_path())?; + let restore_engine = restore::Engine::new(&restore_repository, &restore_target); restore_engine.restore_all()?; } - let are_source_and_target_different = is_different(source_path, &restore_target.path()).unwrap(); + let are_source_and_target_different = is_different(source_path, &restore_target).unwrap(); assert!(!are_source_and_target_different); Ok(()) }