mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-03 08:54:04 +00:00
Perform path matching on Worktree snapshots
We're going to need something that can be moved to a background thread. Worktree used to be easy to clone, but that's no longer really true. Instead we can take a snapshot.
This commit is contained in:
parent
e55abc4220
commit
5648c67d54
2 changed files with 45 additions and 15 deletions
|
@ -2,7 +2,7 @@ mod char_bag;
|
|||
mod fuzzy;
|
||||
|
||||
use crate::{
|
||||
editor::Snapshot,
|
||||
editor::Snapshot as BufferSnapshot,
|
||||
sum_tree::{self, Edit, SumTree},
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
|
@ -50,6 +50,12 @@ pub struct Worktree {
|
|||
poll_scheduled: bool,
|
||||
}
|
||||
|
||||
pub struct Snapshot {
|
||||
id: usize,
|
||||
root_inode: Option<u64>,
|
||||
entries: SumTree<Entry>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FileHandle {
|
||||
worktree: ModelHandle<Worktree>,
|
||||
|
@ -57,7 +63,7 @@ pub struct FileHandle {
|
|||
}
|
||||
|
||||
impl Worktree {
|
||||
fn new(path: impl Into<Arc<Path>>, ctx: &mut ModelContext<Self>) -> Self {
|
||||
pub fn new(path: impl Into<Arc<Path>>, ctx: &mut ModelContext<Self>) -> Self {
|
||||
let path = path.into();
|
||||
let scan_state = smol::channel::unbounded();
|
||||
let scanner = BackgroundScanner::new(path.clone(), scan_state.0);
|
||||
|
@ -79,6 +85,14 @@ impl Worktree {
|
|||
tree
|
||||
}
|
||||
|
||||
pub fn snapshot(&self) -> Snapshot {
|
||||
Snapshot {
|
||||
id: self.id,
|
||||
root_inode: self.root_inode(),
|
||||
entries: self.entries.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn observe_scan_state(&mut self, scan_state: ScanState, ctx: &mut ModelContext<Self>) {
|
||||
self.scan_state = scan_state;
|
||||
self.poll_entries(ctx);
|
||||
|
@ -195,7 +209,12 @@ impl Worktree {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn save<'a>(&self, ino: u64, content: Snapshot, ctx: &AppContext) -> Task<Result<()>> {
|
||||
pub fn save<'a>(
|
||||
&self,
|
||||
ino: u64,
|
||||
content: BufferSnapshot,
|
||||
ctx: &AppContext,
|
||||
) -> Task<Result<()>> {
|
||||
let path = self.abs_path_for_inode(ino);
|
||||
eprintln!("save to path: {:?}", path);
|
||||
ctx.background_executor().spawn(async move {
|
||||
|
@ -250,6 +269,16 @@ impl fmt::Debug for Worktree {
|
|||
}
|
||||
}
|
||||
|
||||
impl Snapshot {
|
||||
pub fn file_count(&self) -> usize {
|
||||
self.entries.summary().file_count
|
||||
}
|
||||
|
||||
pub fn root_entry(&self) -> Option<&Entry> {
|
||||
self.root_inode.and_then(|inode| self.entries.get(&inode))
|
||||
}
|
||||
}
|
||||
|
||||
impl FileHandle {
|
||||
pub fn path(&self, ctx: &AppContext) -> PathBuf {
|
||||
self.worktree
|
||||
|
@ -262,7 +291,7 @@ impl FileHandle {
|
|||
self.worktree.read(ctx).load_file(self.inode, ctx)
|
||||
}
|
||||
|
||||
pub fn save<'a>(&self, content: Snapshot, ctx: &AppContext) -> Task<Result<()>> {
|
||||
pub fn save<'a>(&self, content: BufferSnapshot, ctx: &AppContext) -> Task<Result<()>> {
|
||||
let worktree = self.worktree.read(ctx);
|
||||
worktree.save(self.inode, content, ctx)
|
||||
}
|
||||
|
@ -397,6 +426,7 @@ impl BackgroundScanner {
|
|||
Duration::from_millis(100),
|
||||
|events| {
|
||||
eprintln!("events: {:?}", events);
|
||||
true
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -640,7 +670,7 @@ mod tests {
|
|||
app.read(|ctx| {
|
||||
let tree = tree.read(ctx);
|
||||
let results = match_paths(
|
||||
Some(tree).into_iter(),
|
||||
Some(tree.snapshot()).iter(),
|
||||
"bna",
|
||||
false,
|
||||
false,
|
||||
|
|
|
@ -2,7 +2,7 @@ use gpui::scoped_pool;
|
|||
|
||||
use crate::sum_tree::SeekBias;
|
||||
|
||||
use super::{char_bag::CharBag, Entry, FileCount, Worktree};
|
||||
use super::{char_bag::CharBag, Entry, FileCount, Snapshot, Worktree};
|
||||
|
||||
use std::{
|
||||
cmp::{max, min, Ordering, Reverse},
|
||||
|
@ -71,7 +71,7 @@ impl Ord for PathMatch {
|
|||
}
|
||||
|
||||
pub fn match_paths<'a, T>(
|
||||
trees: T,
|
||||
snapshots: T,
|
||||
query: &str,
|
||||
include_root_name: bool,
|
||||
include_ignored: bool,
|
||||
|
@ -80,7 +80,7 @@ pub fn match_paths<'a, T>(
|
|||
pool: scoped_pool::Pool,
|
||||
) -> Vec<PathMatch>
|
||||
where
|
||||
T: Clone + Send + Iterator<Item = &'a Worktree>,
|
||||
T: Clone + Send + Iterator<Item = &'a Snapshot>,
|
||||
{
|
||||
let lowercase_query = query.to_lowercase().chars().collect::<Vec<_>>();
|
||||
let query = query.chars().collect::<Vec<_>>();
|
||||
|
@ -89,13 +89,13 @@ where
|
|||
let query_chars = CharBag::from(&lowercase_query[..]);
|
||||
|
||||
let cpus = num_cpus::get();
|
||||
let path_count: usize = trees.clone().map(Worktree::file_count).sum();
|
||||
let path_count: usize = snapshots.clone().map(Snapshot::file_count).sum();
|
||||
let segment_size = (path_count + cpus - 1) / cpus;
|
||||
let mut segment_results = (0..cpus).map(|_| BinaryHeap::new()).collect::<Vec<_>>();
|
||||
|
||||
pool.scoped(|scope| {
|
||||
for (segment_idx, results) in segment_results.iter_mut().enumerate() {
|
||||
let trees = trees.clone();
|
||||
let trees = snapshots.clone();
|
||||
scope.execute(move || {
|
||||
let segment_start = segment_idx * segment_size;
|
||||
let segment_end = segment_start + segment_size;
|
||||
|
@ -109,12 +109,12 @@ where
|
|||
let mut best_position_matrix = Vec::new();
|
||||
|
||||
let mut tree_start = 0;
|
||||
for tree in trees {
|
||||
let tree_end = tree_start + tree.file_count();
|
||||
for snapshot in trees {
|
||||
let tree_end = tree_start + snapshot.file_count();
|
||||
if tree_start < segment_end && segment_start < tree_end {
|
||||
let start = max(tree_start, segment_start) - tree_start;
|
||||
let end = min(tree_end, segment_end) - tree_start;
|
||||
let mut cursor = tree.entries.cursor::<_, ()>();
|
||||
let mut cursor = snapshot.entries.cursor::<_, ()>();
|
||||
cursor.seek(&FileCount(start), SeekBias::Right);
|
||||
let path_entries = cursor
|
||||
.filter_map(|e| {
|
||||
|
@ -128,7 +128,7 @@ where
|
|||
|
||||
let skipped_prefix_len = if include_root_name {
|
||||
0
|
||||
} else if let Some(Entry::Dir { name, .. }) = tree.root_entry() {
|
||||
} else if let Some(Entry::Dir { name, .. }) = snapshot.root_entry() {
|
||||
let name = name.to_string_lossy();
|
||||
if name == "/" {
|
||||
1
|
||||
|
@ -140,7 +140,7 @@ where
|
|||
};
|
||||
|
||||
match_single_tree_paths(
|
||||
tree.id,
|
||||
snapshot.id,
|
||||
skipped_prefix_len,
|
||||
path_entries,
|
||||
query,
|
||||
|
|
Loading…
Reference in a new issue