mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-03 08:54:04 +00:00
Recompute the PathEntry for each file under a re-parented subtree
This commit is contained in:
parent
ca62d01b53
commit
f29c42904e
1 changed files with 58 additions and 18 deletions
|
@ -255,7 +255,7 @@ impl Snapshot {
|
||||||
fn reparent_entry(
|
fn reparent_entry(
|
||||||
&mut self,
|
&mut self,
|
||||||
child_inode: u64,
|
child_inode: u64,
|
||||||
new_filename: Option<&OsStr>,
|
new_path: Option<&Path>,
|
||||||
old_parent_inode: Option<u64>,
|
old_parent_inode: Option<u64>,
|
||||||
new_parent_inode: Option<u64>,
|
new_parent_inode: Option<u64>,
|
||||||
) {
|
) {
|
||||||
|
@ -282,11 +282,11 @@ impl Snapshot {
|
||||||
let mut old_parent_entry = None;
|
let mut old_parent_entry = None;
|
||||||
let mut new_parent_entry = None;
|
let mut new_parent_entry = None;
|
||||||
for removed_entry in removed_entries {
|
for removed_entry in removed_entries {
|
||||||
if removed_entry.ino() == child_inode {
|
if removed_entry.inode() == child_inode {
|
||||||
child_entry = Some(removed_entry);
|
child_entry = Some(removed_entry);
|
||||||
} else if Some(removed_entry.ino()) == old_parent_inode {
|
} else if Some(removed_entry.inode()) == old_parent_inode {
|
||||||
old_parent_entry = Some(removed_entry);
|
old_parent_entry = Some(removed_entry);
|
||||||
} else if Some(removed_entry.ino()) == new_parent_inode {
|
} else if Some(removed_entry.inode()) == new_parent_inode {
|
||||||
new_parent_entry = Some(removed_entry);
|
new_parent_entry = Some(removed_entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,12 +294,47 @@ impl Snapshot {
|
||||||
// Update the child entry's parent.
|
// Update the child entry's parent.
|
||||||
let mut child_entry = child_entry.expect("cannot reparent non-existent entry");
|
let mut child_entry = child_entry.expect("cannot reparent non-existent entry");
|
||||||
child_entry.set_parent(new_parent_inode);
|
child_entry.set_parent(new_parent_inode);
|
||||||
if let Some(new_filename) = new_filename {
|
if let Some(new_path) = new_path {
|
||||||
child_entry.set_name(new_filename);
|
let new_path = new_path.strip_prefix(self.path.parent().unwrap()).unwrap();
|
||||||
}
|
child_entry.set_name(new_path.file_name().unwrap());
|
||||||
insertions.push(Edit::Insert(child_entry));
|
|
||||||
|
|
||||||
// Remove the child entry from it's old parent's children.
|
// Recompute the PathEntry for each file under this subtree.
|
||||||
|
let mut stack = Vec::new();
|
||||||
|
stack.push((child_entry, new_path.parent().unwrap().to_path_buf()));
|
||||||
|
while let Some((mut entry, mut new_path)) = stack.pop() {
|
||||||
|
new_path.push(entry.name());
|
||||||
|
match &mut entry {
|
||||||
|
Entry::Dir {
|
||||||
|
children, inode, ..
|
||||||
|
} => {
|
||||||
|
for child_inode in children.as_ref() {
|
||||||
|
let child_entry = self.entries.get(child_inode).unwrap();
|
||||||
|
stack.push((child_entry.clone(), new_path.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Descendant directories don't need to be mutated because their properties
|
||||||
|
// haven't changed, so only re-insert this directory if it is the entry we
|
||||||
|
// were reparenting.
|
||||||
|
if *inode == child_inode {
|
||||||
|
insertions.push(Edit::Insert(entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Entry::File {
|
||||||
|
inode,
|
||||||
|
is_ignored,
|
||||||
|
path,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
*path = PathEntry::new(*inode, &new_path, *is_ignored);
|
||||||
|
insertions.push(Edit::Insert(entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
insertions.push(Edit::Insert(child_entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the child entry from its old parent's children.
|
||||||
if let Some(mut old_parent_entry) = old_parent_entry {
|
if let Some(mut old_parent_entry) = old_parent_entry {
|
||||||
if let Entry::Dir { children, .. } = &mut old_parent_entry {
|
if let Entry::Dir { children, .. } = &mut old_parent_entry {
|
||||||
*children = children
|
*children = children
|
||||||
|
@ -313,7 +348,7 @@ impl Snapshot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the child entry to it's new parent's children.
|
// Add the child entry to its new parent's children.
|
||||||
if let Some(mut new_parent_entry) = new_parent_entry {
|
if let Some(mut new_parent_entry) = new_parent_entry {
|
||||||
if let Entry::Dir { children, .. } = &mut new_parent_entry {
|
if let Entry::Dir { children, .. } = &mut new_parent_entry {
|
||||||
*children = children
|
*children = children
|
||||||
|
@ -410,7 +445,7 @@ pub enum Entry {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entry {
|
impl Entry {
|
||||||
fn ino(&self) -> u64 {
|
fn inode(&self) -> u64 {
|
||||||
match self {
|
match self {
|
||||||
Entry::Dir { inode, .. } => *inode,
|
Entry::Dir { inode, .. } => *inode,
|
||||||
Entry::File { inode, .. } => *inode,
|
Entry::File { inode, .. } => *inode,
|
||||||
|
@ -455,7 +490,7 @@ impl sum_tree::Item for Entry {
|
||||||
|
|
||||||
fn summary(&self) -> Self::Summary {
|
fn summary(&self) -> Self::Summary {
|
||||||
EntrySummary {
|
EntrySummary {
|
||||||
max_ino: self.ino(),
|
max_ino: self.inode(),
|
||||||
file_count: if matches!(self, Self::File { .. }) {
|
file_count: if matches!(self, Self::File { .. }) {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
|
@ -469,7 +504,7 @@ impl sum_tree::KeyedItem for Entry {
|
||||||
type Key = u64;
|
type Key = u64;
|
||||||
|
|
||||||
fn key(&self) -> Self::Key {
|
fn key(&self) -> Self::Key {
|
||||||
self.ino()
|
self.inode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -753,13 +788,13 @@ impl BackgroundScanner {
|
||||||
// If this path currently exists on the filesystem, then ensure that the snapshot's
|
// If this path currently exists on the filesystem, then ensure that the snapshot's
|
||||||
// entry for this path is up-to-date.
|
// entry for this path is up-to-date.
|
||||||
Ok(Some((fs_entry, ignore))) => {
|
Ok(Some((fs_entry, ignore))) => {
|
||||||
let fs_inode = fs_entry.ino();
|
let fs_inode = fs_entry.inode();
|
||||||
let fs_parent_inode = fs_entry.parent();
|
let fs_parent_inode = fs_entry.parent();
|
||||||
|
|
||||||
// If the snapshot already contains an entry for this path, then ensure that the
|
// If the snapshot already contains an entry for this path, then ensure that the
|
||||||
// entry has the correct inode and parent.
|
// entry has the correct inode and parent.
|
||||||
if let Some(snapshot_entry) = snapshot_entry {
|
if let Some(snapshot_entry) = snapshot_entry {
|
||||||
let snapshot_inode = snapshot_entry.ino();
|
let snapshot_inode = snapshot_entry.inode();
|
||||||
let snapshot_parent_inode = snapshot_entry.parent();
|
let snapshot_parent_inode = snapshot_entry.parent();
|
||||||
|
|
||||||
// If the snapshot entry already matches the filesystem, then skip to the
|
// If the snapshot entry already matches the filesystem, then skip to the
|
||||||
|
@ -781,7 +816,7 @@ impl BackgroundScanner {
|
||||||
let snapshot_parent_inode = snapshot_entry_for_inode.parent();
|
let snapshot_parent_inode = snapshot_entry_for_inode.parent();
|
||||||
snapshot.reparent_entry(
|
snapshot.reparent_entry(
|
||||||
fs_inode,
|
fs_inode,
|
||||||
path.file_name(),
|
Some(&path),
|
||||||
snapshot_parent_inode,
|
snapshot_parent_inode,
|
||||||
fs_parent_inode,
|
fs_parent_inode,
|
||||||
);
|
);
|
||||||
|
@ -825,7 +860,7 @@ impl BackgroundScanner {
|
||||||
// If this path no longer exists on the filesystem, then remove it from the snapshot.
|
// If this path no longer exists on the filesystem, then remove it from the snapshot.
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
if let Some(snapshot_entry) = snapshot_entry {
|
if let Some(snapshot_entry) = snapshot_entry {
|
||||||
let snapshot_inode = snapshot_entry.ino();
|
let snapshot_inode = snapshot_entry.inode();
|
||||||
let snapshot_parent_inode = snapshot_entry.parent();
|
let snapshot_parent_inode = snapshot_entry.parent();
|
||||||
snapshot.reparent_entry(snapshot_inode, None, snapshot_parent_inode, None);
|
snapshot.reparent_entry(snapshot_inode, None, snapshot_parent_inode, None);
|
||||||
possible_removed_inodes.insert(snapshot_inode);
|
possible_removed_inodes.insert(snapshot_inode);
|
||||||
|
@ -1167,6 +1202,9 @@ mod tests {
|
||||||
let operations = env::var("OPERATIONS")
|
let operations = env::var("OPERATIONS")
|
||||||
.map(|o| o.parse().unwrap())
|
.map(|o| o.parse().unwrap())
|
||||||
.unwrap_or(40);
|
.unwrap_or(40);
|
||||||
|
let initial_entries = env::var("INITIAL_ENTRIES")
|
||||||
|
.map(|o| o.parse().unwrap())
|
||||||
|
.unwrap_or(20);
|
||||||
let seeds = if let Ok(seed) = env::var("SEED").map(|s| s.parse().unwrap()) {
|
let seeds = if let Ok(seed) = env::var("SEED").map(|s| s.parse().unwrap()) {
|
||||||
seed..seed + 1
|
seed..seed + 1
|
||||||
} else {
|
} else {
|
||||||
|
@ -1178,7 +1216,7 @@ mod tests {
|
||||||
let mut rng = StdRng::seed_from_u64(seed);
|
let mut rng = StdRng::seed_from_u64(seed);
|
||||||
|
|
||||||
let root_dir = tempdir::TempDir::new(&format!("test-{}", seed)).unwrap();
|
let root_dir = tempdir::TempDir::new(&format!("test-{}", seed)).unwrap();
|
||||||
for _ in 0..20 {
|
for _ in 0..initial_entries {
|
||||||
randomly_mutate_tree(root_dir.path(), 1.0, &mut rng).unwrap();
|
randomly_mutate_tree(root_dir.path(), 1.0, &mut rng).unwrap();
|
||||||
}
|
}
|
||||||
log::info!("Generated initial tree");
|
log::info!("Generated initial tree");
|
||||||
|
@ -1201,12 +1239,14 @@ mod tests {
|
||||||
if !events.is_empty() && rng.gen_bool(0.4) {
|
if !events.is_empty() && rng.gen_bool(0.4) {
|
||||||
let len = rng.gen_range(0..=events.len());
|
let len = rng.gen_range(0..=events.len());
|
||||||
let to_deliver = events.drain(0..len).collect::<Vec<_>>();
|
let to_deliver = events.drain(0..len).collect::<Vec<_>>();
|
||||||
|
log::info!("Delivering events: {:#?}", to_deliver);
|
||||||
scanner.process_events(to_deliver);
|
scanner.process_events(to_deliver);
|
||||||
} else {
|
} else {
|
||||||
events.extend(randomly_mutate_tree(root_dir.path(), 0.6, &mut rng).unwrap());
|
events.extend(randomly_mutate_tree(root_dir.path(), 0.6, &mut rng).unwrap());
|
||||||
mutations_len -= 1;
|
mutations_len -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log::info!("Quiescing: {:#?}", events);
|
||||||
scanner.process_events(events);
|
scanner.process_events(events);
|
||||||
|
|
||||||
let (notify_tx, _notify_rx) = smol::channel::unbounded();
|
let (notify_tx, _notify_rx) = smol::channel::unbounded();
|
||||||
|
|
Loading…
Reference in a new issue