checkpoint: more remote work

dino created

Change summary

crates/collab/src/rpc.rs                     |  1 
crates/fs/src/fs.rs                          | 12 ++++
crates/project/src/worktree_store.rs         |  2 
crates/proto/proto/worktree.proto            | 15 +++--
crates/proto/proto/zed.proto                 |  4 +
crates/proto/src/proto.rs                    |  4 +
crates/remote_server/src/headless_project.rs |  3 
crates/rpc/src/peer.rs                       |  5 +
crates/worktree/src/worktree.rs              | 57 +++++++++++++--------
9 files changed, 70 insertions(+), 33 deletions(-)

Detailed changes

crates/collab/src/rpc.rs 🔗

@@ -442,6 +442,7 @@ impl Server {
             .add_request_handler(forward_mutating_project_request::<proto::CheckForPushedCommits>)
             .add_request_handler(forward_mutating_project_request::<proto::ToggleLspLogs>)
             .add_message_handler(broadcast_project_message_from_host::<proto::LanguageServerLog>)
+            // TODO!(yara) add new message here
             .add_request_handler(share_agent_thread)
             .add_request_handler(get_shared_agent_thread)
             .add_request_handler(forward_project_search_chunk);

crates/fs/src/fs.rs 🔗

@@ -1,7 +1,7 @@
 pub mod fs_watcher;
 
 use parking_lot::Mutex;
-use slotmap::SlotMap;
+use slotmap::{KeyData, SlotMap};
 use std::ffi::OsString;
 use std::sync::atomic::{AtomicU8, AtomicUsize, Ordering};
 use std::time::Instant;
@@ -399,6 +399,16 @@ impl From<MTime> for proto::Timestamp {
 // TODO!(yara) for protocol get out u64 via keydata().ffi()
 slotmap::new_key_type! { pub struct TrashId; }
 
+impl TrashId {
+    pub fn from_u64(value: u64) -> Self {
+        KeyData::from_ffi(value).into()
+    }
+
+    pub fn to_u64(&self) -> u64 {
+        self.0.as_ffi()
+    }
+}
+
 pub struct RealFs {
     bundled_git_binary_path: Option<PathBuf>,
     executor: BackgroundExecutor,

crates/project/src/worktree_store.rs 🔗

@@ -1158,7 +1158,6 @@ impl WorktreeStore {
         Ok(proto::ProjectEntryResponse {
             entry: entry.as_ref().map(|entry| entry.into()),
             worktree_scan_id: scan_id as u64,
-            trashed_entry: None,
         })
     }
 
@@ -1222,7 +1221,6 @@ impl WorktreeStore {
                 CreatedEntry::Excluded { .. } => None,
             },
             worktree_scan_id: scan_id as u64,
-            trashed_entry: None,
         })
     }
 

crates/proto/proto/worktree.proto 🔗

@@ -116,9 +116,15 @@ message CopyProjectEntry {
 message DeleteProjectEntry {
   uint64 project_id = 1;
   uint64 entry_id = 2;
+  // TODO! (yara) depracate in many week
   bool use_trash = 3;
 }
 
+message TrashProjectEntry {
+  uint64 project_id = 1;
+  uint64 entry_id = 2;
+}
+
 message ExpandProjectEntry {
   uint64 project_id = 1;
   uint64 entry_id = 2;
@@ -137,17 +143,14 @@ message ExpandAllForProjectEntryResponse {
   uint64 worktree_scan_id = 1;
 }
 
+// TODO!(yara) split this up in future PR
 message ProjectEntryResponse {
   optional Entry entry = 1;
   uint64 worktree_scan_id = 2;
-  // TODO!(dino): new message for delete?
-  optional TrashedEntry trashed_entry = 3;
 }
 
-message TrashedEntry {
-  string trash_id = 1;
-  string file_name = 2;
-  string original_parent_path = 3;
+message TrashProjectEntryResponse {
+  uint64 trash_id = 1;
 }
 
 message UpdateWorktreeSettings {

crates/proto/proto/zed.proto 🔗

@@ -476,7 +476,9 @@ message Envelope {
     GitDiffCheckpoints git_diff_checkpoints = 438;
     GitDiffCheckpointsResponse git_diff_checkpoints_response = 439;
     GitGetHeadSha git_get_head_sha = 440;
-    GitGetHeadShaResponse git_get_head_sha_response = 441; // current max
+    GitGetHeadShaResponse git_get_head_sha_response = 441;
+    TrashProjectEntry trash_project_entry = 442;
+    TrashProjectEntryResponse trash_project_entry_response = 443; // current max
   }
 
   reserved 87 to 88;

crates/proto/src/proto.rs 🔗

@@ -64,6 +64,8 @@ messages!(
     (DeleteChannel, Foreground),
     (DeleteNotification, Foreground),
     (DeleteProjectEntry, Foreground),
+    (TrashProjectEntry, Foreground),
+    (TrashProjectEntryResponse, Foreground),
     (DownloadFileByPath, Background),
     (DownloadFileResponse, Background),
     (EndStream, Foreground),
@@ -387,6 +389,7 @@ request_messages!(
     (DeclineCall, Ack),
     (DeleteChannel, Ack),
     (DeleteProjectEntry, ProjectEntryResponse),
+    (TrashProjectEntry, TrashProjectEntryResponse),
     (DownloadFileByPath, DownloadFileResponse),
     (ExpandProjectEntry, ExpandProjectEntryResponse),
     (ExpandAllForProjectEntry, ExpandAllForProjectEntryResponse),
@@ -612,6 +615,7 @@ entity_messages!(
     GetDocumentColor,
     GetFoldingRanges,
     DeleteProjectEntry,
+    TrashProjectEntry,
     ExpandProjectEntry,
     ExpandAllForProjectEntry,
     FindSearchCandidates,

crates/remote_server/src/headless_project.rs 🔗

@@ -309,6 +309,7 @@ impl HeadlessProject {
         session.add_entity_request_handler(Self::handle_restrict_worktrees);
         session.add_entity_request_handler(Self::handle_download_file_by_path);
 
+        // TODO!(yara) add message handlers here (+ look for the other side, recv on UI side client)
         session.add_entity_message_handler(Self::handle_find_search_candidates_cancel);
         session.add_entity_request_handler(BufferStore::handle_update_buffer);
         session.add_entity_message_handler(BufferStore::handle_close_buffer);
@@ -326,7 +327,7 @@ impl HeadlessProject {
         session.add_request_handler(cx.weak_entity(), Self::handle_kill_kernel);
 
         BufferStore::init(&session);
-        WorktreeStore::init(&session);
+        WorktreeStore::init(&session); // TODO!(yara) maybe here
         SettingsObserver::init(&session);
         LspStore::init(&session);
         TaskStore::init(Some(&session));

crates/rpc/src/peer.rs 🔗

@@ -463,15 +463,18 @@ impl Peer {
                 .lock()
                 .as_mut()
                 .context("connection was closed")?
+                // requesting to forward the response on the oneshot tx
+                // when it's envelope.id matches the one for the request we are about to send
                 .insert(envelope.id, tx);
             connection
                 .outgoing_tx
+                // request that the message is send at some point in the future
                 .unbounded_send(Message::Envelope(envelope))
                 .context("connection was closed")?;
             Ok(())
         });
         async move {
-            send?;
+            send?; // wait for reception
             let (response, received_at, _barrier) = rx.await.context("connection was closed")?;
             if let Some(proto::envelope::Payload::Error(error)) = &response.payload {
                 return Err(RpcError::from_proto(error, type_name));

crates/worktree/src/worktree.rs 🔗

@@ -821,7 +821,7 @@ impl Worktree {
                     is_directory,
                 });
                 cx.spawn(async move |this, cx| {
-                    let response = request.await?;
+                    let response = request.await?; // TODO!(yara) HERE
                     match response.entry {
                         Some(entry) => this
                             .update(cx, |worktree, cx| {
@@ -982,7 +982,6 @@ impl Worktree {
                 CreatedEntry::Excluded { .. } => None,
             },
             worktree_scan_id: scan_id as u64,
-            trashed_entry: None,
         })
     }
 
@@ -1007,11 +1006,6 @@ impl Worktree {
         Ok(proto::ProjectEntryResponse {
             entry: None,
             worktree_scan_id: scan_id as u64,
-            trashed_entry: trash_id.map(|e| proto::TrashedEntry {
-                trash_id: e.id.to_string_lossy().to_string(),
-                file_name: e.name.to_string_lossy().to_string(),
-                original_parent_path: e.original_parent.to_string_lossy().to_string(),
-            }),
         })
     }
 
@@ -1748,7 +1742,7 @@ impl LocalWorktree {
     }
 
     pub async fn restore_entry(
-        trash_entry: TrashedEntry,
+        trash_entry: TrashId,
         this: Entity<Worktree>,
         cx: &mut AsyncApp,
     ) -> Result<RelPathBuf> {
@@ -2137,21 +2131,20 @@ impl RemoteWorktree {
         })
     }
 
-    fn delete_entry(
+    fn trash_entry(
         &self,
         entry_id: ProjectEntryId,
-        trash: bool,
         cx: &Context<Worktree>,
-    ) -> Option<Task<Result<Option<TrashedEntry>>>> {
-        let response = self.client.request(proto::DeleteProjectEntry {
+    ) -> Task<Result<TrashId>> {
+        let response = self.client.request(proto::TrashProjectEntry {
             project_id: self.project_id,
             entry_id: entry_id.to_proto(),
-            use_trash: trash,
         });
-        Some(cx.spawn(async move |this, cx| {
+
+        cx.spawn(async move |this, cx| {
             let response = response.await?;
             let scan_id = response.worktree_scan_id as usize;
-            let trashed_entry = response.trashed_entry;
+            let trash_id = response.trash_id;
 
             this.update(cx, move |this, _| {
                 this.as_remote_mut().unwrap().wait_for_snapshot(scan_id)
@@ -2165,12 +2158,33 @@ impl RemoteWorktree {
                 this.snapshot = snapshot.clone();
             })?;
 
-            Ok(trashed_entry.map(|e| TrashedEntry {
-                id: e.trash_id.into(),
-                name: e.file_name.into(),
-                original_parent: e.original_parent_path.into(),
-            }))
-        }))
+            Ok(TrashId::from_u64(trash_id))
+        })
+    }
+
+    fn delete_entry(&self, entry_id: ProjectEntryId, cx: &Context<Worktree>) -> Task<Result<()>> {
+        let response = self.client.request(proto::DeleteProjectEntry {
+            project_id: self.project_id,
+            entry_id: entry_id.to_proto(),
+            use_trash: false, // deprecated
+        });
+
+        cx.spawn(async move |this, cx| {
+            let response = response.await?;
+            let scan_id = response.worktree_scan_id as usize;
+
+            this.update(cx, move |this, _| {
+                this.as_remote_mut().unwrap().wait_for_snapshot(scan_id)
+            })?
+            .await?;
+
+            this.update(cx, |this, _| {
+                let this = this.as_remote_mut().unwrap();
+                let snapshot = &mut this.background_snapshot.lock().0;
+                snapshot.delete_entry(entry_id);
+                this.snapshot = snapshot.clone();
+            })
+        })
     }
 
     fn copy_external_entries(
@@ -2460,6 +2474,7 @@ impl Snapshot {
         }
 
         self.scan_id = update.scan_id as usize;
+        /// TODO!(yara) batch the scans
         if update.is_last_update {
             self.completed_scan_id = update.scan_id as usize;
         }