diff --git a/fs-index/benches/resource_index_benchmark.rs b/fs-index/benches/resource_index_benchmark.rs index 1a1a4660..5f73f172 100644 --- a/fs-index/benches/resource_index_benchmark.rs +++ b/fs-index/benches/resource_index_benchmark.rs @@ -55,61 +55,6 @@ fn resource_index_benchmark(c: &mut Criterion) { }); }); - // Benchmark `ResourceIndex::track_addition()` - let new_file = benchmarks_dir.join("new_file.txt"); - group.bench_function("index_track_addition", |b| { - b.iter(|| { - std::fs::File::create(&new_file).unwrap(); - std::fs::write(&new_file, "Hello, World!").unwrap(); - let mut index: ResourceIndex = - ResourceIndex::build(black_box(benchmarks_dir)).unwrap(); - let _addition_result = index.track_addition(&new_file).unwrap(); - - // Cleanup - std::fs::remove_file(&new_file).unwrap(); - }); - }); - - // Benchmark `ResourceIndex::track_removal()` - let removed_file = benchmarks_dir.join("new_file.txt"); - group.bench_function("index_track_removal", |b| { - b.iter(|| { - std::fs::File::create(&removed_file).unwrap(); - std::fs::write(&removed_file, "Hello, World!").unwrap(); - let mut index: ResourceIndex = - ResourceIndex::build(black_box(benchmarks_dir)).unwrap(); - std::fs::remove_file(&removed_file).unwrap(); - let relative_path = removed_file - .strip_prefix(benchmarks_dir) - .unwrap() - .to_str() - .unwrap(); - let _removal_result = index.track_removal(&relative_path).unwrap(); - }); - }); - - // Benchmark `ResourceIndex::track_modification()` - let modified_file = benchmarks_dir.join("new_file.txt"); - group.bench_function("index_track_modification", |b| { - b.iter(|| { - std::fs::File::create(&modified_file).unwrap(); - std::fs::write(&modified_file, "Hello, World!").unwrap(); - let mut index: ResourceIndex = - ResourceIndex::build(black_box(benchmarks_dir)).unwrap(); - std::fs::write(&modified_file, "Hello, World! Modified").unwrap(); - let relative_path = modified_file - .strip_prefix(benchmarks_dir) - .unwrap() - .to_str() - .unwrap(); - let _modification_result = - index.track_modification(&relative_path).unwrap(); - - // Cleanup - std::fs::remove_file(&modified_file).unwrap(); - }); - }); - // Benchmark `ResourceIndex::update_all()` // First, create a new temp directory specifically for the update_all diff --git a/fs-index/src/index.rs b/fs-index/src/index.rs index 6c36e542..385aa6e7 100644 --- a/fs-index/src/index.rs +++ b/fs-index/src/index.rs @@ -6,7 +6,6 @@ use std::{ time::SystemTime, }; -use anyhow::anyhow; use log; use serde::{Deserialize, Serialize}; use walkdir::WalkDir; @@ -103,21 +102,6 @@ impl IndexedResource { /// let _resource = loaded_index /// .get_resource_by_path("cat.txt") /// .expect("Resource not found"); -/// -/// // Track the removal of a file -/// loaded_index -/// .track_removal(Path::new("cat.txt")) -/// .expect("Failed to track removal"); -/// -/// // Track the addition of a new file -/// loaded_index -/// .track_addition(Path::new("dog.txt")) -/// .expect("Failed to track addition"); -/// -/// // Track the modification of a file -/// loaded_index -/// .track_modification(Path::new("dog.txt")) -/// .expect("Failed to track modification"); /// ``` #[derive(Clone, Debug)] pub struct ResourceIndex @@ -351,151 +335,4 @@ impl ResourceIndex { removed, }) } - - /// Track the addition of a newly added file to the resource index. - /// - /// This method checks if the file exists in the file system. - /// - /// # Arguments - /// * `relative_path` - The path of the file to be added (relative to the - /// root path of the index). - /// - /// # Returns - /// Returns `Ok(resource)` if the file was successfully added to the index. - /// - /// # Errors - /// - If the file does not exist in the file system. - /// - If there was an error calculating the checksum of the file. - pub fn track_addition>( - &mut self, - relative_path: P, - ) -> Result> { - log::debug!("Tracking addition of file: {:?}", relative_path.as_ref()); - - let path = relative_path.as_ref(); - let full_path = self.root.join(path); - if !full_path.exists() { - return Err(ArklibError::Path(format!( - "File does not exist: {:?}", - full_path - ))); - } - let metadata = fs::metadata(&full_path)?; - // empty files don't have content, so we can't compute id - if metadata.len() == 0 { - return Err(ArklibError::Path(format!( - "File is empty: {:?}", - full_path - ))); - } - let last_modified = metadata.modified()?; - let id = Id::from_path(&full_path)?; - - let resource = IndexedResource { - id: id.clone(), - path: path.to_path_buf(), - last_modified, - }; - self.path_to_resource - .insert(resource.path.clone(), resource.clone()); - self.id_to_resources - .entry(id) - .or_default() - .push(resource.clone()); - - Ok(resource) - } - - /// Track the removal of a file from the resource index. - /// - /// This method checks if the file exists in the file system - /// - /// # Arguments - /// * `relative_path` - The path of the file to be removed (relative to the - /// root path of the index). - /// - /// # Returns - /// Returns `Ok(resource)` if the resource was successfully removed from the - /// index. - /// - /// # Errors - /// - If the file still exists in the file system. - /// - If the resource does not exist in the index. - pub fn track_removal>( - &mut self, - relative_path: P, - ) -> Result> { - log::debug!("Tracking removal of file: {:?}", relative_path.as_ref()); - - let path = relative_path.as_ref(); - let full_path = self.root.join(path); - if full_path.exists() { - return Err(ArklibError::Path(format!( - "File still exists: {:?}", - full_path - ))); - } - - // Remove the resource from the index - let resource = self - .path_to_resource - .remove(path) - .ok_or_else(|| anyhow!("Resource not found: {}", path.display()))?; - - // Remove the resource from the id_to_resources map - if let Some(resources) = self.id_to_resources.get_mut(&resource.id) { - resources.retain(|r| r.path != resource.path); - if resources.is_empty() { - self.id_to_resources.remove(&resource.id); - } - } - - Ok(resource) - } - - /// Track the modification of a file in the resource index. - /// - /// This method checks if the file exists in the file system and removes the - /// old resource from the index before adding the new resource to the - /// index. - /// - /// # Arguments - /// * `relative_path` - The relative path of the file to be modified. - /// - /// # Returns - /// Returns `Ok(new_resource)` if the resource was successfully modified in - /// the index. - /// - /// # Errors - /// - If there was a problem removing the old resource from the index. - /// - If there was a problem adding the new resource to the index. - pub fn track_modification>( - &mut self, - relative_path: P, - ) -> Result> { - log::debug!( - "Tracking modification of file: {:?}", - relative_path.as_ref() - ); - - let path = relative_path.as_ref(); - // Remove the resource from the index - let resource = self - .path_to_resource - .remove(path) - .ok_or_else(|| anyhow!("Resource not found: {}", path.display()))?; - - // Remove the resource from the id_to_resources map - if let Some(resources) = self.id_to_resources.get_mut(&resource.id) { - resources.retain(|r| r.path != resource.path); - if resources.is_empty() { - self.id_to_resources.remove(&resource.id); - } - } - - // Add the new resource to the index - let new_resource = self.track_addition(path)?; - - Ok(new_resource) - } } diff --git a/fs-index/src/tests.rs b/fs-index/src/tests.rs index 4c661482..b2601cd0 100644 --- a/fs-index/src/tests.rs +++ b/fs-index/src/tests.rs @@ -275,270 +275,6 @@ fn test_build_index_with_multiple_directories() { assert_eq!(resource, &expected_resource2); } -/// Test tracking the removal of a file from the index. -/// -/// ## Test scenario: -/// - Create two files within the temporary directory. -/// - Build a resource index in the temporary directory. -/// - Assert that the index contains two entries. -/// - Remove one of the files. -/// - Track the removal of the file in the index. -/// - Assert that the index contains only one entry after removal. -/// - Assert that the removed file is no longer present in the index, while the -/// other file remains. -#[test] -fn test_track_removal() { - let temp_dir = TempDir::with_prefix("ark_test_track_removal") - .expect("Failed to create temp dir"); - let root_path = temp_dir.path(); - - let file_path = root_path.join("file.txt"); - fs::write(&file_path, "file content").expect("Failed to write to file"); - let image_path = root_path.join("image.png"); - fs::write(&image_path, "image content").expect("Failed to write to file"); - - let mut index: ResourceIndex = - ResourceIndex::build(root_path).expect("Failed to build index"); - index.store().expect("Failed to store index"); - assert_eq!(index.len(), 2); - - fs::remove_file(&file_path).expect("Failed to remove file"); - - let file_relative_path = file_path - .strip_prefix(root_path) - .expect("Failed to get relative path"); - index - .track_removal(&file_relative_path) - .expect("Failed to track removal"); - - assert_eq!(index.len(), 1); - assert!(index.get_resource_by_path("file.txt").is_none()); - assert!(index.get_resource_by_path("image.png").is_some()); -} - -/// Test tracking the removal of a file that doesn't exist. -/// -/// ## Test scenario: -/// - Create a file within the temporary directory. -/// - Build a resource index in the temporary directory. -/// - Assert that the index contains only one entry. -/// - Track the removal of a file that doesn't exist in the index. -/// - Assert that the index still contains only one entry. -#[test] -fn test_track_removal_non_existent() { - let temp_dir = TempDir::with_prefix("ark_test_track_removal_non_existent") - .expect("Failed to create temp dir"); - let root_path = temp_dir.path(); - - let file_path = root_path.join("file.txt"); - fs::write(&file_path, "file content").expect("Failed to write to file"); - - let mut index: ResourceIndex = - ResourceIndex::build(root_path).expect("Failed to build index"); - index.store().expect("Failed to store index"); - assert_eq!(index.len(), 1); - - let new_file_path = root_path.join("new_file.txt"); - - let new_file_relative_path = new_file_path - .strip_prefix(root_path) - .expect("Failed to get relative path"); - let removal_result = index.track_removal(&new_file_relative_path); - assert!(removal_result.is_err()); - assert_eq!(index.len(), 1); -} - -/// Test tracking the addition of a new file to the index. -/// -/// ## Test scenario: -/// - Create a file within the temporary directory. -/// - Build a resource index in the temporary directory. -/// - Assert that the index initially contains only one entry. -/// - Create a new file in the temporary directory. -/// - Track the addition of the new file in the index. -/// - Assert that the index contains two entries after addition. -/// - Assert that both files are present in the index. -#[test] -fn test_track_addition() { - let temp_dir = TempDir::with_prefix("ark_test_track_addition") - .expect("Failed to create temp dir"); - let root_path = temp_dir.path(); - - let file_path = root_path.join("file.txt"); - fs::write(&file_path, "file content").expect("Failed to write to file"); - - let mut index: ResourceIndex = - ResourceIndex::build(root_path).expect("Failed to build index"); - index.store().expect("Failed to store index"); - assert_eq!(index.len(), 1); - - let new_file_path = root_path.join("new_file.txt"); - fs::write(&new_file_path, "new file content") - .expect("Failed to write to file"); - - let new_file_relative_path = new_file_path - .strip_prefix(root_path) - .expect("Failed to get relative path"); - index - .track_addition(&new_file_relative_path) - .expect("Failed to track addition"); - - assert_eq!(index.len(), 2); - assert!(index.get_resource_by_path("file.txt").is_some()); - assert!(index - .get_resource_by_path("new_file.txt") - .is_some()); -} - -/// Test tracking the addition of an empty file to the index. -/// -/// ## Test scenario: -/// - Create a file within the temporary directory. -/// - Build a resource index in the temporary directory. -/// - Assert that the index initially contains only one entry. -/// - Create a new empty file in the temporary directory. -/// - Track the addition of the new file in the index. -/// - Assert that it retuns an error. -#[test] -fn test_track_addition_empty_file() { - let temp_dir = TempDir::with_prefix("ark_test_track_addition_empty_file") - .expect("Failed to create temp dir"); - let root_path = temp_dir.path(); - - let file_path = root_path.join("file.txt"); - fs::write(&file_path, "file content").expect("Failed to write to file"); - - let mut index: ResourceIndex = - ResourceIndex::build(root_path).expect("Failed to build index"); - index.store().expect("Failed to store index"); - assert_eq!(index.len(), 1); - - let new_file_path = root_path.join("new_file.txt"); - fs::write(&new_file_path, "").expect("Failed to write to file"); - - let new_file_relative_path = new_file_path - .strip_prefix(root_path) - .expect("Failed to get relative path"); - let addition_result = index.track_addition(&new_file_relative_path); - assert!(addition_result.is_err()); -} - -/// Test for tracking addition of a file that doesn't exist -/// -/// ## Test scenario: -/// - Create a file within the temporary directory. -/// - Build a resource index in the temporary directory. -/// - Assert that the index initially contains only one entry. -/// - Track the addition of a file that doesn't exist in the index. -/// - Assert that the index still contains only one entry. -#[test] -fn test_track_addition_non_existent() { - let temp_dir = TempDir::with_prefix("ark_test_track_addition_non_existent") - .expect("Failed to create temp dir"); - let root_path = temp_dir.path(); - - let file_path = root_path.join("file.txt"); - fs::write(&file_path, "file content").expect("Failed to write to file"); - - let mut index: ResourceIndex = - ResourceIndex::build(root_path).expect("Failed to build index"); - index.store().expect("Failed to store index"); - assert_eq!(index.len(), 1); - - let new_file_path = root_path.join("new_file.txt"); - - let new_file_relative_path = new_file_path - .strip_prefix(root_path) - .expect("Failed to get relative path"); - let addition_result = index.track_addition(&new_file_relative_path); - assert!(addition_result.is_err()); - assert_eq!(index.len(), 1); -} - -/// Test tracking the modification of a file in the index. -/// -/// ## Test scenario: -/// - Create a file within the temporary directory. -/// - Build a resource index in the temporary directory. -/// - Assert that the index initially contains only one entry. -/// - Update the content of the file. -/// - Track the modification of the file in the index. -/// - Assert that the index still contains only one entry. -/// - Assert that the modification timestamp of the file in the index matches -/// the actual file's modification timestamp. -#[test] -fn test_track_modification() { - let temp_dir = TempDir::with_prefix("ark_test_track_modification") - .expect("Failed to create temp dir"); - let root_path = temp_dir.path(); - - let file_path = root_path.join("file.txt"); - fs::write(&file_path, "file content").expect("Failed to write to file"); - - let mut index: ResourceIndex = - ResourceIndex::build(root_path).expect("Failed to build index"); - index.store().expect("Failed to store index"); - assert_eq!(index.len(), 1); - - fs::write(&file_path, "updated file content") - .expect("Failed to write to file"); - - let file_relative_path = file_path - .strip_prefix(root_path) - .expect("Failed to get relative path"); - index - .track_modification(&file_relative_path) - .expect("Failed to track modification"); - - assert_eq!(index.len(), 1); - let resource = index - .get_resource_by_path("file.txt") - .expect("Resource not found"); - assert_eq!( - resource.last_modified(), - fs::metadata(&file_path) - .unwrap() - .modified() - .unwrap() - ); -} - -/// Test that track modification does not add a new file to the index. -/// -/// ## Test scenario: -/// - Create a file within the temporary directory. -/// - Build a resource index in the temporary directory. -/// - Assert that the index initially contains only one entry. -/// - Create a new file in the temporary directory. -/// - Track the modification of the new file in the index. -/// - Assert that the index still contains only one entry. -#[test] -fn test_track_modification_does_not_add() { - let temp_dir = - TempDir::with_prefix("ark_test_track_modification_does_not_add") - .expect("Failed to create temp dir"); - let root_path = temp_dir.path(); - - let file_path = root_path.join("file.txt"); - fs::write(&file_path, "file content").expect("Failed to write to file"); - - let mut index: ResourceIndex = - ResourceIndex::build(root_path).expect("Failed to build index"); - index.store().expect("Failed to store index"); - assert_eq!(index.len(), 1); - - let new_file_path = root_path.join("new_file.txt"); - fs::write(&new_file_path, "new file content") - .expect("Failed to write to file"); - - let new_file_relative_path = new_file_path - .strip_prefix(root_path) - .expect("Failed to get relative path"); - - let modification_result = index.track_modification(&new_file_relative_path); - assert!(modification_result.is_err()); -} - /// Test updating the resource index. /// /// ## Test scenario: @@ -629,12 +365,9 @@ fn test_add_colliding_files() { let new_file_path = root_path.join("new_file.txt"); fs::write(&new_file_path, "file content").expect("Failed to write to file"); - let new_file_relative_path = new_file_path - .strip_prefix(root_path) - .expect("Failed to get relative path"); index - .track_addition(&new_file_relative_path) - .expect("Failed to track addition"); + .update_all() + .expect("Failed to update index"); assert_eq!(index.len(), 2); assert_eq!(index.collisions().len(), 1);