zeta2: Fix panic when running Zed without any worktrees (#39365)

Release Notes:

- N/A
This commit is contained in:
Bennet Bo Fenner 2025-10-02 15:34:13 +02:00 committed by GitHub
parent 702e618bba
commit d85b6a1544
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -116,64 +116,33 @@ impl SyntaxIndex {
.worktrees() .worktrees()
.map(|w| w.read(cx).snapshot()) .map(|w| w.read(cx).snapshot())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
this.state.try_lock().unwrap()._file_indexing_task = if !initial_worktree_snapshots.is_empty() {
Some(cx.spawn(async move |this, cx| { this.state.try_lock().unwrap()._file_indexing_task =
let snapshots_file_count = initial_worktree_snapshots Some(cx.spawn(async move |this, cx| {
.iter() let snapshots_file_count = initial_worktree_snapshots
.map(|worktree| worktree.file_count()) .iter()
.sum::<usize>(); .map(|worktree| worktree.file_count())
let chunk_size = snapshots_file_count.div_ceil(file_indexing_parallelism); .sum::<usize>();
let chunk_count = snapshots_file_count.div_ceil(chunk_size); let chunk_size = snapshots_file_count.div_ceil(file_indexing_parallelism);
let file_chunks = initial_worktree_snapshots let chunk_count = snapshots_file_count.div_ceil(chunk_size);
.iter() let file_chunks = initial_worktree_snapshots
.flat_map(|worktree| { .iter()
let worktree_id = worktree.id(); .flat_map(|worktree| {
worktree.files(false, 0).map(move |entry| { let worktree_id = worktree.id();
( worktree.files(false, 0).map(move |entry| {
entry.id, (
ProjectPath { entry.id,
worktree_id, ProjectPath {
path: entry.path.clone(), worktree_id,
}, path: entry.path.clone(),
) },
)
})
}) })
}) .chunks(chunk_size);
.chunks(chunk_size);
let mut tasks = Vec::with_capacity(chunk_count);
for chunk in file_chunks.into_iter() {
tasks.push(Self::update_dirty_files(
&this,
chunk.into_iter().collect(),
cx.clone(),
));
}
futures::future::join_all(tasks).await;
log::info!("Finished initial file indexing");
*initial_file_indexing_done_tx.borrow_mut() = true;
let Ok(state) = this.read_with(cx, |this, _cx| this.state.clone()) else {
return;
};
while dirty_files_rx.next().await.is_some() {
let mut state = state.lock().await;
let was_underused = state.dirty_files.capacity() > 255
&& state.dirty_files.len() * 8 < state.dirty_files.capacity();
let dirty_files = state.dirty_files.drain().collect::<Vec<_>>();
if was_underused {
state.dirty_files.shrink_to_fit();
}
drop(state);
if dirty_files.is_empty() {
continue;
}
let chunk_size = dirty_files.len().div_ceil(file_indexing_parallelism);
let chunk_count = dirty_files.len().div_ceil(chunk_size);
let mut tasks = Vec::with_capacity(chunk_count); let mut tasks = Vec::with_capacity(chunk_count);
let chunks = dirty_files.into_iter().chunks(chunk_size); for chunk in file_chunks.into_iter() {
for chunk in chunks.into_iter() {
tasks.push(Self::update_dirty_files( tasks.push(Self::update_dirty_files(
&this, &this,
chunk.into_iter().collect(), chunk.into_iter().collect(),
@ -181,8 +150,41 @@ impl SyntaxIndex {
)); ));
} }
futures::future::join_all(tasks).await; futures::future::join_all(tasks).await;
}
})); log::info!("Finished initial file indexing");
*initial_file_indexing_done_tx.borrow_mut() = true;
let Ok(state) = this.read_with(cx, |this, _cx| this.state.clone()) else {
return;
};
while dirty_files_rx.next().await.is_some() {
let mut state = state.lock().await;
let was_underused = state.dirty_files.capacity() > 255
&& state.dirty_files.len() * 8 < state.dirty_files.capacity();
let dirty_files = state.dirty_files.drain().collect::<Vec<_>>();
if was_underused {
state.dirty_files.shrink_to_fit();
}
drop(state);
if dirty_files.is_empty() {
continue;
}
let chunk_size = dirty_files.len().div_ceil(file_indexing_parallelism);
let chunk_count = dirty_files.len().div_ceil(chunk_size);
let mut tasks = Vec::with_capacity(chunk_count);
let chunks = dirty_files.into_iter().chunks(chunk_size);
for chunk in chunks.into_iter() {
tasks.push(Self::update_dirty_files(
&this,
chunk.into_iter().collect(),
cx.clone(),
));
}
futures::future::join_all(tasks).await;
}
}));
}
cx.subscribe(&worktree_store, Self::handle_worktree_store_event) cx.subscribe(&worktree_store, Self::handle_worktree_store_event)
.detach(); .detach();