diff --git a/zed/src/worktree.rs b/zed/src/worktree.rs index 5d5e7b5742..6e8f5c6dc7 100644 --- a/zed/src/worktree.rs +++ b/zed/src/worktree.rs @@ -299,45 +299,33 @@ impl Snapshot { 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()) { - Some(e) => e, - None => return, - }; + fn remove_subtree(&mut self, subtree_inode: u64) { + let entry = self.entries.get(&subtree_inode).unwrap(); let mut edits = Vec::new(); - let parent_inode = parent_entry.inode(); - let mut entry_inode = None; - if let Entry::Dir { children, .. } = &mut parent_entry { - let mut new_children = Vec::new(); - for (child_inode, child_name) in children.as_ref() { - if Some(child_name.as_ref()) == path.file_name() { - entry_inode = Some(*child_inode); - } else { - new_children.push((*child_inode, child_name.clone())); - } - } - if new_children.iter().any(|c| Some(c.0) == entry_inode) { - entry_inode = None; + // Update the parent entry to not include this subtree as one of its children. + if let Some(parent_inode) = entry.parent() { + let mut parent_entry = self.entries.get(&parent_inode).unwrap().clone(); + if let Entry::Dir { children, .. } = &mut parent_entry { + *children = children + .into_iter() + .filter(|(child_inode, _)| *child_inode != subtree_inode) + .cloned() + .collect::>() + .into(); + } else { + unreachable!("parent was not a directory"); } - - *children = new_children.into(); edits.push(Edit::Insert(parent_entry)); } - if let Some(entry_inode) = entry_inode { - let mut descendant_stack = Vec::new(); - descendant_stack.push((entry_inode, parent_inode)); - while let Some((inode, parent_inode)) = descendant_stack.pop() { - if let Some(entry) = self.entries.get(&inode) { - if entry.parent() == Some(parent_inode) { - edits.push(Edit::Remove(inode)); - if let Entry::Dir { children, .. } = entry { - descendant_stack.extend(children.iter().map(|c| (c.0, entry.inode()))); - } - } - } + // Remove all descendant entries for this subtree. + let mut stack = vec![subtree_inode]; + while let Some(inode) = stack.pop() { + edits.push(Edit::Remove(inode)); + if let Entry::Dir { children, .. } = self.entries.get(&inode).unwrap() { + stack.extend(children.iter().map(|(child_inode, _)| *child_inode)); } } @@ -729,7 +717,9 @@ impl BackgroundScanner { paths.next(); } - snapshot.remove_entry(&relative_path); + if let Some(inode) = snapshot.inode_for_path(&relative_path) { + snapshot.remove_subtree(inode); + } match self.fs_entry_for_path(&root_path, &path) { Ok(Some((fs_entry, ignore))) => {