From 37d9aae8943ae4256c72cd72056ea2eb64366b37 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Tue, 25 Jul 2023 21:41:19 -0700 Subject: [PATCH] working_copy: handle ignored files outside of `get_updated_file_state()` I want to replace the `DirEntry` argument to `get_updated_file_state()` by a `PathBuf` and a `Metadata`. To avoid always reading the metadata, we need to check for ignored files outside of `get_updated_file_state()`. I also think that gives the call site a nice symmetry in how we use the `git_ignore` for directories (`.matches_all_files_in()`)) and files (`.matches_file()`). --- lib/src/working_copy.rs | 55 +++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/lib/src/working_copy.rs b/lib/src/working_copy.rs index b74f26b8c..11f961de1 100644 --- a/lib/src/working_copy.rs +++ b/lib/src/working_copy.rs @@ -409,7 +409,6 @@ pub enum TreeStateError { } enum UpdatedFileState { - Ignored, Unchanged(FileState), Deleted, Changed(TreeValue, FileState), @@ -706,24 +705,31 @@ impl TreeState { if let Some(progress) = progress { progress(&sub_path); } - let update = self.get_updated_file_state( - &sub_path, - &entry, - git_ignore.as_ref(), - ¤t_tree, - )?; - match update { - UpdatedFileState::Ignored => {} - UpdatedFileState::Unchanged(file_state) => { - self.file_states.insert(sub_path, file_state); - } - UpdatedFileState::Deleted => { - self.file_states.remove(&sub_path); - tree_builder.remove(sub_path); - } - UpdatedFileState::Changed(tree_value, file_state) => { - self.file_states.insert(sub_path.clone(), file_state); - tree_builder.set(sub_path, tree_value); + let maybe_current_file_state = self.file_states.get(&sub_path); + if maybe_current_file_state.is_none() + && git_ignore.matches_file(&sub_path.to_internal_file_string()) + { + // If it wasn't already tracked and it matches the ignored paths, then + // ignore it. + } else { + let update = self.get_updated_file_state( + &sub_path, + &entry, + maybe_current_file_state, + ¤t_tree, + )?; + match update { + UpdatedFileState::Unchanged(file_state) => { + self.file_states.insert(sub_path, file_state); + } + UpdatedFileState::Deleted => { + self.file_states.remove(&sub_path); + tree_builder.remove(sub_path); + } + UpdatedFileState::Changed(tree_value, file_state) => { + self.file_states.insert(sub_path.clone(), file_state); + tree_builder.set(sub_path, tree_value); + } } } } @@ -800,18 +806,9 @@ impl TreeState { &self, repo_path: &RepoPath, dir_entry: &DirEntry, - git_ignore: &GitIgnoreFile, + maybe_current_file_state: Option<&FileState>, current_tree: &Tree, ) -> Result { - let maybe_current_file_state = self.file_states.get(repo_path); - if maybe_current_file_state.is_none() - && git_ignore.matches_file(&repo_path.to_internal_file_string()) - { - // If it wasn't already tracked and it matches the ignored paths, then - // ignore it. - return Ok(UpdatedFileState::Ignored); - } - let disk_path = dir_entry.path(); let metadata = dir_entry.metadata().map_err(|err| SnapshotError::IoError { message: format!("Failed to stat file {}", disk_path.display()),