Add protos

Julia Ryan created

Change summary

crates/project/src/project.rs                | 17 ++++++++++
crates/proto/proto/worktree.proto            | 11 ++++++
crates/proto/proto/zed.proto                 |  5 ++
crates/proto/src/proto.rs                    |  3 +
crates/remote_server/src/headless_project.rs | 29 ++++++++++++++++++
crates/worktree/src/worktree.rs              | 35 ++++++++++++++++++---
6 files changed, 94 insertions(+), 6 deletions(-)

Detailed changes

crates/project/src/project.rs 🔗

@@ -1035,6 +1035,7 @@ impl Project {
         client.add_entity_request_handler(Self::handle_open_new_buffer);
         client.add_entity_message_handler(Self::handle_create_buffer_for_peer);
         client.add_entity_message_handler(Self::handle_toggle_lsp_logs);
+        client.add_entity_request_handler(Self::handle_load_binary_file);
 
         WorktreeStore::init(&client);
         BufferStore::init(&client);
@@ -5169,6 +5170,22 @@ impl Project {
         })
     }
 
+    async fn handle_load_binary_file(
+        this: Entity<Self>,
+        envelope: TypedEnvelope<proto::LoadBinaryFile>,
+        mut cx: AsyncApp,
+    ) -> Result<proto::BinaryFileResponse> {
+        // let peer_id = envelope.original_sender_id()?;
+        // let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
+        // let path = RelPath::from_proto(&envelope.payload.path)?;
+        // let open_buffer = this
+        //     .update(&mut cx, |this, cx| {
+        //         this.open_buffer(ProjectPath { worktree_id, path }, cx)
+        //     })?
+        //     .await?;
+        // Project::respond_to_open_buffer_request(this, open_buffer, peer_id, &mut cx)
+    }
+
     fn set_worktrees_from_proto(
         &mut self,
         worktrees: Vec<proto::WorktreeMetadata>,

crates/proto/proto/worktree.proto 🔗

@@ -158,3 +158,14 @@ message UpdateUserSettings {
     uint64 project_id = 1;
     string contents = 2;
 }
+
+message LoadBinaryFile{
+    uint64 project_id = 1;
+    uint64 worktree_id = 2;
+    string path = 3;
+}
+
+message BinaryFileResponse {
+    Entry entry = 1;
+    bytes content = 2;
+}

crates/proto/proto/zed.proto 🔗

@@ -427,7 +427,10 @@ message Envelope {
         GetTreeDiffResponse get_tree_diff_response = 385;
 
         GetBlobContent get_blob_content = 386;
-        GetBlobContentResponse get_blob_content_response = 387; // current max
+        GetBlobContentResponse get_blob_content_response = 387;
+
+        LoadBinaryFile load_binary_file = 388;
+        BinaryFileResponse binary_file_response = 389; // current max
     }
 
     reserved 87 to 88;

crates/proto/src/proto.rs 🔗

@@ -157,6 +157,8 @@ messages!(
     (ListToolchainsResponse, Foreground),
     (LoadCommitDiff, Foreground),
     (LoadCommitDiffResponse, Foreground),
+    (LoadBinaryFile, Background),
+    (BinaryFileResponse, Background),
     (LspExtExpandMacro, Background),
     (LspExtExpandMacroResponse, Background),
     (LspExtOpenDocs, Background),
@@ -389,6 +391,7 @@ request_messages!(
     (LeaveChannelBuffer, Ack),
     (LeaveRoom, Ack),
     (LoadCommitDiff, LoadCommitDiffResponse),
+    (LoadBinaryFile, BinaryFileResponse),
     (MarkNotificationRead, Ack),
     (MoveChannel, Ack),
     (OnTypeFormatting, OnTypeFormattingResponse),

crates/remote_server/src/headless_project.rs 🔗

@@ -259,6 +259,7 @@ impl HeadlessProject {
         session.add_entity_request_handler(Self::handle_open_server_settings);
         session.add_entity_request_handler(Self::handle_get_directory_environment);
         session.add_entity_message_handler(Self::handle_toggle_lsp_logs);
+        session.add_entity_request_handler(Self::handle_load_binary_file);
 
         session.add_entity_request_handler(BufferStore::handle_update_buffer);
         session.add_entity_message_handler(BufferStore::handle_close_buffer);
@@ -629,6 +630,34 @@ impl HeadlessProject {
         })
     }
 
+    pub async fn handle_load_binary_file(
+        this: Entity<Self>,
+        message: TypedEnvelope<proto::OpenBufferByPath>,
+        mut cx: AsyncApp,
+    ) -> Result<proto::BinaryFileResposne> {
+        // let worktree_id = WorktreeId::from_proto(message.payload.worktree_id);
+        // let path = RelPath::from_proto(&message.payload.path)?;
+        // let (buffer_store, buffer) = this.update(&mut cx, |this, cx| {
+        //     let buffer_store = this.buffer_store.clone();
+        //     let buffer = this.buffer_store.update(cx, |buffer_store, cx| {
+        //         buffer_store.open_buffer(ProjectPath { worktree_id, path }, cx)
+        //     });
+        //     anyhow::Ok((buffer_store, buffer))
+        // })??;
+
+        // let buffer = buffer.await?;
+        // let buffer_id = buffer.read_with(&cx, |b, _| b.remote_id())?;
+        // buffer_store.update(&mut cx, |buffer_store, cx| {
+        //     buffer_store
+        //         .create_buffer_for_peer(&buffer, REMOTE_SERVER_PEER_ID, cx)
+        //         .detach_and_log_err(cx);
+        // })?;
+
+        // Ok(proto::OpenBufferResponse {
+        //     buffer_id: buffer_id.to_proto(),
+        // })
+    }
+
     async fn handle_find_search_candidates(
         this: Entity<Self>,
         envelope: TypedEnvelope<proto::FindSearchCandidates>,

crates/worktree/src/worktree.rs 🔗

@@ -719,9 +719,7 @@ impl Worktree {
     ) -> Task<Result<LoadedBinaryFile>> {
         match self {
             Worktree::Local(this) => this.load_binary_file(path, cx),
-            Worktree::Remote(_) => {
-                Task::ready(Err(anyhow!("remote worktrees can't yet load binary files")))
-            }
+            Worktree::Remote(this) => this.load_binary_file(path, cx),
         }
     }
 
@@ -1970,7 +1968,7 @@ impl RemoteWorktree {
         paths_to_copy: Vec<Arc<Path>>,
         local_fs: Arc<dyn Fs>,
         cx: &Context<Worktree>,
-    ) -> Task<anyhow::Result<Vec<ProjectEntryId>>> {
+    ) -> Task<Result<Vec<ProjectEntryId>>> {
         let client = self.client.clone();
         let worktree_id = self.id().to_proto();
         let project_id = self.project_id;
@@ -2028,6 +2026,33 @@ impl RemoteWorktree {
             Ok(copied_entry_ids)
         })
     }
+
+    fn load_binary_file(
+        &self,
+        path: &RelPath,
+        cx: &Context<Worktree>,
+    ) -> Task<Result<LoadedBinaryFile>> {
+        let path = Arc::from(path);
+        let abs_path = self.absolutize(&path);
+        // let fs = self.fs.clone();
+        // let entry = self.refresh_entry(path.clone(), None, cx);
+        // let is_private = self.is_path_private(&path);
+        let response = self.client.request(proto::LoadBinaryFile{
+            path: path.to_proto(),
+            project_id: self.project_id(),
+            worktree_id: self.id().to_proto(),
+        });
+        let worktree = cx.weak_entity();
+        cx.background_spawn(async move {
+            let proto::BinaryFileResponse { entry, content } = response.await?;
+            let worktree = worktree.upgrade().context("worktree was dropped")?;
+            // TODO: check is_private
+            Ok(LoadedBinaryFile {
+                file: File::for_entry(entry.unwrap().into(), worktree),
+                content,
+            })
+        })
+    }
 }
 
 impl Snapshot {
@@ -5551,7 +5576,7 @@ impl CreatedEntry {
     }
 }
 
-fn parse_gitfile(content: &str) -> anyhow::Result<&Path> {
+fn parse_gitfile(content: &str) -> Result<&Path> {
     let path = content
         .strip_prefix("gitdir:")
         .with_context(|| format!("parsing gitfile content {content:?}"))?;