Remove is_ignored from PathEntry and lean more on the tree instead

This commit is contained in:
Antonio Scandurra 2021-04-22 16:49:11 +02:00
parent f3b663e375
commit c429a937be
2 changed files with 95 additions and 46 deletions

View file

@ -244,6 +244,10 @@ impl Snapshot {
self.entries.summary().file_count self.entries.summary().file_count
} }
pub fn visible_file_count(&self) -> usize {
self.entries.summary().visible_file_count
}
pub fn root_entry(&self) -> Option<&Entry> { pub fn root_entry(&self) -> Option<&Entry> {
self.root_inode.and_then(|inode| self.entries.get(&inode)) self.root_inode.and_then(|inode| self.entries.get(&inode))
} }
@ -606,12 +610,7 @@ impl Entry {
fn set_ignored(&mut self, ignored: bool) { fn set_ignored(&mut self, ignored: bool) {
match self { match self {
Entry::Dir { is_ignored, .. } => *is_ignored = Some(ignored), Entry::Dir { is_ignored, .. } => *is_ignored = Some(ignored),
Entry::File { Entry::File { is_ignored, .. } => *is_ignored = Some(ignored),
is_ignored, path, ..
} => {
*is_ignored = Some(ignored);
path.is_ignored = Some(ignored);
}
} }
} }
@ -638,14 +637,25 @@ impl sum_tree::Item for Entry {
type Summary = EntrySummary; type Summary = EntrySummary;
fn summary(&self) -> Self::Summary { fn summary(&self) -> Self::Summary {
let file_count;
let visible_file_count;
if let Entry::File { is_ignored, .. } = self {
file_count = 1;
if is_ignored.unwrap_or(false) {
visible_file_count = 0;
} else {
visible_file_count = 1;
}
} else {
file_count = 0;
visible_file_count = 0;
}
EntrySummary { EntrySummary {
max_ino: self.inode(), max_ino: self.inode(),
file_count: if matches!(self, Self::File { .. }) { file_count,
1 visible_file_count,
} else { recompute_ignore_status: self.is_ignored().is_none(),
0
},
recompute_is_ignored: self.is_ignored().is_none(),
} }
} }
} }
@ -662,14 +672,16 @@ impl sum_tree::KeyedItem for Entry {
pub struct EntrySummary { pub struct EntrySummary {
max_ino: u64, max_ino: u64,
file_count: usize, file_count: usize,
recompute_is_ignored: bool, visible_file_count: usize,
recompute_ignore_status: bool,
} }
impl<'a> AddAssign<&'a EntrySummary> for EntrySummary { impl<'a> AddAssign<&'a EntrySummary> for EntrySummary {
fn add_assign(&mut self, rhs: &'a EntrySummary) { fn add_assign(&mut self, rhs: &'a EntrySummary) {
self.max_ino = rhs.max_ino; self.max_ino = rhs.max_ino;
self.file_count += rhs.file_count; self.file_count += rhs.file_count;
self.recompute_is_ignored |= rhs.recompute_is_ignored; self.visible_file_count += rhs.visible_file_count;
self.recompute_ignore_status |= rhs.recompute_ignore_status;
} }
} }
@ -688,6 +700,15 @@ impl<'a> sum_tree::Dimension<'a, EntrySummary> for FileCount {
} }
} }
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Ord, PartialOrd)]
struct VisibleFileCount(usize);
impl<'a> sum_tree::Dimension<'a, EntrySummary> for VisibleFileCount {
fn add_summary(&mut self, summary: &'a EntrySummary) {
self.0 += summary.visible_file_count;
}
}
struct BackgroundScanner { struct BackgroundScanner {
snapshot: Arc<Mutex<Snapshot>>, snapshot: Arc<Mutex<Snapshot>>,
notify: Sender<ScanState>, notify: Sender<ScanState>,
@ -802,7 +823,7 @@ impl BackgroundScanner {
None, None,
Entry::File { Entry::File {
parent: None, parent: None,
path: PathEntry::new(inode, &relative_path, None), path: PathEntry::new(inode, &relative_path),
inode, inode,
is_symlink, is_symlink,
is_ignored: None, is_ignored: None,
@ -854,7 +875,7 @@ impl BackgroundScanner {
child_name, child_name,
Entry::File { Entry::File {
parent: Some(job.inode), parent: Some(job.inode),
path: PathEntry::new(child_inode, &child_relative_path, None), path: PathEntry::new(child_inode, &child_relative_path),
inode: child_inode, inode: child_inode,
is_symlink: child_is_symlink, is_symlink: child_is_symlink,
is_ignored: None, is_ignored: None,
@ -1046,7 +1067,10 @@ impl BackgroundScanner {
scope.execute(|| { scope.execute(|| {
let entries_tx = entries_tx; let entries_tx = entries_tx;
for entry in snapshot.entries.filter::<_, ()>(|e| e.recompute_is_ignored) { for entry in snapshot
.entries
.filter::<_, ()>(|e| e.recompute_ignore_status)
{
entries_tx.send(entry.clone()).unwrap(); entries_tx.send(entry.clone()).unwrap();
} }
}); });
@ -1110,7 +1134,6 @@ impl BackgroundScanner {
root_path root_path
.parent() .parent()
.map_or(path, |parent| path.strip_prefix(parent).unwrap()), .map_or(path, |parent| path.strip_prefix(parent).unwrap()),
None,
), ),
is_ignored: None, is_ignored: None,
} }

View file

@ -2,7 +2,7 @@ use gpui::scoped_pool;
use crate::sum_tree::SeekBias; use crate::sum_tree::SeekBias;
use super::{char_bag::CharBag, Entry, FileCount, Snapshot}; use super::{char_bag::CharBag, Entry, FileCount, Snapshot, VisibleFileCount};
use std::{ use std::{
cmp::{max, min, Ordering, Reverse}, cmp::{max, min, Ordering, Reverse},
@ -21,11 +21,10 @@ pub struct PathEntry {
pub path_chars: CharBag, pub path_chars: CharBag,
pub path: Arc<[char]>, pub path: Arc<[char]>,
pub lowercase_path: Arc<[char]>, pub lowercase_path: Arc<[char]>,
pub is_ignored: Option<bool>,
} }
impl PathEntry { impl PathEntry {
pub fn new(ino: u64, path: &Path, is_ignored: Option<bool>) -> Self { pub fn new(ino: u64, path: &Path) -> Self {
let path = path.to_string_lossy(); let path = path.to_string_lossy();
let lowercase_path = path.to_lowercase().chars().collect::<Vec<_>>().into(); let lowercase_path = path.to_lowercase().chars().collect::<Vec<_>>().into();
let path: Arc<[char]> = path.chars().collect::<Vec<_>>().into(); let path: Arc<[char]> = path.chars().collect::<Vec<_>>().into();
@ -36,7 +35,6 @@ impl PathEntry {
path_chars, path_chars,
path, path,
lowercase_path, lowercase_path,
is_ignored,
} }
} }
} }
@ -90,7 +88,12 @@ where
let query_chars = CharBag::from(&lowercase_query[..]); let query_chars = CharBag::from(&lowercase_query[..]);
let cpus = num_cpus::get(); let cpus = num_cpus::get();
let path_count: usize = snapshots.clone().map(Snapshot::file_count).sum(); let path_count: usize = if include_ignored {
snapshots.clone().map(Snapshot::file_count).sum()
} else {
snapshots.clone().map(Snapshot::visible_file_count).sum()
};
let segment_size = (path_count + cpus - 1) / cpus; let segment_size = (path_count + cpus - 1) / cpus;
let mut segment_results = (0..cpus).map(|_| BinaryHeap::new()).collect::<Vec<_>>(); let mut segment_results = (0..cpus).map(|_| BinaryHeap::new()).collect::<Vec<_>>();
@ -111,22 +114,15 @@ where
let mut tree_start = 0; let mut tree_start = 0;
for snapshot in trees { for snapshot in trees {
let tree_end = tree_start + snapshot.file_count(); let tree_end = if include_ignored {
tree_start + snapshot.file_count()
} else {
tree_start + snapshot.visible_file_count()
};
if tree_start < segment_end && segment_start < tree_end { if tree_start < segment_end && segment_start < tree_end {
let start = max(tree_start, segment_start) - tree_start; let start = max(tree_start, segment_start) - tree_start;
let end = min(tree_end, segment_end) - tree_start; let end = min(tree_end, segment_end) - tree_start;
let mut cursor = snapshot.entries.cursor::<_, ()>(); let path_entries = path_entries_iter(snapshot, start, end, include_ignored);
cursor.seek(&FileCount(start), SeekBias::Right);
let path_entries = cursor
.filter_map(|e| {
if let Entry::File { path, .. } = e {
Some(path)
} else {
None
}
})
.take(end - start);
let skipped_prefix_len = if include_root_name { let skipped_prefix_len = if include_root_name {
0 0
} else if let Some(Entry::Dir { .. }) = snapshot.root_entry() { } else if let Some(Entry::Dir { .. }) = snapshot.root_entry() {
@ -145,8 +141,7 @@ where
path_entries, path_entries,
query, query,
lowercase_query, lowercase_query,
query_chars.clone(), query_chars,
include_ignored,
smart_case, smart_case,
results, results,
max_results, max_results,
@ -176,6 +171,44 @@ where
results results
} }
fn path_entries_iter<'a>(
snapshot: &'a Snapshot,
start: usize,
end: usize,
include_ignored: bool,
) -> impl Iterator<Item = &'a PathEntry> {
let mut files_cursor = None;
let mut visible_files_cursor = None;
if include_ignored {
let mut cursor = snapshot.entries.cursor::<_, ()>();
cursor.seek(&FileCount(start), SeekBias::Right);
files_cursor = Some(cursor);
} else {
let mut cursor = snapshot.entries.cursor::<_, ()>();
cursor.seek(&VisibleFileCount(start), SeekBias::Right);
visible_files_cursor = Some(cursor);
}
files_cursor
.into_iter()
.flatten()
.chain(visible_files_cursor.into_iter().flatten())
.filter_map(move |e| {
if let Entry::File {
path, is_ignored, ..
} = e
{
if is_ignored.unwrap_or(false) && !include_ignored {
None
} else {
Some(path)
}
} else {
None
}
})
.take(end - start)
}
fn match_single_tree_paths<'a>( fn match_single_tree_paths<'a>(
snapshot: &Snapshot, snapshot: &Snapshot,
skipped_prefix_len: usize, skipped_prefix_len: usize,
@ -183,7 +216,6 @@ fn match_single_tree_paths<'a>(
query: &[char], query: &[char],
lowercase_query: &[char], lowercase_query: &[char],
query_chars: CharBag, query_chars: CharBag,
include_ignored: bool,
smart_case: bool, smart_case: bool,
results: &mut BinaryHeap<Reverse<PathMatch>>, results: &mut BinaryHeap<Reverse<PathMatch>>,
max_results: usize, max_results: usize,
@ -194,11 +226,7 @@ fn match_single_tree_paths<'a>(
best_position_matrix: &mut Vec<usize>, best_position_matrix: &mut Vec<usize>,
) { ) {
for path_entry in path_entries { for path_entry in path_entries {
if !path_entry.path_chars.is_superset(query_chars.clone()) { if !path_entry.path_chars.is_superset(query_chars) {
continue;
}
if !include_ignored && path_entry.is_ignored.unwrap_or(false) {
continue; continue;
} }
@ -502,7 +530,6 @@ mod tests {
path_chars, path_chars,
path, path,
lowercase_path, lowercase_path,
is_ignored: Some(false),
}); });
} }
@ -526,7 +553,6 @@ mod tests {
&query[..], &query[..],
&lowercase_query[..], &lowercase_query[..],
query_chars, query_chars,
true,
smart_case, smart_case,
&mut results, &mut results,
100, 100,