working_copy: extract visit_directory function for snapshotting

This commit is contained in:
Waleed Khan 2023-08-03 08:09:05 -07:00 committed by Martin von Zweigbergk
parent 515fb02049
commit 174704d752

View File

@ -51,6 +51,7 @@ use crate::op_store::{OperationId, WorkspaceId};
use crate::repo_path::{FsPathParseError, RepoPath, RepoPathComponent, RepoPathJoin};
use crate::store::Store;
use crate::tree::{Diff, Tree};
use crate::tree_builder::TreeBuilder;
#[cfg(unix)]
type FileExecutableFlag = bool;
@ -654,23 +655,56 @@ impl TreeState {
git_ignore: base_ignores,
}];
trace_span!("traverse filesystem").in_scope(|| -> Result<(), SnapshotError> {
while let Some(WorkItem {
while let Some(work_item) = work.pop() {
work.extend(self.visit_directory(
&matcher,
&current_tree,
&mut tree_builder,
&mut deleted_files,
work_item,
progress,
)?);
}
Ok(())
})?;
for file in &deleted_files {
self.file_states.remove(file);
tree_builder.remove(file.clone());
}
let has_changes = tree_builder.has_overrides();
self.tree_id = tree_builder.write_tree();
self.watchman_clock = watchman_clock;
Ok(has_changes || fsmonitor_clock_needs_save)
}
fn visit_directory(
&mut self,
matcher: &dyn Matcher,
current_tree: &Tree,
tree_builder: &mut TreeBuilder,
deleted_files: &mut HashSet<RepoPath>,
work_item: WorkItem,
progress: Option<&SnapshotProgress>,
) -> Result<Vec<WorkItem>, SnapshotError> {
let WorkItem {
dir,
disk_dir,
git_ignore,
}) = work.pop()
{
} = work_item;
if matcher.visit(&dir).is_nothing() {
continue;
return Ok(Default::default());
}
let git_ignore = git_ignore
.chain_with_file(&dir.to_internal_dir_string(), disk_dir.join(".gitignore"));
let git_ignore =
git_ignore.chain_with_file(&dir.to_internal_dir_string(), disk_dir.join(".gitignore"));
let mut work = Vec::new();
for maybe_entry in disk_dir.read_dir().unwrap() {
let entry = maybe_entry.unwrap();
let file_type = entry.file_type().unwrap();
let file_name = entry.file_name();
let name =
file_name
let name = file_name
.to_str()
.ok_or_else(|| SnapshotError::InvalidUtf8Path {
path: file_name.clone(),
@ -693,9 +727,7 @@ impl TreeState {
.file_states
.range((Bound::Excluded(&path), Bound::Unbounded))
.take_while(|(sub_path, _)| path.contains(sub_path))
.map(|(sub_path, file_state)| {
(sub_path.clone(), file_state.clone())
})
.map(|(sub_path, file_state)| (sub_path.clone(), file_state.clone()))
.collect_vec();
for (tracked_path, current_file_state) in tracked_paths {
if !matcher.matches(&tracked_path) {
@ -709,10 +741,7 @@ impl TreeState {
}
Err(err) => {
return Err(SnapshotError::IoError {
message: format!(
"Failed to stat file {}",
disk_path.display()
),
message: format!("Failed to stat file {}", disk_path.display()),
err,
});
}
@ -723,7 +752,7 @@ impl TreeState {
&tracked_path,
disk_path,
Some(&current_file_state),
&current_tree,
current_tree,
&new_file_state,
)?;
if let Some(tree_value) = update {
@ -751,12 +780,8 @@ impl TreeState {
// the ignored paths, then
// ignore it.
} else {
let metadata =
entry.metadata().map_err(|err| SnapshotError::IoError {
message: format!(
"Failed to stat file {}",
entry.path().display()
),
let metadata = entry.metadata().map_err(|err| SnapshotError::IoError {
message: format!("Failed to stat file {}", entry.path().display()),
err,
})?;
if let Some(new_file_state) = file_state(&metadata) {
@ -765,7 +790,7 @@ impl TreeState {
&path,
entry.path(),
maybe_current_file_state,
&current_tree,
current_tree,
&new_file_state,
)?;
if let Some(tree_value) = update {
@ -776,18 +801,7 @@ impl TreeState {
}
}
}
}
Ok(())
})?;
for file in &deleted_files {
self.file_states.remove(file);
tree_builder.remove(file.clone());
}
let has_changes = tree_builder.has_overrides();
self.tree_id = tree_builder.write_tree();
self.watchman_clock = watchman_clock;
Ok(has_changes || fsmonitor_clock_needs_save)
Ok(work)
}
#[instrument(skip_all)]