Always open buffers via the project

Max Brunsfeld created

Change summary

crates/editor/src/items.rs        | 10 ++--
crates/project/src/project.rs     | 43 ++++++++++++++++----
crates/project/src/worktree.rs    | 68 ++++----------------------------
crates/workspace/src/workspace.rs | 15 +-----
4 files changed, 53 insertions(+), 83 deletions(-)

Detailed changes

crates/editor/src/items.rs 🔗

@@ -7,7 +7,7 @@ use gpui::{
 use language::{Bias, Buffer, Diagnostic};
 use postage::watch;
 use project::worktree::File;
-use project::{Project, ProjectEntry, ProjectPath, Worktree};
+use project::{Project, ProjectEntry, ProjectPath};
 use std::rc::Rc;
 use std::{fmt::Write, path::PathBuf};
 use text::{Point, Selection};
@@ -28,13 +28,13 @@ struct WeakBufferItemHandle(WeakModelHandle<Buffer>);
 impl PathOpener for BufferOpener {
     fn open(
         &self,
-        worktree: &mut Worktree,
+        project: &mut Project,
         project_path: ProjectPath,
-        cx: &mut ModelContext<Worktree>,
+        cx: &mut ModelContext<Project>,
     ) -> Option<Task<Result<Box<dyn ItemHandle>>>> {
-        let buffer = worktree.open_buffer(project_path.path, cx);
+        let buffer = project.open_buffer(project_path, cx);
         let task = cx.spawn(|_, _| async move {
-            let buffer = buffer.await?.0;
+            let buffer = buffer.await?;
             Ok(Box::new(BufferItemHandle(buffer)) as Box<dyn ItemHandle>)
         });
         Some(task)

crates/project/src/project.rs 🔗

@@ -1088,26 +1088,51 @@ impl Project {
         rpc: Arc<Client>,
         cx: &mut ModelContext<Self>,
     ) -> anyhow::Result<()> {
+        let receipt = envelope.receipt();
+        let peer_id = envelope.original_sender_id()?;
         let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
-        if let Some(worktree) = self.worktree_for_id(worktree_id, cx) {
-            return worktree.update(cx, |worktree, cx| {
-                worktree.handle_open_buffer(envelope, rpc, cx)
-            });
-        } else {
-            Err(anyhow!("no such worktree"))
-        }
+        let worktree = self
+            .worktree_for_id(worktree_id, cx)
+            .ok_or_else(|| anyhow!("no such worktree"))?;
+
+        let task = self.open_buffer(
+            ProjectPath {
+                worktree_id,
+                path: PathBuf::from(envelope.payload.path).into(),
+            },
+            cx,
+        );
+        cx.spawn(|_, mut cx| {
+            async move {
+                let buffer = task.await?;
+                let response = worktree.update(&mut cx, |worktree, cx| {
+                    worktree
+                        .as_local_mut()
+                        .unwrap()
+                        .open_remote_buffer(peer_id, buffer, cx)
+                });
+                rpc.respond(receipt, response).await?;
+                Ok(())
+            }
+            .log_err()
+        })
+        .detach();
+        Ok(())
     }
 
     pub fn handle_close_buffer(
         &mut self,
         envelope: TypedEnvelope<proto::CloseBuffer>,
-        rpc: Arc<Client>,
+        _: Arc<Client>,
         cx: &mut ModelContext<Self>,
     ) -> anyhow::Result<()> {
         let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
         if let Some(worktree) = self.worktree_for_id(worktree_id, cx) {
             worktree.update(cx, |worktree, cx| {
-                worktree.handle_close_buffer(envelope, rpc, cx)
+                worktree
+                    .as_local_mut()
+                    .unwrap()
+                    .close_remote_buffer(envelope, cx)
             })?;
         }
         Ok(())

crates/project/src/worktree.rs 🔗

@@ -286,43 +286,6 @@ impl Worktree {
         }
     }
 
-    pub fn handle_open_buffer(
-        &mut self,
-        envelope: TypedEnvelope<proto::OpenBuffer>,
-        rpc: Arc<Client>,
-        cx: &mut ModelContext<Self>,
-    ) -> anyhow::Result<()> {
-        let receipt = envelope.receipt();
-
-        let response = self
-            .as_local_mut()
-            .unwrap()
-            .open_remote_buffer(envelope, cx);
-
-        cx.background()
-            .spawn(
-                async move {
-                    rpc.respond(receipt, response.await?).await?;
-                    Ok(())
-                }
-                .log_err(),
-            )
-            .detach();
-
-        Ok(())
-    }
-
-    pub fn handle_close_buffer(
-        &mut self,
-        envelope: TypedEnvelope<proto::CloseBuffer>,
-        _: Arc<Client>,
-        cx: &mut ModelContext<Self>,
-    ) -> anyhow::Result<()> {
-        self.as_local_mut()
-            .unwrap()
-            .close_remote_buffer(envelope, cx)
-    }
-
     pub fn diagnostic_summaries<'a>(
         &'a self,
     ) -> impl Iterator<Item = (Arc<Path>, DiagnosticSummary)> + 'a {
@@ -1006,28 +969,17 @@ impl LocalWorktree {
 
     pub fn open_remote_buffer(
         &mut self,
-        envelope: TypedEnvelope<proto::OpenBuffer>,
+        peer_id: PeerId,
+        buffer: ModelHandle<Buffer>,
         cx: &mut ModelContext<Worktree>,
-    ) -> Task<Result<proto::OpenBufferResponse>> {
-        cx.spawn(|this, mut cx| async move {
-            let peer_id = envelope.original_sender_id();
-            let path = Path::new(&envelope.payload.path);
-            let (buffer, _) = this
-                .update(&mut cx, |this, cx| this.open_buffer(path, cx))
-                .await?;
-            this.update(&mut cx, |this, cx| {
-                this.as_local_mut()
-                    .unwrap()
-                    .shared_buffers
-                    .entry(peer_id?)
-                    .or_default()
-                    .insert(buffer.id() as u64, buffer.clone());
-
-                Ok(proto::OpenBufferResponse {
-                    buffer: Some(buffer.update(cx.as_mut(), |buffer, _| buffer.to_proto())),
-                })
-            })
-        })
+    ) -> proto::OpenBufferResponse {
+        self.shared_buffers
+            .entry(peer_id)
+            .or_default()
+            .insert(buffer.id() as u64, buffer.clone());
+        proto::OpenBufferResponse {
+            buffer: Some(buffer.update(cx.as_mut(), |buffer, _| buffer.to_proto())),
+        }
     }
 
     pub fn close_remote_buffer(

crates/workspace/src/workspace.rs 🔗

@@ -125,9 +125,9 @@ pub struct JoinProjectParams {
 pub trait PathOpener {
     fn open(
         &self,
-        worktree: &mut Worktree,
+        project: &mut Project,
         path: ProjectPath,
-        cx: &mut ModelContext<Worktree>,
+        cx: &mut ModelContext<Project>,
     ) -> Option<Task<Result<Box<dyn ItemHandle>>>>;
 }
 
@@ -766,18 +766,11 @@ impl Workspace {
             return Task::ready(Ok(existing_item));
         }
 
-        let worktree = match self.project.read(cx).worktree_for_id(path.worktree_id, cx) {
-            Some(worktree) => worktree,
-            None => {
-                return Task::ready(Err(anyhow!("worktree {} does not exist", path.worktree_id)));
-            }
-        };
-
         let project_path = path.clone();
         let path_openers = self.path_openers.clone();
-        worktree.update(cx, |worktree, cx| {
+        self.project.update(cx, |project, cx| {
             for opener in path_openers.iter() {
-                if let Some(task) = opener.open(worktree, project_path.clone(), cx) {
+                if let Some(task) = opener.open(project, project_path.clone(), cx) {
                     return task;
                 }
             }