Use entry_id on File instead of worktree::Diff to detect when buffers' files change

Rather than computing a diff after processing a batch of FSEvents, we instead detect renames as we're inserting entries. We store an entry_id on the File object that is owned by each buffer, and use this to detect when the path of the File has changed.

We now also manage all File-related state and event emission for Buffers in the LocalWorktree, since the logic will need to be totally different in the remote case.

Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-Authored-By: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
Nathan Sobo
2021-06-29 18:19:38 -06:00
co-authored by Max Brunsfeld Antonio Scandurra
parent e80439daaa
commit 34963ac80d
7 changed files with 396 additions and 553 deletions
+12 -8
View File
@@ -6,7 +6,7 @@ use crate::{
language::LanguageRegistry,
rpc,
settings::Settings,
worktree::{File, Worktree, WorktreeHandle},
worktree::{File, Worktree},
AppState,
};
use anyhow::{anyhow, Result};
@@ -394,7 +394,7 @@ impl Workspace {
let entries = abs_paths
.iter()
.cloned()
.map(|path| self.file_for_path(&path, cx))
.map(|path| self.entry_id_for_path(&path, cx))
.collect::<Vec<_>>();
let bg = cx.background_executor().clone();
@@ -402,12 +402,11 @@ impl Workspace {
.iter()
.cloned()
.zip(entries.into_iter())
.map(|(abs_path, file)| {
.map(|(abs_path, entry_id)| {
let is_file = bg.spawn(async move { abs_path.is_file() });
cx.spawn(|this, mut cx| async move {
if is_file.await {
return this
.update(&mut cx, |this, cx| this.open_entry(file.entry_id(), cx));
return this.update(&mut cx, |this, cx| this.open_entry(entry_id, cx));
} else {
None
}
@@ -440,18 +439,22 @@ impl Workspace {
(self.add_worktree(abs_path, cx), PathBuf::new())
}
fn file_for_path(&mut self, abs_path: &Path, cx: &mut ViewContext<Self>) -> File {
fn entry_id_for_path(
&mut self,
abs_path: &Path,
cx: &mut ViewContext<Self>,
) -> (usize, Arc<Path>) {
for tree in self.worktrees.iter() {
if let Some(relative_path) = tree
.read(cx)
.as_local()
.and_then(|t| abs_path.strip_prefix(t.abs_path()).ok())
{
return tree.file(relative_path);
return (tree.id(), relative_path.into());
}
}
let worktree = self.add_worktree(&abs_path, cx);
worktree.file(Path::new(""))
(worktree.id(), Path::new("").into())
}
pub fn add_worktree(
@@ -880,6 +883,7 @@ mod tests {
use crate::{
editor::Editor,
test::{build_app_state, temp_tree},
worktree::WorktreeHandle,
};
use serde_json::json;
use std::{collections::HashSet, fs};