Load diff base for buffers that are opening but not yet opened when repositories are discovered
This commit is contained in:
parent
fc82489128
commit
51d94f532b
2 changed files with 92 additions and 29 deletions
|
@ -16,6 +16,7 @@ use copilot::Copilot;
|
||||||
use futures::{
|
use futures::{
|
||||||
channel::mpsc::{self, UnboundedReceiver},
|
channel::mpsc::{self, UnboundedReceiver},
|
||||||
future::{try_join_all, Shared},
|
future::{try_join_all, Shared},
|
||||||
|
stream::FuturesUnordered,
|
||||||
AsyncWriteExt, Future, FutureExt, StreamExt, TryFutureExt,
|
AsyncWriteExt, Future, FutureExt, StreamExt, TryFutureExt,
|
||||||
};
|
};
|
||||||
use globset::{Glob, GlobSet, GlobSetBuilder};
|
use globset::{Glob, GlobSet, GlobSetBuilder};
|
||||||
|
@ -1374,7 +1375,7 @@ impl Project {
|
||||||
return Task::ready(Ok(existing_buffer));
|
return Task::ready(Ok(existing_buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut loading_watch = match self.loading_buffers_by_path.entry(project_path.clone()) {
|
let loading_watch = match self.loading_buffers_by_path.entry(project_path.clone()) {
|
||||||
// If the given path is already being loaded, then wait for that existing
|
// If the given path is already being loaded, then wait for that existing
|
||||||
// task to complete and return the same buffer.
|
// task to complete and return the same buffer.
|
||||||
hash_map::Entry::Occupied(e) => e.get().clone(),
|
hash_map::Entry::Occupied(e) => e.get().clone(),
|
||||||
|
@ -1405,15 +1406,9 @@ impl Project {
|
||||||
};
|
};
|
||||||
|
|
||||||
cx.foreground().spawn(async move {
|
cx.foreground().spawn(async move {
|
||||||
loop {
|
pump_loading_buffer_reciever(loading_watch)
|
||||||
if let Some(result) = loading_watch.borrow().as_ref() {
|
.await
|
||||||
match result {
|
.map_err(|error| anyhow!("{}", error))
|
||||||
Ok(buffer) => return Ok(buffer.clone()),
|
|
||||||
Err(error) => return Err(anyhow!("{}", error)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loading_watch.next().await;
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4822,6 +4817,51 @@ impl Project {
|
||||||
) {
|
) {
|
||||||
debug_assert!(worktree_handle.read(cx).is_local());
|
debug_assert!(worktree_handle.read(cx).is_local());
|
||||||
|
|
||||||
|
// Setup the pending buffers
|
||||||
|
let future_buffers = self
|
||||||
|
.loading_buffers_by_path
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(path, receiver)| {
|
||||||
|
let path = &path.path;
|
||||||
|
let (work_directory, repo) = repos
|
||||||
|
.iter()
|
||||||
|
.find(|(work_directory, _)| path.starts_with(work_directory))?;
|
||||||
|
|
||||||
|
let repo_relative_path = path.strip_prefix(work_directory).log_err()?;
|
||||||
|
|
||||||
|
let receiver = receiver.clone();
|
||||||
|
let repo_ptr = repo.repo_ptr.clone();
|
||||||
|
let repo_relative_path = repo_relative_path.to_owned();
|
||||||
|
Some(async move {
|
||||||
|
pump_loading_buffer_reciever(receiver)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
.map(|buffer| (buffer, repo_relative_path, repo_ptr))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<FuturesUnordered<_>>()
|
||||||
|
.filter_map(|result| async move {
|
||||||
|
let (buffer_handle, repo_relative_path, repo_ptr) = result?;
|
||||||
|
|
||||||
|
let lock = repo_ptr.lock();
|
||||||
|
lock.load_index_text(&repo_relative_path)
|
||||||
|
.map(|diff_base| (diff_base, buffer_handle))
|
||||||
|
});
|
||||||
|
|
||||||
|
let update_diff_base_fn = update_diff_base(self);
|
||||||
|
cx.spawn(|_, mut cx| async move {
|
||||||
|
let diff_base_tasks = cx
|
||||||
|
.background()
|
||||||
|
.spawn(future_buffers.collect::<Vec<_>>())
|
||||||
|
.await;
|
||||||
|
|
||||||
|
for (diff_base, buffer) in diff_base_tasks.into_iter() {
|
||||||
|
update_diff_base_fn(Some(diff_base), buffer, &mut cx);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
|
||||||
|
// And the current buffers
|
||||||
for (_, buffer) in &self.opened_buffers {
|
for (_, buffer) in &self.opened_buffers {
|
||||||
if let Some(buffer) = buffer.upgrade(cx) {
|
if let Some(buffer) = buffer.upgrade(cx) {
|
||||||
let file = match File::from_dyn(buffer.read(cx).file()) {
|
let file = match File::from_dyn(buffer.read(cx).file()) {
|
||||||
|
@ -4841,18 +4881,17 @@ impl Project {
|
||||||
.find(|(work_directory, _)| path.starts_with(work_directory))
|
.find(|(work_directory, _)| path.starts_with(work_directory))
|
||||||
{
|
{
|
||||||
Some(repo) => repo.clone(),
|
Some(repo) => repo.clone(),
|
||||||
None => return,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let relative_repo = match path.strip_prefix(work_directory).log_err() {
|
let relative_repo = match path.strip_prefix(work_directory).log_err() {
|
||||||
Some(relative_repo) => relative_repo.to_owned(),
|
Some(relative_repo) => relative_repo.to_owned(),
|
||||||
None => return,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
drop(worktree);
|
drop(worktree);
|
||||||
|
|
||||||
let remote_id = self.remote_id();
|
let update_diff_base_fn = update_diff_base(self);
|
||||||
let client = self.client.clone();
|
|
||||||
let git_ptr = repo.repo_ptr.clone();
|
let git_ptr = repo.repo_ptr.clone();
|
||||||
let diff_base_task = cx
|
let diff_base_task = cx
|
||||||
.background()
|
.background()
|
||||||
|
@ -4860,21 +4899,7 @@ impl Project {
|
||||||
|
|
||||||
cx.spawn(|_, mut cx| async move {
|
cx.spawn(|_, mut cx| async move {
|
||||||
let diff_base = diff_base_task.await;
|
let diff_base = diff_base_task.await;
|
||||||
|
update_diff_base_fn(diff_base, buffer, &mut cx);
|
||||||
let buffer_id = buffer.update(&mut cx, |buffer, cx| {
|
|
||||||
buffer.set_diff_base(diff_base.clone(), cx);
|
|
||||||
buffer.remote_id()
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(project_id) = remote_id {
|
|
||||||
client
|
|
||||||
.send(proto::UpdateDiffBase {
|
|
||||||
project_id,
|
|
||||||
buffer_id: buffer_id as u64,
|
|
||||||
diff_base,
|
|
||||||
})
|
|
||||||
.log_err();
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
@ -6764,3 +6789,40 @@ impl Item for Buffer {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn pump_loading_buffer_reciever(
|
||||||
|
mut receiver: postage::watch::Receiver<Option<Result<ModelHandle<Buffer>, Arc<anyhow::Error>>>>,
|
||||||
|
) -> Result<ModelHandle<Buffer>, Arc<anyhow::Error>> {
|
||||||
|
loop {
|
||||||
|
if let Some(result) = receiver.borrow().as_ref() {
|
||||||
|
match result {
|
||||||
|
Ok(buffer) => return Ok(buffer.to_owned()),
|
||||||
|
Err(e) => return Err(e.to_owned()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
receiver.next().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_diff_base(
|
||||||
|
project: &Project,
|
||||||
|
) -> impl Fn(Option<String>, ModelHandle<Buffer>, &mut AsyncAppContext) {
|
||||||
|
let remote_id = project.remote_id();
|
||||||
|
let client = project.client().clone();
|
||||||
|
move |diff_base, buffer, cx| {
|
||||||
|
let buffer_id = buffer.update(cx, |buffer, cx| {
|
||||||
|
buffer.set_diff_base(diff_base.clone(), cx);
|
||||||
|
buffer.remote_id()
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(project_id) = remote_id {
|
||||||
|
client
|
||||||
|
.send(proto::UpdateDiffBase {
|
||||||
|
project_id,
|
||||||
|
buffer_id: buffer_id as u64,
|
||||||
|
diff_base,
|
||||||
|
})
|
||||||
|
.log_err();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -839,6 +839,7 @@ impl LocalWorktree {
|
||||||
fn set_snapshot(&mut self, new_snapshot: LocalSnapshot, cx: &mut ModelContext<Worktree>) {
|
fn set_snapshot(&mut self, new_snapshot: LocalSnapshot, cx: &mut ModelContext<Worktree>) {
|
||||||
let updated_repos =
|
let updated_repos =
|
||||||
self.changed_repos(&self.git_repositories, &new_snapshot.git_repositories);
|
self.changed_repos(&self.git_repositories, &new_snapshot.git_repositories);
|
||||||
|
|
||||||
self.snapshot = new_snapshot;
|
self.snapshot = new_snapshot;
|
||||||
|
|
||||||
if let Some(share) = self.share.as_mut() {
|
if let Some(share) = self.share.as_mut() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue