Emit loaded events for lazily loaded paths in worktree
This commit is contained in:
parent
9ad1ebf387
commit
b22a18345e
2 changed files with 64 additions and 8 deletions
|
@ -2759,6 +2759,10 @@ impl EntryKind {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_unloaded(&self) -> bool {
|
||||||
|
matches!(self, EntryKind::UnloadedDir)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_file(&self) -> bool {
|
pub fn is_file(&self) -> bool {
|
||||||
matches!(self, EntryKind::File(_))
|
matches!(self, EntryKind::File(_))
|
||||||
}
|
}
|
||||||
|
@ -3773,6 +3777,7 @@ impl BackgroundScanner {
|
||||||
let mut changes = Vec::new();
|
let mut changes = Vec::new();
|
||||||
let mut old_paths = old_snapshot.entries_by_path.cursor::<PathKey>();
|
let mut old_paths = old_snapshot.entries_by_path.cursor::<PathKey>();
|
||||||
let mut new_paths = new_snapshot.entries_by_path.cursor::<PathKey>();
|
let mut new_paths = new_snapshot.entries_by_path.cursor::<PathKey>();
|
||||||
|
let mut last_newly_loaded_dir_path = None;
|
||||||
old_paths.next(&());
|
old_paths.next(&());
|
||||||
new_paths.next(&());
|
new_paths.next(&());
|
||||||
for path in event_paths {
|
for path in event_paths {
|
||||||
|
@ -3820,20 +3825,33 @@ impl BackgroundScanner {
|
||||||
changes.push((old_entry.path.clone(), old_entry.id, Removed));
|
changes.push((old_entry.path.clone(), old_entry.id, Removed));
|
||||||
changes.push((new_entry.path.clone(), new_entry.id, Added));
|
changes.push((new_entry.path.clone(), new_entry.id, Added));
|
||||||
} else if old_entry != new_entry {
|
} else if old_entry != new_entry {
|
||||||
changes.push((new_entry.path.clone(), new_entry.id, Updated));
|
if old_entry.kind.is_unloaded() {
|
||||||
|
last_newly_loaded_dir_path = Some(&new_entry.path);
|
||||||
|
changes.push((
|
||||||
|
new_entry.path.clone(),
|
||||||
|
new_entry.id,
|
||||||
|
Loaded,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
changes.push((
|
||||||
|
new_entry.path.clone(),
|
||||||
|
new_entry.id,
|
||||||
|
Updated,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
old_paths.next(&());
|
old_paths.next(&());
|
||||||
new_paths.next(&());
|
new_paths.next(&());
|
||||||
}
|
}
|
||||||
Ordering::Greater => {
|
Ordering::Greater => {
|
||||||
|
let is_newly_loaded = self.phase == InitialScan
|
||||||
|
|| last_newly_loaded_dir_path
|
||||||
|
.as_ref()
|
||||||
|
.map_or(false, |dir| new_entry.path.starts_with(&dir));
|
||||||
changes.push((
|
changes.push((
|
||||||
new_entry.path.clone(),
|
new_entry.path.clone(),
|
||||||
new_entry.id,
|
new_entry.id,
|
||||||
if self.phase == InitialScan {
|
if is_newly_loaded { Loaded } else { Added },
|
||||||
Loaded
|
|
||||||
} else {
|
|
||||||
Added
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
new_paths.next(&());
|
new_paths.next(&());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ use serde_json::json;
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
fmt::Write,
|
fmt::Write,
|
||||||
|
mem,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
@ -313,6 +314,21 @@ async fn test_symlinks_pointing_outside(cx: &mut TestAppContext) {
|
||||||
cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
|
cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
let tree_updates = Arc::new(Mutex::new(Vec::new()));
|
||||||
|
tree.update(cx, |_, cx| {
|
||||||
|
let tree_updates = tree_updates.clone();
|
||||||
|
cx.subscribe(&tree, move |_, _, event, _| {
|
||||||
|
if let Event::UpdatedEntries(update) = event {
|
||||||
|
tree_updates.lock().extend(
|
||||||
|
update
|
||||||
|
.iter()
|
||||||
|
.map(|(path, _, change)| (path.clone(), *change)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
});
|
||||||
|
|
||||||
// The symlinked directories are not scanned by default.
|
// The symlinked directories are not scanned by default.
|
||||||
tree.read_with(cx, |tree, _| {
|
tree.read_with(cx, |tree, _| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -365,6 +381,14 @@ async fn test_symlinks_pointing_outside(cx: &mut TestAppContext) {
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
assert_eq!(
|
||||||
|
mem::take(&mut *tree_updates.lock()),
|
||||||
|
&[
|
||||||
|
(Path::new("deps/dep-dir3").into(), PathChange::Loaded),
|
||||||
|
(Path::new("deps/dep-dir3/deps").into(), PathChange::Loaded),
|
||||||
|
(Path::new("deps/dep-dir3/src").into(), PathChange::Loaded)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
// Expand a subdirectory of one of the symlinked directories.
|
// Expand a subdirectory of one of the symlinked directories.
|
||||||
tree.read_with(cx, |tree, _| {
|
tree.read_with(cx, |tree, _| {
|
||||||
|
@ -396,6 +420,21 @@ async fn test_symlinks_pointing_outside(cx: &mut TestAppContext) {
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
mem::take(&mut *tree_updates.lock()),
|
||||||
|
&[
|
||||||
|
(Path::new("deps/dep-dir3/src").into(), PathChange::Loaded),
|
||||||
|
(
|
||||||
|
Path::new("deps/dep-dir3/src/e.rs").into(),
|
||||||
|
PathChange::Loaded
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Path::new("deps/dep-dir3/src/f.rs").into(),
|
||||||
|
PathChange::Loaded
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
|
@ -1114,7 +1153,6 @@ fn check_worktree_change_events(tree: &mut Worktree, cx: &mut ModelContext<Workt
|
||||||
Ok(ix) | Err(ix) => ix,
|
Ok(ix) | Err(ix) => ix,
|
||||||
};
|
};
|
||||||
match change_type {
|
match change_type {
|
||||||
PathChange::Loaded => entries.insert(ix, entry.unwrap()),
|
|
||||||
PathChange::Added => entries.insert(ix, entry.unwrap()),
|
PathChange::Added => entries.insert(ix, entry.unwrap()),
|
||||||
PathChange::Removed => drop(entries.remove(ix)),
|
PathChange::Removed => drop(entries.remove(ix)),
|
||||||
PathChange::Updated => {
|
PathChange::Updated => {
|
||||||
|
@ -1123,7 +1161,7 @@ fn check_worktree_change_events(tree: &mut Worktree, cx: &mut ModelContext<Workt
|
||||||
assert_eq!(existing_entry.path, entry.path);
|
assert_eq!(existing_entry.path, entry.path);
|
||||||
*existing_entry = entry;
|
*existing_entry = entry;
|
||||||
}
|
}
|
||||||
PathChange::AddedOrUpdated => {
|
PathChange::AddedOrUpdated | PathChange::Loaded => {
|
||||||
let entry = entry.unwrap();
|
let entry = entry.unwrap();
|
||||||
if entries.get(ix).map(|e| &e.path) == Some(&entry.path) {
|
if entries.get(ix).map(|e| &e.path) == Some(&entry.path) {
|
||||||
*entries.get_mut(ix).unwrap() = entry;
|
*entries.get_mut(ix).unwrap() = entry;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue