WIP: Save remote buffers

This commit is contained in:
Antonio Scandurra
2021-07-02 17:02:17 +02:00
parent b8bddd6c05
commit 569a4a1e2d
5 changed files with 140 additions and 28 deletions
+15 -2
View File
@@ -17,8 +17,10 @@ message Envelope {
OpenBufferResponse open_buffer_response = 12;
CloseBuffer close_buffer = 13;
UpdateBuffer update_buffer = 14;
AddGuest add_guest = 15;
RemoveGuest remove_guest = 16;
SaveBuffer save_buffer = 15;
BufferSaved buffer_saved = 16;
AddGuest add_guest = 17;
RemoveGuest remove_guest = 18;
}
}
@@ -90,6 +92,17 @@ message UpdateBuffer {
repeated Operation operations = 3;
}
message SaveBuffer {
uint64 worktree_id = 1;
uint64 buffer_id = 2;
}
message BufferSaved {
uint64 worktree_id = 1;
uint64 buffer_id = 2;
repeated VectorClockEntry version = 3;
}
message User {
uint64 id = 1;
string github_login = 2;
+1
View File
@@ -75,6 +75,7 @@ message!(CloseWorktree);
request_message!(OpenBuffer, OpenBufferResponse);
message!(CloseBuffer);
message!(UpdateBuffer);
request_message!(SaveBuffer, BufferSaved);
message!(AddGuest);
message!(RemoveGuest);
+5 -1
View File
@@ -2538,7 +2538,11 @@ impl workspace::ItemView for Editor {
}
fn save(&mut self, cx: &mut ViewContext<Self>) -> Result<Task<Result<()>>> {
self.buffer.update(cx, |b, cx| b.save(cx))
let save = self.buffer.update(cx, |b, cx| b.save(cx))?;
Ok(cx.spawn(|_, _| async move {
save.await?;
Ok(())
}))
}
fn save_as(
+6 -8
View File
@@ -666,22 +666,20 @@ impl Buffer {
self.file.as_mut()
}
pub fn save(&mut self, cx: &mut ModelContext<Self>) -> Result<Task<Result<()>>> {
pub fn save(&mut self, cx: &mut ModelContext<Self>) -> Result<Task<Result<time::Global>>> {
let file = self
.file
.as_ref()
.ok_or_else(|| anyhow!("buffer has no file"))?;
let text = self.visible_text.clone();
let version = self.version.clone();
let save = file.save(text, cx.as_mut());
let save = file.save(self.remote_id, text, version, cx.as_mut());
Ok(cx.spawn(|this, mut cx| async move {
save.await?;
let version = save.await?;
this.update(&mut cx, |this, cx| {
this.did_save(version, cx).unwrap();
this.did_save(version.clone(), cx).unwrap();
});
Ok(())
Ok(version)
}))
}
@@ -711,7 +709,7 @@ impl Buffer {
})
}
fn did_save(&mut self, version: time::Global, cx: &mut ModelContext<Self>) -> Result<()> {
pub fn did_save(&mut self, version: time::Global, cx: &mut ModelContext<Self>) -> Result<()> {
if let Some(file) = self.file.as_ref() {
self.saved_mtime = file.mtime;
self.saved_version = version;
+113 -17
View File
@@ -8,7 +8,7 @@ use crate::{
language::LanguageRegistry,
rpc::{self, proto},
sum_tree::{self, Cursor, Edit, SumTree},
time::ReplicaId,
time::{self, ReplicaId},
util::Bias,
};
use ::ignore::gitignore::Gitignore;
@@ -58,6 +58,7 @@ pub fn init(cx: &mut MutableAppContext, rpc: rpc::Client) {
rpc.on_message(remote::open_buffer, cx);
rpc.on_message(remote::close_buffer, cx);
rpc.on_message(remote::update_buffer, cx);
rpc.on_message(remote::buffer_saved, cx);
}
#[derive(Clone, Debug)]
@@ -274,21 +275,28 @@ impl Worktree {
Ok(())
}
fn save(
&self,
path: &Path,
text: Rope,
pub fn buffer_saved(
&mut self,
message: proto::BufferSaved,
cx: &mut ModelContext<Self>,
) -> impl Future<Output = Result<()>> {
match self {
Worktree::Local(worktree) => {
let save = worktree.save(path, text, cx);
async move {
save.await?;
Ok(())
}
) -> Result<()> {
if let Worktree::Remote(worktree) = self {
if let Some(buffer) = worktree
.open_buffers
.get(&(message.buffer_id as usize))
.and_then(|buf| buf.upgrade(&cx))
{
buffer.update(cx, |buffer, cx| {
buffer.did_save(message.version.try_into()?, cx);
Result::<_, anyhow::Error>::Ok(())
})?;
}
Worktree::Remote(_) => todo!(),
Ok(())
} else {
Err(anyhow!(
"invalid buffer {} in buffer saved message",
message.buffer_id
))
}
}
}
@@ -649,6 +657,20 @@ impl LocalWorktree {
})
}
pub fn save_remote_buffer(
&self,
envelope: &TypedEnvelope<proto::SaveBuffer>,
cx: &mut ModelContext<Worktree>,
) -> Result<Task<Result<time::Global>>> {
let sender_id = envelope.original_sender_id()?;
let buffer = self
.shared_buffers
.get_mut(&sender_id)
.and_then(|shared_buffers| shared_buffers.get(&envelope.payload.buffer_id))
.ok_or_else(|| anyhow!("unknown buffer id {}", envelope.payload.buffer_id))?;
buffer.update(cx, |buffer, cx| buffer.save(cx))
}
pub fn save_buffer_as(
&self,
buffer: ModelHandle<Buffer>,
@@ -1248,9 +1270,44 @@ impl File {
!self.is_deleted()
}
pub fn save(&self, text: Rope, cx: &mut MutableAppContext) -> impl Future<Output = Result<()>> {
self.worktree
.update(cx, |worktree, cx| worktree.save(&self.path, text, cx))
pub fn save(
&self,
buffer_id: u64,
text: Rope,
version: time::Global,
cx: &mut MutableAppContext,
) -> Task<Result<time::Global>> {
self.worktree.update(cx, |worktree, cx| match worktree {
Worktree::Local(worktree) => {
let rpc = worktree.rpc.clone();
let save = worktree.save(self.path.clone(), text, cx);
cx.spawn(|_, _| async move {
save.await?;
if let Some((rpc, worktree_id)) = rpc {
rpc.send(proto::BufferSaved {
worktree_id,
buffer_id,
version: (&version).into(),
})
.await?;
}
Ok(version)
})
}
Worktree::Remote(worktree) => {
let rpc = worktree.rpc.clone();
let worktree_id = worktree.remote_id;
cx.spawn(|_, _| async move {
let response = rpc
.request(proto::SaveBuffer {
worktree_id,
buffer_id,
})
.await?;
Ok(response.version.try_into()?)
})
}
})
}
pub fn worktree_id(&self) -> usize {
@@ -2138,6 +2195,45 @@ mod remote {
worktree.update(cx, |tree, cx| tree.update_buffer(message, cx))?;
Ok(())
}
pub async fn save_buffer(
envelope: TypedEnvelope<proto::SaveBuffer>,
rpc: &rpc::Client,
cx: &mut AsyncAppContext,
) -> anyhow::Result<()> {
let mut state = rpc.state.lock().await;
let worktree = state.shared_worktree(envelope.payload.worktree_id, cx)?;
let version = worktree
.update(cx, |tree, cx| {
tree.as_local_mut()
.unwrap()
.save_remote_buffer(&envelope, cx)
})?
.await?;
rpc.respond(
envelope.receipt(),
proto::BufferSaved {
worktree_id: envelope.payload.worktree_id,
buffer_id: envelope.payload.buffer_id,
version: (&version).into(),
},
)
.await?;
Ok(())
}
pub async fn buffer_saved(
envelope: TypedEnvelope<proto::BufferSaved>,
rpc: &rpc::Client,
cx: &mut AsyncAppContext,
) -> anyhow::Result<()> {
let mut state = rpc.state.lock().await;
let worktree = state.shared_worktree(envelope.payload.worktree_id, cx)?;
worktree.update(cx, |worktree, cx| {
worktree.buffer_saved(envelope.payload, cx)
})?;
Ok(())
}
}
#[cfg(test)]