From 8ae5c0d7d66aeccf604bdf86c555c859005d70e2 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 21 Jun 2021 15:08:21 -0600 Subject: [PATCH] Implement worktree::Snapshot::diff Co-Authored-By: Max Brunsfeld --- zed/src/worktree.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/zed/src/worktree.rs b/zed/src/worktree.rs index 7c0b46f5ce..67c2c7429a 100644 --- a/zed/src/worktree.rs +++ b/zed/src/worktree.rs @@ -22,7 +22,7 @@ use postage::{ use smol::{channel::Sender, lock::Mutex as AsyncMutex}; use std::{ cmp, - collections::HashMap, + collections::{HashMap, HashSet}, ffi::{OsStr, OsString}, fmt, fs, future::Future, @@ -621,6 +621,57 @@ impl Snapshot { ignore_stack } + + fn diff(&self, old: &Self) -> Diff { + let mut new = self.entries.cursor::<(), ()>().peekable(); + let mut old = old.entries.cursor::<(), ()>().peekable(); + + let mut diff = Diff::default(); + let mut removed_inodes = HashMap::new(); + let mut added_inodes = HashMap::new(); + + loop { + match (new.peek(), old.peek()) { + (Some(new_entry), Some(old_entry)) => match new_entry.path.cmp(&old_entry.path) { + cmp::Ordering::Equal => { + new.next(); + old.next(); + } + cmp::Ordering::Less => { + added_inodes.insert(new_entry.inode, new_entry.path.clone()); + diff.added.insert(new_entry.path.clone()); + new.next(); + } + cmp::Ordering::Greater => { + removed_inodes.insert(old_entry.path.clone(), old_entry.inode); + diff.removed.insert(old_entry.path.clone()); + old.next(); + } + }, + (Some(new_entry), None) => { + added_inodes.insert(new_entry.inode, new_entry.path.clone()); + diff.added.insert(new_entry.path.clone()); + new.next(); + } + (None, Some(old_entry)) => { + removed_inodes.insert(old_entry.path.clone(), old_entry.inode); + diff.removed.insert(old_entry.path.clone()); + old.next(); + } + (None, None) => break, + } + } + + for (removed_path, inode) in removed_inodes { + if let Some(added_path) = added_inodes.remove(&inode) { + diff.removed.remove(&removed_path); + diff.added.remove(&added_path); + diff.moved.insert(removed_path, added_path); + } + } + + diff + } } impl fmt::Debug for Snapshot { @@ -635,6 +686,14 @@ impl fmt::Debug for Snapshot { } } +#[derive(Default)] +struct Diff { + moved: HashMap, Arc>, + removed: HashSet>, + added: HashSet>, + modified: HashSet>, +} + impl FileHandle { pub fn id(&self) -> u64 { self.state.lock().id