Get all worktree tests passing

* Store non-canocalized path on worktree, but canonicalize it for the purpose of processing events
* Simplify rescan unit test
This commit is contained in:
Max Brunsfeld 2021-04-19 14:11:55 -07:00
parent f06164ade9
commit f27b01fcd5

View file

@ -260,18 +260,19 @@ impl Snapshot {
let mut edits = Vec::new(); let mut edits = Vec::new();
edits.push(Edit::Insert(entry.clone())); edits.push(Edit::Insert(entry.clone()));
if let Some(parent) = entry.parent() { if let Some(parent) = entry.parent() {
let mut parent_entry = self.entries.get(&parent).unwrap().clone(); if let Some(mut parent_entry) = self.entries.get(&parent).cloned() {
if let Entry::Dir { children, .. } = &mut parent_entry { if let Entry::Dir { children, .. } = &mut parent_entry {
let name = Arc::from(path.file_name().unwrap()); let name = Arc::from(path.file_name().unwrap());
*children = children *children = children
.into_iter() .into_iter()
.cloned() .cloned()
.chain(Some((entry.inode(), name))) .chain(Some((entry.inode(), name)))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into(); .into();
edits.push(Edit::Insert(parent_entry)); edits.push(Edit::Insert(parent_entry));
} else { } else {
unreachable!(); unreachable!();
}
} }
} }
self.entries.edit(edits); self.entries.edit(edits);
@ -500,16 +501,7 @@ impl BackgroundScanner {
} }
fn run(&self) { fn run(&self) {
let path = { let path = self.snapshot.lock().path.clone();
let mut snapshot = self.snapshot.lock();
let canonical_path = snapshot
.path
.canonicalize()
.map(Arc::from)
.unwrap_or_else(|_| snapshot.path.clone());
snapshot.path = canonical_path.clone();
canonical_path
};
// Create the event stream before we start scanning to ensure we receive events for changes // Create the event stream before we start scanning to ensure we receive events for changes
// that occur in the middle of the scan. // that occur in the middle of the scan.
@ -699,15 +691,19 @@ impl BackgroundScanner {
fn process_events(&self, mut events: Vec<fsevent::Event>) { fn process_events(&self, mut events: Vec<fsevent::Event>) {
let mut snapshot = self.snapshot(); let mut snapshot = self.snapshot();
let root_path = snapshot
.path
.canonicalize()
.unwrap_or_else(|_| snapshot.path.to_path_buf());
events.sort_unstable_by(|a, b| a.path.cmp(&b.path)); events.sort_unstable_by(|a, b| a.path.cmp(&b.path));
let mut paths = events.into_iter().map(|e| e.path).peekable(); let mut paths = events.into_iter().map(|e| e.path).peekable();
let (scan_queue_tx, scan_queue_rx) = crossbeam_channel::unbounded(); let (scan_queue_tx, scan_queue_rx) = crossbeam_channel::unbounded();
while let Some(path) = paths.next() { while let Some(path) = paths.next() {
let relative_path = match path.strip_prefix(&snapshot.path) { let relative_path = match path.strip_prefix(&root_path) {
Ok(relative_path) => relative_path.to_path_buf(), Ok(relative_path) => relative_path.to_path_buf(),
Err(e) => { Err(_) => {
log::error!("unexpected event {:?}", e); log::error!("unexpected event {:?} for root path {:?}", path, root_path);
continue; continue;
} }
}; };
@ -718,7 +714,7 @@ impl BackgroundScanner {
snapshot.remove_entry(&relative_path); snapshot.remove_entry(&relative_path);
match self.fs_entry_for_path(&snapshot.path, &path) { match self.fs_entry_for_path(&root_path, &path) {
Ok(Some((fs_entry, ignore))) => { Ok(Some((fs_entry, ignore))) => {
snapshot.insert_entry(&path, fs_entry.clone()); snapshot.insert_entry(&path, fs_entry.clone());
@ -977,61 +973,49 @@ mod tests {
#[test] #[test]
fn test_rescan() { fn test_rescan() {
App::test_async((), |mut app| async move { App::test_async((), |mut app| async move {
let dir2 = temp_tree(json!({
"dir1": {
"dir3": {
"file": "contents",
}
},
"dir2": {
}
}));
let dir = temp_tree(json!({ let dir = temp_tree(json!({
"dir1": { "dir1": {
"dir3": { "file1": "contents 1",
"file": "contents",
}
}, },
"dir2": { "dir2": {
"dir3": {
"file2": "contents 2",
}
} }
})); }));
let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx)); let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
assert_condition(1, 300, || app.read(|ctx| tree.read(ctx).file_count() == 1)).await; assert_condition(1, 300, || app.read(|ctx| tree.read(ctx).file_count() == 2)).await;
let dir_inode = app.read(|ctx| { let file2_inode = app.read(|ctx| {
tree.read(ctx) tree.read(ctx)
.snapshot() .snapshot()
.inode_for_path("dir1/dir3") .inode_for_path("dir2/dir3/file2")
.unwrap() .unwrap()
}); });
app.read(|ctx| { app.read(|ctx| {
let tree = tree.read(ctx); let tree = tree.read(ctx);
assert_eq!( assert_eq!(
tree.path_for_inode(dir_inode, false) tree.path_for_inode(file2_inode, false)
.unwrap() .unwrap()
.to_str() .to_str()
.unwrap(), .unwrap(),
"dir1/dir3" "dir2/dir3/file2"
); );
}); });
std::fs::rename(dir2.path(), dir.path().join("foo")).unwrap(); std::fs::rename(dir.path().join("dir2/dir3"), dir.path().join("dir4")).unwrap();
assert_condition(1, 300, || { assert_condition(1, 300, || {
app.read(|ctx| { app.read(|ctx| {
let tree = tree.read(ctx); let tree = tree.read(ctx);
tree.path_for_inode(dir_inode, false) tree.path_for_inode(file2_inode, false)
.unwrap() .unwrap()
.to_str() .to_str()
.unwrap() .unwrap()
== "dir2/dir3" == "dir4/file2"
}) })
}) })
.await; .await;
app.read(|ctx| {
let tree = tree.read(ctx);
assert_eq!(tree.snapshot().inode_for_path("dir2/dir3"), Some(dir_inode));
});
}); });
} }
@ -1112,7 +1096,8 @@ mod tests {
insertion_probability: f64, insertion_probability: f64,
rng: &mut impl Rng, rng: &mut impl Rng,
) -> Result<Vec<fsevent::Event>> { ) -> Result<Vec<fsevent::Event>> {
let (dirs, files) = read_dir_recursive(root_path.to_path_buf()); let root_path = root_path.canonicalize().unwrap();
let (dirs, files) = read_dir_recursive(root_path.clone());
let mut events = Vec::new(); let mut events = Vec::new();
let mut record_event = |path: PathBuf| { let mut record_event = |path: PathBuf| {