forked from mirrors/jj
working_copy: in ignored directories, visit only already tracked paths
`.gitignores` in ignored directories should be ignored. Before this commit, we would visit ignored directories like any others if there were any ignored paths in them. I've done a lot of preparation for this commit, but There's still a bit of duplication between the new code and the existing code. I don't mind improving it if anyone has suggestions. Otherwise I might end up doing that when I get back to working on snapshotting tree-level conflicts soon. This fixes #1785.
This commit is contained in:
parent
bcba1c6682
commit
48b1a1c533
2 changed files with 54 additions and 14 deletions
|
@ -20,6 +20,7 @@ use std::ffi::OsString;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::fs::{File, Metadata, OpenOptions};
|
use std::fs::{File, Metadata, OpenOptions};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
use std::ops::Bound;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use std::os::unix::fs::symlink;
|
use std::os::unix::fs::symlink;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
@ -680,19 +681,59 @@ impl TreeState {
|
||||||
}
|
}
|
||||||
|
|
||||||
if file_type.is_dir() {
|
if file_type.is_dir() {
|
||||||
// If the whole directory is ignored, skip it unless we're already tracking
|
if git_ignore.matches_all_files_in(&path.to_internal_dir_string()) {
|
||||||
// some file in it.
|
// If the whole directory is ignored, visit only paths we're already
|
||||||
if git_ignore.matches_all_files_in(&path.to_internal_dir_string())
|
// tracking.
|
||||||
&& current_tree.path_value(&path).is_none()
|
let tracked_paths = self
|
||||||
{
|
.file_states
|
||||||
continue;
|
.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())
|
||||||
|
})
|
||||||
|
.collect_vec();
|
||||||
|
for (tracked_path, current_file_state) in tracked_paths {
|
||||||
|
if !matcher.matches(&tracked_path) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let disk_path = tracked_path.to_fs_path(&self.working_copy_path);
|
||||||
|
let metadata = match disk_path.metadata() {
|
||||||
|
Ok(metadata) => metadata,
|
||||||
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
return Err(SnapshotError::IoError {
|
||||||
|
message: format!(
|
||||||
|
"Failed to stat file {}",
|
||||||
|
disk_path.display()
|
||||||
|
),
|
||||||
|
err,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(new_file_state) = file_state(&metadata) {
|
||||||
|
deleted_files.remove(&tracked_path);
|
||||||
|
let update = self.get_updated_tree_value(
|
||||||
|
&tracked_path,
|
||||||
|
disk_path,
|
||||||
|
Some(¤t_file_state),
|
||||||
|
¤t_tree,
|
||||||
|
&new_file_state,
|
||||||
|
)?;
|
||||||
|
if let Some(tree_value) = update {
|
||||||
|
tree_builder.set(tracked_path.clone(), tree_value);
|
||||||
|
}
|
||||||
|
self.file_states.insert(tracked_path, new_file_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
work.push(WorkItem {
|
||||||
|
dir: path,
|
||||||
|
disk_dir: entry.path(),
|
||||||
|
git_ignore: git_ignore.clone(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
work.push(WorkItem {
|
|
||||||
dir: path,
|
|
||||||
disk_dir: entry.path(),
|
|
||||||
git_ignore: git_ignore.clone(),
|
|
||||||
});
|
|
||||||
} else if matcher.matches(&path) {
|
} else if matcher.matches(&path) {
|
||||||
if let Some(progress) = progress {
|
if let Some(progress) = progress {
|
||||||
progress(&path);
|
progress(&path);
|
||||||
|
|
|
@ -594,8 +594,7 @@ fn test_gitignores_in_ignored_dir(use_git: bool) {
|
||||||
locked_wc.finish(OperationId::from_hex("abc123")).unwrap();
|
locked_wc.finish(OperationId::from_hex("abc123")).unwrap();
|
||||||
|
|
||||||
let new_tree = test_workspace.snapshot();
|
let new_tree = test_workspace.snapshot();
|
||||||
// TODO(#1785): should be equal
|
assert_eq!(
|
||||||
assert_ne!(
|
|
||||||
new_tree.entries().collect_vec(),
|
new_tree.entries().collect_vec(),
|
||||||
tree2.entries().collect_vec()
|
tree2.entries().collect_vec()
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue