Expand dirs on-demand when opening buffers inside unloaded dirs
This commit is contained in:
parent
cd823ede4d
commit
3e6aedfc69
3 changed files with 206 additions and 74 deletions
|
@ -5413,7 +5413,10 @@ impl Project {
|
||||||
if self.is_local() {
|
if self.is_local() {
|
||||||
let worktree = self.worktree_for_id(worktree_id, cx)?;
|
let worktree = self.worktree_for_id(worktree_id, cx)?;
|
||||||
worktree.update(cx, |worktree, cx| {
|
worktree.update(cx, |worktree, cx| {
|
||||||
worktree.as_local_mut().unwrap().expand_dir(entry_id, cx);
|
worktree
|
||||||
|
.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.expand_entry_for_id(entry_id, cx);
|
||||||
});
|
});
|
||||||
} else if let Some(project_id) = self.remote_id() {
|
} else if let Some(project_id) = self.remote_id() {
|
||||||
cx.background()
|
cx.background()
|
||||||
|
@ -5739,7 +5742,10 @@ impl Project {
|
||||||
.read_with(&cx, |this, cx| this.worktree_for_entry(entry_id, cx))
|
.read_with(&cx, |this, cx| this.worktree_for_entry(entry_id, cx))
|
||||||
.ok_or_else(|| anyhow!("invalid request"))?;
|
.ok_or_else(|| anyhow!("invalid request"))?;
|
||||||
worktree.update(&mut cx, |worktree, cx| {
|
worktree.update(&mut cx, |worktree, cx| {
|
||||||
worktree.as_local_mut().unwrap().expand_dir(entry_id, cx)
|
worktree
|
||||||
|
.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.expand_entry_for_id(entry_id, cx)
|
||||||
});
|
});
|
||||||
Ok(proto::Ack {})
|
Ok(proto::Ack {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,8 +89,8 @@ enum ScanRequest {
|
||||||
relative_paths: Vec<Arc<Path>>,
|
relative_paths: Vec<Arc<Path>>,
|
||||||
done: barrier::Sender,
|
done: barrier::Sender,
|
||||||
},
|
},
|
||||||
ExpandDir {
|
ExpandPath {
|
||||||
entry_id: ProjectEntryId,
|
path: Arc<Path>,
|
||||||
done: barrier::Sender,
|
done: barrier::Sender,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -879,18 +879,24 @@ impl LocalWorktree {
|
||||||
path: &Path,
|
path: &Path,
|
||||||
cx: &mut ModelContext<Worktree>,
|
cx: &mut ModelContext<Worktree>,
|
||||||
) -> Task<Result<(File, String, Option<String>)>> {
|
) -> Task<Result<(File, String, Option<String>)>> {
|
||||||
let handle = cx.handle();
|
|
||||||
let path = Arc::from(path);
|
let path = Arc::from(path);
|
||||||
let abs_path = self.absolutize(&path);
|
let abs_path = self.absolutize(&path);
|
||||||
let fs = self.fs.clone();
|
let fs = self.fs.clone();
|
||||||
let snapshot = self.snapshot();
|
let expand = path
|
||||||
|
.parent()
|
||||||
|
.map(|path| self.expand_entry_for_path(path, cx));
|
||||||
|
|
||||||
|
cx.spawn(|this, mut cx| async move {
|
||||||
|
if let Some(mut expand) = expand {
|
||||||
|
expand.recv().await;
|
||||||
|
}
|
||||||
|
|
||||||
let mut index_task = None;
|
let mut index_task = None;
|
||||||
|
let snapshot = this.read_with(&cx, |this, _| this.as_local().unwrap().snapshot());
|
||||||
if let Some(repo) = snapshot.repository_for_path(&path) {
|
if let Some(repo) = snapshot.repository_for_path(&path) {
|
||||||
let repo_path = repo.work_directory.relativize(self, &path).unwrap();
|
let repo_path = repo.work_directory.relativize(&snapshot, &path).unwrap();
|
||||||
if let Some(repo) = self.git_repositories.get(&*repo.work_directory) {
|
if let Some(repo) = snapshot.git_repositories.get(&*repo.work_directory) {
|
||||||
let repo = repo.repo_ptr.to_owned();
|
let repo = repo.repo_ptr.clone();
|
||||||
index_task = Some(
|
index_task = Some(
|
||||||
cx.background()
|
cx.background()
|
||||||
.spawn(async move { repo.lock().load_index_text(&repo_path) }),
|
.spawn(async move { repo.lock().load_index_text(&repo_path) }),
|
||||||
|
@ -898,7 +904,6 @@ impl LocalWorktree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.spawn(|this, mut cx| async move {
|
|
||||||
let text = fs.load(&abs_path).await?;
|
let text = fs.load(&abs_path).await?;
|
||||||
|
|
||||||
let diff_base = if let Some(index_task) = index_task {
|
let diff_base = if let Some(index_task) = index_task {
|
||||||
|
@ -917,7 +922,7 @@ impl LocalWorktree {
|
||||||
Ok((
|
Ok((
|
||||||
File {
|
File {
|
||||||
entry_id: entry.id,
|
entry_id: entry.id,
|
||||||
worktree: handle,
|
worktree: this,
|
||||||
path: entry.path,
|
path: entry.path,
|
||||||
mtime: entry.mtime,
|
mtime: entry.mtime,
|
||||||
is_local: true,
|
is_local: true,
|
||||||
|
@ -1146,14 +1151,34 @@ impl LocalWorktree {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand_dir(
|
pub fn expand_entry_for_id(
|
||||||
&mut self,
|
&mut self,
|
||||||
entry_id: ProjectEntryId,
|
entry_id: ProjectEntryId,
|
||||||
_cx: &mut ModelContext<Worktree>,
|
_cx: &mut ModelContext<Worktree>,
|
||||||
) -> barrier::Receiver {
|
) -> barrier::Receiver {
|
||||||
let (tx, rx) = barrier::channel();
|
let (tx, rx) = barrier::channel();
|
||||||
|
if let Some(entry) = self.entry_for_id(entry_id) {
|
||||||
self.scan_requests_tx
|
self.scan_requests_tx
|
||||||
.try_send(ScanRequest::ExpandDir { entry_id, done: tx })
|
.try_send(ScanRequest::ExpandPath {
|
||||||
|
path: entry.path.clone(),
|
||||||
|
done: tx,
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
rx
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expand_entry_for_path(
|
||||||
|
&self,
|
||||||
|
path: impl Into<Arc<Path>>,
|
||||||
|
_cx: &mut ModelContext<Worktree>,
|
||||||
|
) -> barrier::Receiver {
|
||||||
|
let (tx, rx) = barrier::channel();
|
||||||
|
self.scan_requests_tx
|
||||||
|
.try_send(ScanRequest::ExpandPath {
|
||||||
|
path: path.into(),
|
||||||
|
done: tx,
|
||||||
|
})
|
||||||
.ok();
|
.ok();
|
||||||
rx
|
rx
|
||||||
}
|
}
|
||||||
|
@ -2192,10 +2217,6 @@ impl LocalSnapshot {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackgroundScannerState {
|
impl BackgroundScannerState {
|
||||||
fn is_entry_expanded(&self, entry: &Entry) -> bool {
|
|
||||||
self.expanded_dirs.contains(&entry.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reuse_entry_id(&mut self, entry: &mut Entry) {
|
fn reuse_entry_id(&mut self, entry: &mut Entry) {
|
||||||
if let Some(removed_entry_id) = self.removed_entry_ids.remove(&entry.inode) {
|
if let Some(removed_entry_id) = self.removed_entry_ids.remove(&entry.inode) {
|
||||||
entry.id = removed_entry_id;
|
entry.id = removed_entry_id;
|
||||||
|
@ -2989,34 +3010,39 @@ impl BackgroundScanner {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
self.reload_entries_for_paths(root_path, root_canonical_path, abs_paths, None)
|
|
||||||
.await;
|
|
||||||
self.send_status_update(false, Some(done))
|
|
||||||
}
|
|
||||||
ScanRequest::ExpandDir { entry_id, done } => {
|
|
||||||
let abs_path;
|
|
||||||
{
|
|
||||||
let mut state = self.state.lock();
|
|
||||||
if let Some(entry) = state.snapshot.entry_for_id(entry_id) {
|
|
||||||
abs_path = root_canonical_path.join(&entry.path);
|
|
||||||
state.expanded_dirs.insert(entry_id);
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let (scan_job_tx, mut scan_job_rx) = channel::unbounded();
|
|
||||||
self.reload_entries_for_paths(
|
self.reload_entries_for_paths(
|
||||||
root_path,
|
root_path,
|
||||||
root_canonical_path,
|
root_canonical_path,
|
||||||
vec![abs_path],
|
abs_paths,
|
||||||
Some(scan_job_tx),
|
false,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
if let Some(job) = scan_job_rx.next().await {
|
self.send_status_update(false, Some(done))
|
||||||
self.scan_dir(&job).await.log_err();
|
|
||||||
self.send_status_update(false, Some(done));
|
|
||||||
}
|
}
|
||||||
|
ScanRequest::ExpandPath { path, done } => {
|
||||||
|
let (scan_job_tx, mut scan_job_rx) = channel::unbounded();
|
||||||
|
let mut abs_path = root_canonical_path.clone();
|
||||||
|
for component in path.iter() {
|
||||||
|
abs_path.push(component);
|
||||||
|
self.reload_entries_for_paths(
|
||||||
|
root_path.clone(),
|
||||||
|
root_canonical_path.clone(),
|
||||||
|
vec![abs_path.clone()],
|
||||||
|
true,
|
||||||
|
Some(scan_job_tx.clone()),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
drop(scan_job_tx);
|
||||||
|
|
||||||
|
// Scan the expanded directories serially. This is ok, because only
|
||||||
|
// the direct ancestors of the expanded path need to be scanned.
|
||||||
|
while let Some(job) = scan_job_rx.next().await {
|
||||||
|
self.scan_dir(&job).await.log_err();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.send_status_update(false, Some(done));
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3038,6 +3064,7 @@ impl BackgroundScanner {
|
||||||
root_path,
|
root_path,
|
||||||
root_canonical_path,
|
root_canonical_path,
|
||||||
abs_paths,
|
abs_paths,
|
||||||
|
false,
|
||||||
Some(scan_job_tx.clone()),
|
Some(scan_job_tx.clone()),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -3176,22 +3203,18 @@ impl BackgroundScanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn scan_dir(&self, job: &ScanJob) -> Result<()> {
|
async fn scan_dir(&self, job: &ScanJob) -> Result<()> {
|
||||||
|
log::debug!(
|
||||||
|
"scan directory {:?}. external: {}",
|
||||||
|
job.path,
|
||||||
|
job.is_external
|
||||||
|
);
|
||||||
|
|
||||||
let mut new_entries: Vec<Entry> = Vec::new();
|
let mut new_entries: Vec<Entry> = Vec::new();
|
||||||
let mut new_jobs: Vec<Option<ScanJob>> = Vec::new();
|
let mut new_jobs: Vec<Option<ScanJob>> = Vec::new();
|
||||||
let mut ignore_stack = job.ignore_stack.clone();
|
let mut ignore_stack = job.ignore_stack.clone();
|
||||||
let mut new_ignore = None;
|
let mut new_ignore = None;
|
||||||
let (root_abs_path, root_char_bag, next_entry_id, repository) = {
|
let (root_abs_path, root_char_bag, next_entry_id, repository) = {
|
||||||
let state = self.state.lock();
|
let snapshot = &self.state.lock().snapshot;
|
||||||
if job.is_external || job.ignore_stack.is_all() {
|
|
||||||
if let Some(entry) = state.snapshot.entry_for_path(&job.path) {
|
|
||||||
if !state.is_entry_expanded(entry) {
|
|
||||||
log::debug!("defer scanning directory {:?}", job.path);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let snapshot = &state.snapshot;
|
|
||||||
(
|
(
|
||||||
snapshot.abs_path().clone(),
|
snapshot.abs_path().clone(),
|
||||||
snapshot.root_char_bag,
|
snapshot.root_char_bag,
|
||||||
|
@ -3202,12 +3225,6 @@ impl BackgroundScanner {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
log::debug!(
|
|
||||||
"scan directory {:?}. external: {}",
|
|
||||||
job.path,
|
|
||||||
job.is_external
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut root_canonical_path = None;
|
let mut root_canonical_path = None;
|
||||||
let mut child_paths = self.fs.read_dir(&job.abs_path).await?;
|
let mut child_paths = self.fs.read_dir(&job.abs_path).await?;
|
||||||
while let Some(child_abs_path) = child_paths.next().await {
|
while let Some(child_abs_path) = child_paths.next().await {
|
||||||
|
@ -3258,7 +3275,7 @@ impl BackgroundScanner {
|
||||||
ignore_stack.is_abs_path_ignored(&entry_abs_path, entry.is_dir());
|
ignore_stack.is_abs_path_ignored(&entry_abs_path, entry.is_dir());
|
||||||
|
|
||||||
if entry.is_dir() {
|
if entry.is_dir() {
|
||||||
if let Some(job) = new_jobs.next().expect("Missing scan job for entry") {
|
if let Some(job) = new_jobs.next().expect("missing scan job for entry") {
|
||||||
job.ignore_stack = if entry.is_ignored {
|
job.ignore_stack = if entry.is_ignored {
|
||||||
IgnoreStack::all()
|
IgnoreStack::all()
|
||||||
} else {
|
} else {
|
||||||
|
@ -3351,13 +3368,26 @@ impl BackgroundScanner {
|
||||||
new_entries.push(child_entry);
|
new_entries.push(child_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state
|
let mut state = self.state.lock();
|
||||||
.lock()
|
state.populate_dir(&job.path, new_entries, new_ignore, self.fs.as_ref());
|
||||||
.populate_dir(&job.path, new_entries, new_ignore, self.fs.as_ref());
|
|
||||||
|
|
||||||
for new_job in new_jobs {
|
for new_job in new_jobs {
|
||||||
if let Some(new_job) = new_job {
|
if let Some(new_job) = new_job {
|
||||||
job.scan_queue.send(new_job).await.ok();
|
// If a subdirectory is ignored, or is external to the worktree, don't scan
|
||||||
|
// it unless it is marked as expanded.
|
||||||
|
if (new_job.is_external || new_job.ignore_stack.is_all())
|
||||||
|
&& !state
|
||||||
|
.snapshot
|
||||||
|
.entry_for_path(&new_job.path)
|
||||||
|
.map_or(true, |entry| state.expanded_dirs.contains(&entry.id))
|
||||||
|
{
|
||||||
|
log::debug!("defer scanning directory {:?}", new_job.path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
job.scan_queue
|
||||||
|
.try_send(new_job)
|
||||||
|
.expect("channel is unbounded");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3369,6 +3399,7 @@ impl BackgroundScanner {
|
||||||
root_abs_path: Arc<Path>,
|
root_abs_path: Arc<Path>,
|
||||||
root_canonical_path: PathBuf,
|
root_canonical_path: PathBuf,
|
||||||
mut abs_paths: Vec<PathBuf>,
|
mut abs_paths: Vec<PathBuf>,
|
||||||
|
expand: bool,
|
||||||
scan_queue_tx: Option<Sender<ScanJob>>,
|
scan_queue_tx: Option<Sender<ScanJob>>,
|
||||||
) -> Option<Vec<Arc<Path>>> {
|
) -> Option<Vec<Arc<Path>>> {
|
||||||
let doing_recursive_update = scan_queue_tx.is_some();
|
let doing_recursive_update = scan_queue_tx.is_some();
|
||||||
|
@ -3456,6 +3487,9 @@ impl BackgroundScanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
let fs_entry = state.insert_entry(fs_entry, self.fs.as_ref());
|
let fs_entry = state.insert_entry(fs_entry, self.fs.as_ref());
|
||||||
|
if expand {
|
||||||
|
state.expanded_dirs.insert(fs_entry.id);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(scan_queue_tx) = &scan_queue_tx {
|
if let Some(scan_queue_tx) = &scan_queue_tx {
|
||||||
let mut ancestor_inodes = state.snapshot.ancestor_inodes_for_path(&path);
|
let mut ancestor_inodes = state.snapshot.ancestor_inodes_for_path(&path);
|
||||||
|
|
|
@ -160,7 +160,7 @@ async fn test_descendent_entries(cx: &mut TestAppContext) {
|
||||||
// Expand gitignored directory.
|
// Expand gitignored directory.
|
||||||
tree.update(cx, |tree, cx| {
|
tree.update(cx, |tree, cx| {
|
||||||
let tree = tree.as_local_mut().unwrap();
|
let tree = tree.as_local_mut().unwrap();
|
||||||
tree.expand_dir(tree.entry_for_path("i/j").unwrap().id, cx)
|
tree.expand_entry_for_path("i/j".as_ref(), cx)
|
||||||
})
|
})
|
||||||
.recv()
|
.recv()
|
||||||
.await;
|
.await;
|
||||||
|
@ -341,7 +341,7 @@ async fn test_symlinks_pointing_outside(cx: &mut TestAppContext) {
|
||||||
// Expand one of the symlinked directories.
|
// Expand one of the symlinked directories.
|
||||||
tree.update(cx, |tree, cx| {
|
tree.update(cx, |tree, cx| {
|
||||||
let tree = tree.as_local_mut().unwrap();
|
let tree = tree.as_local_mut().unwrap();
|
||||||
tree.expand_dir(tree.entry_for_path("deps/dep-dir3").unwrap().id, cx)
|
tree.expand_entry_for_path("deps/dep-dir3".as_ref(), cx)
|
||||||
})
|
})
|
||||||
.recv()
|
.recv()
|
||||||
.await;
|
.await;
|
||||||
|
@ -370,7 +370,7 @@ async fn test_symlinks_pointing_outside(cx: &mut TestAppContext) {
|
||||||
// Expand a subdirectory of one of the symlinked directories.
|
// Expand a subdirectory of one of the symlinked directories.
|
||||||
tree.update(cx, |tree, cx| {
|
tree.update(cx, |tree, cx| {
|
||||||
let tree = tree.as_local_mut().unwrap();
|
let tree = tree.as_local_mut().unwrap();
|
||||||
tree.expand_dir(tree.entry_for_path("deps/dep-dir3/src").unwrap().id, cx)
|
tree.expand_entry_for_path("deps/dep-dir3/src".as_ref(), cx)
|
||||||
})
|
})
|
||||||
.recv()
|
.recv()
|
||||||
.await;
|
.await;
|
||||||
|
@ -398,6 +398,98 @@ async fn test_symlinks_pointing_outside(cx: &mut TestAppContext) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_open_gitignored_files(cx: &mut TestAppContext) {
|
||||||
|
let fs = FakeFs::new(cx.background());
|
||||||
|
fs.insert_tree(
|
||||||
|
"/root",
|
||||||
|
json!({
|
||||||
|
".gitignore": "node_modules\n",
|
||||||
|
"node_modules": {
|
||||||
|
"a": {
|
||||||
|
"a1.js": "a1",
|
||||||
|
"a2.js": "a2",
|
||||||
|
},
|
||||||
|
"b": {
|
||||||
|
"b1.js": "b1",
|
||||||
|
"b2.js": "b2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"src": {
|
||||||
|
"x.js": "",
|
||||||
|
"y.js": "",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let client = cx.read(|cx| Client::new(FakeHttpClient::with_404_response(), cx));
|
||||||
|
let tree = Worktree::local(
|
||||||
|
client,
|
||||||
|
Path::new("/root"),
|
||||||
|
true,
|
||||||
|
fs.clone(),
|
||||||
|
Default::default(),
|
||||||
|
&mut cx.to_async(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
tree.read_with(cx, |tree, _| {
|
||||||
|
assert_eq!(
|
||||||
|
tree.entries(true)
|
||||||
|
.map(|entry| (entry.path.as_ref(), entry.is_ignored))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
vec![
|
||||||
|
(Path::new(""), false),
|
||||||
|
(Path::new(".gitignore"), false),
|
||||||
|
(Path::new("node_modules"), true),
|
||||||
|
(Path::new("src"), false),
|
||||||
|
(Path::new("src/x.js"), false),
|
||||||
|
(Path::new("src/y.js"), false),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
let buffer = tree
|
||||||
|
.update(cx, |tree, cx| {
|
||||||
|
tree.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.load_buffer(0, "node_modules/b/b1.js".as_ref(), cx)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
tree.read_with(cx, |tree, cx| {
|
||||||
|
assert_eq!(
|
||||||
|
tree.entries(true)
|
||||||
|
.map(|entry| (entry.path.as_ref(), entry.is_ignored))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
vec![
|
||||||
|
(Path::new(""), false),
|
||||||
|
(Path::new(".gitignore"), false),
|
||||||
|
(Path::new("node_modules"), true),
|
||||||
|
(Path::new("node_modules/a"), true),
|
||||||
|
(Path::new("node_modules/b"), true),
|
||||||
|
(Path::new("node_modules/b/b1.js"), true),
|
||||||
|
(Path::new("node_modules/b/b2.js"), true),
|
||||||
|
(Path::new("src"), false),
|
||||||
|
(Path::new("src/x.js"), false),
|
||||||
|
(Path::new("src/y.js"), false),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
let buffer = buffer.read(cx);
|
||||||
|
assert_eq!(
|
||||||
|
buffer.file().unwrap().path().as_ref(),
|
||||||
|
Path::new("node_modules/b/b1.js")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_rescan_with_gitignore(cx: &mut TestAppContext) {
|
async fn test_rescan_with_gitignore(cx: &mut TestAppContext) {
|
||||||
// .gitignores are handled explicitly by Zed and do not use the git
|
// .gitignores are handled explicitly by Zed and do not use the git
|
||||||
|
@ -435,7 +527,7 @@ async fn test_rescan_with_gitignore(cx: &mut TestAppContext) {
|
||||||
|
|
||||||
tree.update(cx, |tree, cx| {
|
tree.update(cx, |tree, cx| {
|
||||||
let tree = tree.as_local_mut().unwrap();
|
let tree = tree.as_local_mut().unwrap();
|
||||||
tree.expand_dir(tree.entry_for_path("ignored-dir").unwrap().id, cx)
|
tree.expand_entry_for_path("ignored-dir".as_ref(), cx)
|
||||||
})
|
})
|
||||||
.recv()
|
.recv()
|
||||||
.await;
|
.await;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue