Start work on reload buffers (#18245)

Release Notes:

- Fixed: ssh-remote reload buffers

---------

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Conrad Irwin 2024-09-24 12:23:39 -06:00 committed by GitHub
parent 8a7ef4db59
commit f39e54decc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 325 additions and 208 deletions

View file

@ -42,10 +42,7 @@ use gpui::{
use itertools::Itertools;
use language::{
language_settings::InlayHintKind,
proto::{
deserialize_anchor, serialize_anchor, serialize_line_ending, serialize_version,
split_operations,
},
proto::{deserialize_anchor, serialize_anchor, split_operations},
Buffer, BufferEvent, CachedLspAdapter, Capability, CodeLabel, ContextProvider, DiagnosticEntry,
Documentation, File as _, Language, LanguageRegistry, LanguageServerName, PointUtf16, ToOffset,
ToPointUtf16, Transaction, Unclipped,
@ -559,7 +556,6 @@ impl Project {
client.add_model_message_handler(Self::handle_unshare_project);
client.add_model_request_handler(Self::handle_update_buffer);
client.add_model_message_handler(Self::handle_update_worktree);
client.add_model_request_handler(Self::handle_reload_buffers);
client.add_model_request_handler(Self::handle_synchronize_buffers);
client.add_model_request_handler(Self::handle_search_project);
@ -599,8 +595,7 @@ impl Project {
cx.subscribe(&worktree_store, Self::on_worktree_store_event)
.detach();
let buffer_store =
cx.new_model(|cx| BufferStore::new(worktree_store.clone(), None, cx));
let buffer_store = cx.new_model(|cx| BufferStore::local(worktree_store.clone(), cx));
cx.subscribe(&buffer_store, Self::on_buffer_store_event)
.detach();
@ -695,8 +690,14 @@ impl Project {
cx.subscribe(&worktree_store, Self::on_worktree_store_event)
.detach();
let buffer_store =
cx.new_model(|cx| BufferStore::new(worktree_store.clone(), None, cx));
let buffer_store = cx.new_model(|cx| {
BufferStore::remote(
worktree_store.clone(),
ssh.clone().into(),
SSH_PROJECT_ID,
cx,
)
});
cx.subscribe(&buffer_store, Self::on_buffer_store_event)
.detach();
@ -851,8 +852,9 @@ impl Project {
.map(DevServerProjectId),
)
})?;
let buffer_store =
cx.new_model(|cx| BufferStore::new(worktree_store.clone(), Some(remote_id), cx))?;
let buffer_store = cx.new_model(|cx| {
BufferStore::remote(worktree_store.clone(), client.clone().into(), remote_id, cx)
})?;
let lsp_store = cx.new_model(|cx| {
let mut lsp_store = LspStore::new_remote(
@ -2167,23 +2169,6 @@ impl Project {
.ok();
}
BufferEvent::Reloaded => {
if self.is_local_or_ssh() {
if let Some(project_id) = self.remote_id() {
let buffer = buffer.read(cx);
self.client
.send(proto::BufferReloaded {
project_id,
buffer_id: buffer.remote_id().to_proto(),
version: serialize_version(&buffer.version()),
mtime: buffer.saved_mtime().map(|t| t.into()),
line_ending: serialize_line_ending(buffer.line_ending()) as i32,
})
.log_err();
}
}
}
_ => {}
}
@ -2347,67 +2332,8 @@ impl Project {
push_to_history: bool,
cx: &mut ModelContext<Self>,
) -> Task<Result<ProjectTransaction>> {
let mut local_buffers = Vec::new();
let mut remote_buffers = None;
for buffer_handle in buffers {
let buffer = buffer_handle.read(cx);
if buffer.is_dirty() {
if let Some(file) = File::from_dyn(buffer.file()) {
if file.is_local() {
local_buffers.push(buffer_handle);
} else {
remote_buffers.get_or_insert(Vec::new()).push(buffer_handle);
}
}
}
}
let remote_buffers = self.remote_id().zip(remote_buffers);
let client = self.client.clone();
cx.spawn(move |this, mut cx| async move {
let mut project_transaction = ProjectTransaction::default();
if let Some((project_id, remote_buffers)) = remote_buffers {
let response = client
.request(proto::ReloadBuffers {
project_id,
buffer_ids: remote_buffers
.iter()
.filter_map(|buffer| {
buffer
.update(&mut cx, |buffer, _| buffer.remote_id().into())
.ok()
})
.collect(),
})
.await?
.transaction
.ok_or_else(|| anyhow!("missing transaction"))?;
BufferStore::deserialize_project_transaction(
this.read_with(&cx, |this, _| this.buffer_store.downgrade())?,
response,
push_to_history,
cx.clone(),
)
.await?;
}
for buffer in local_buffers {
let transaction = buffer
.update(&mut cx, |buffer, cx| buffer.reload(cx))?
.await?;
buffer.update(&mut cx, |buffer, cx| {
if let Some(transaction) = transaction {
if !push_to_history {
buffer.forget_transaction(transaction.id);
}
project_transaction.0.insert(cx.handle(), transaction);
}
})?;
}
Ok(project_transaction)
self.buffer_store.update(cx, |buffer_store, cx| {
buffer_store.reload_buffers(buffers, push_to_history, cx)
})
}
@ -3589,30 +3515,6 @@ impl Project {
})?
}
async fn handle_reload_buffers(
this: Model<Self>,
envelope: TypedEnvelope<proto::ReloadBuffers>,
mut cx: AsyncAppContext,
) -> Result<proto::ReloadBuffersResponse> {
let sender_id = envelope.original_sender_id()?;
let reload = this.update(&mut cx, |this, cx| {
let mut buffers = HashSet::default();
for buffer_id in &envelope.payload.buffer_ids {
let buffer_id = BufferId::new(*buffer_id)?;
buffers.insert(this.buffer_store.read(cx).get_existing(buffer_id)?);
}
Ok::<_, anyhow::Error>(this.reload_buffers(buffers, false, cx))
})??;
let project_transaction = reload.await?;
let project_transaction = this.update(&mut cx, |this, cx| {
this.serialize_project_transaction_for_peer(project_transaction, sender_id, cx)
})?;
Ok(proto::ReloadBuffersResponse {
transaction: Some(project_transaction),
})
}
async fn handle_synchronize_buffers(
this: Model<Self>,
envelope: TypedEnvelope<proto::SynchronizeBuffers>,
@ -3896,17 +3798,6 @@ impl Project {
})?
}
fn serialize_project_transaction_for_peer(
&mut self,
project_transaction: ProjectTransaction,
peer_id: proto::PeerId,
cx: &mut AppContext,
) -> proto::ProjectTransaction {
self.buffer_store.update(cx, |buffer_store, cx| {
buffer_store.serialize_project_transaction_for_peer(project_transaction, peer_id, cx)
})
}
fn create_buffer_for_peer(
&mut self,
buffer: &Model<Buffer>,