💄 process_events

This commit is contained in:
Max Brunsfeld 2021-04-19 13:19:34 -07:00
parent e44a59dc7d
commit f06164ade9

View file

@ -208,6 +208,11 @@ impl Snapshot {
self.path.file_name() self.path.file_name()
} }
fn entry_for_path(&self, path: impl AsRef<Path>) -> Option<&Entry> {
self.inode_for_path(path)
.and_then(|inode| self.entries.get(&inode))
}
fn inode_for_path(&self, path: impl AsRef<Path>) -> Option<u64> { fn inode_for_path(&self, path: impl AsRef<Path>) -> Option<u64> {
let path = path.as_ref(); let path = path.as_ref();
self.root_inode.and_then(|mut inode| { self.root_inode.and_then(|mut inode| {
@ -226,38 +231,53 @@ impl Snapshot {
}) })
} }
fn entry_for_path(&self, path: impl AsRef<Path>) -> Option<&Entry> { pub fn path_for_inode(&self, mut inode: u64, include_root: bool) -> Result<PathBuf> {
self.inode_for_path(path)
.and_then(|inode| self.entries.get(&inode))
}
pub fn path_for_inode(&self, mut ino: u64, include_root: bool) -> Result<PathBuf> {
let mut components = Vec::new(); let mut components = Vec::new();
let mut entry = self let mut entry = self
.entries .entries
.get(&ino) .get(&inode)
.ok_or_else(|| anyhow!("entry does not exist in worktree"))?; .ok_or_else(|| anyhow!("entry does not exist in worktree"))?;
while let Some(parent) = entry.parent() { while let Some(parent) = entry.parent() {
entry = self.entries.get(&parent).unwrap(); entry = self.entries.get(&parent).unwrap();
if let Entry::Dir { children, .. } = entry { if let Entry::Dir { children, .. } = entry {
let (_, child_name) = children let (_, child_name) = children
.iter() .iter()
.find(|(child_inode, _)| *child_inode == ino) .find(|(child_inode, _)| *child_inode == inode)
.unwrap(); .unwrap();
components.push(child_name.as_ref()); components.push(child_name.as_ref());
ino = parent; inode = parent;
} else { } else {
unreachable!(); unreachable!();
} }
} }
if include_root { if include_root {
components.push(self.path.file_name().unwrap()); components.push(self.root_name().unwrap());
} }
Ok(components.into_iter().rev().collect()) Ok(components.into_iter().rev().collect())
} }
fn remove_path(&mut self, path: &Path) { fn insert_entry(&mut self, path: &Path, entry: Entry) {
let mut edits = Vec::new();
edits.push(Edit::Insert(entry.clone()));
if let Some(parent) = entry.parent() {
let mut parent_entry = self.entries.get(&parent).unwrap().clone();
if let Entry::Dir { children, .. } = &mut parent_entry {
let name = Arc::from(path.file_name().unwrap());
*children = children
.into_iter()
.cloned()
.chain(Some((entry.inode(), name)))
.collect::<Vec<_>>()
.into();
edits.push(Edit::Insert(parent_entry));
} else {
unreachable!();
}
}
self.entries.edit(edits);
}
fn remove_entry(&mut self, path: &Path) {
let mut parent_entry = match path.parent().and_then(|p| self.entry_for_path(p).cloned()) { let mut parent_entry = match path.parent().and_then(|p| self.entry_for_path(p).cloned()) {
Some(e) => e, Some(e) => e,
None => return, None => return,
@ -687,7 +707,7 @@ impl BackgroundScanner {
let relative_path = match path.strip_prefix(&snapshot.path) { let relative_path = match path.strip_prefix(&snapshot.path) {
Ok(relative_path) => relative_path.to_path_buf(), Ok(relative_path) => relative_path.to_path_buf(),
Err(e) => { Err(e) => {
log::error!("Unexpected event {:?}", e); log::error!("unexpected event {:?}", e);
continue; continue;
} }
}; };
@ -696,40 +716,21 @@ impl BackgroundScanner {
paths.next(); paths.next();
} }
snapshot.remove_path(&relative_path); snapshot.remove_entry(&relative_path);
match self.fs_entry_for_path(&snapshot.path, &path) { match self.fs_entry_for_path(&snapshot.path, &path) {
Ok(Some((fs_entry, ignore))) => { Ok(Some((fs_entry, ignore))) => {
let mut edits = Vec::new(); snapshot.insert_entry(&path, fs_entry.clone());
edits.push(Edit::Insert(fs_entry.clone()));
if let Some(parent) = fs_entry.parent() {
let mut parent_entry = snapshot.entries.get(&parent).unwrap().clone();
if let Entry::Dir { children, .. } = &mut parent_entry {
let name = Arc::from(path.file_name().unwrap());
*children = children
.into_iter()
.cloned()
.chain(Some((fs_entry.inode(), name)))
.collect::<Vec<_>>()
.into();
edits.push(Edit::Insert(parent_entry));
} else {
unreachable!();
}
}
snapshot.entries.edit(edits);
if fs_entry.is_dir() { if fs_entry.is_dir() {
let relative_path = snapshot
.path
.parent()
.map_or(path.as_path(), |parent| path.strip_prefix(parent).unwrap())
.to_path_buf();
scan_queue_tx scan_queue_tx
.send(Ok(ScanJob { .send(Ok(ScanJob {
inode: fs_entry.inode(), inode: fs_entry.inode(),
path: Arc::from(path), path: Arc::from(path),
relative_path, relative_path: snapshot
.root_name()
.map_or(PathBuf::new(), PathBuf::from)
.join(relative_path),
dir_entry: fs_entry, dir_entry: fs_entry,
ignore: Some(ignore), ignore: Some(ignore),
scan_queue: scan_queue_tx.clone(), scan_queue: scan_queue_tx.clone(),
@ -740,14 +741,14 @@ impl BackgroundScanner {
Ok(None) => {} Ok(None) => {}
Err(err) => { Err(err) => {
// TODO - create a special 'error' entry in the entries tree to mark this // TODO - create a special 'error' entry in the entries tree to mark this
log::error!("Error reading file on event {:?}", err); log::error!("error reading file on event {:?}", err);
} }
} }
} }
*self.snapshot.lock() = snapshot; *self.snapshot.lock() = snapshot;
// Scan any directories that were moved into this worktree as part of this event batch. // Scan any directories that were created as part of this event batch.
drop(scan_queue_tx); drop(scan_queue_tx);
self.thread_pool.scoped(|pool| { self.thread_pool.scoped(|pool| {
for _ in 0..self.thread_pool.workers() { for _ in 0..self.thread_pool.workers() {