From f65eac30a6f3f3d97a425ef2d329cfc08413895f Mon Sep 17 00:00:00 2001 From: dino Date: Wed, 15 Apr 2026 17:56:26 +0100 Subject: [PATCH] checkpoint: more remote work --- 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(-) diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index fa84a95837d390e4c81c09c1e11d7fc4ad704f20..59ddd50dc5224ceffa9b63c0ef72de61d04b04db 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -442,6 +442,7 @@ impl Server { .add_request_handler(forward_mutating_project_request::) .add_request_handler(forward_mutating_project_request::) .add_message_handler(broadcast_project_message_from_host::) + // 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); diff --git a/crates/fs/src/fs.rs b/crates/fs/src/fs.rs index 88a7c675475a7111451061b14b6314638c417faa..0e15bdd26fde89692fe036fa34eb19372e479234 100644 --- a/crates/fs/src/fs.rs +++ b/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 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, executor: BackgroundExecutor, diff --git a/crates/project/src/worktree_store.rs b/crates/project/src/worktree_store.rs index 1302150d2f7bb082aa442337b639691ace10c011..be95a6b0ded02ed3527195433adf6eb1ab1f781b 100644 --- a/crates/project/src/worktree_store.rs +++ b/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, }) } diff --git a/crates/proto/proto/worktree.proto b/crates/proto/proto/worktree.proto index 84225a96a56669b4a303b5714f0b1fb4ada7c2c7..bc00e814628610167564ea0d632744dac936b3f9 100644 --- a/crates/proto/proto/worktree.proto +++ b/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 { diff --git a/crates/proto/proto/zed.proto b/crates/proto/proto/zed.proto index 8b62754d7af40b7c4f5e1a87ad42899d682ba453..676ad8c389062b827910d3af3de4c2570c78a7f4 100644 --- a/crates/proto/proto/zed.proto +++ b/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; diff --git a/crates/proto/src/proto.rs b/crates/proto/src/proto.rs index b77bd02313c13a9b04eb7762a97f9e77ac8cbaf8..8e0e3251bedd662f93b4713f9c980b520f59085d 100644 --- a/crates/proto/src/proto.rs +++ b/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, diff --git a/crates/remote_server/src/headless_project.rs b/crates/remote_server/src/headless_project.rs index 63e9b4b787230ea877cdc92e1fdcdd6daa86dc0c..18d6965b4d436363b5ad337aa5d8c5a054ddb9ab 100644 --- a/crates/remote_server/src/headless_project.rs +++ b/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)); diff --git a/crates/rpc/src/peer.rs b/crates/rpc/src/peer.rs index 73be0f19fe20ba9228bb3264a812c7404543aeff..9b17e44738a00565e90cbe2cff31762adee08d70 100644 --- a/crates/rpc/src/peer.rs +++ b/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)); diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index ae9fbde907da90a52f18cf05ed4677449ba6f76a..4af12fd646f44ae8b36326bbf82a9ee5e09473f8 100644 --- a/crates/worktree/src/worktree.rs +++ b/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, cx: &mut AsyncApp, ) -> Result { @@ -2137,21 +2131,20 @@ impl RemoteWorktree { }) } - fn delete_entry( + fn trash_entry( &self, entry_id: ProjectEntryId, - trash: bool, cx: &Context, - ) -> Option>>> { - let response = self.client.request(proto::DeleteProjectEntry { + ) -> Task> { + 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) -> Task> { + 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; }