From 34a7355b22d27b4fc31bffcd4e08b9e6bef4e14c Mon Sep 17 00:00:00 2001 From: dino Date: Fri, 17 Apr 2026 16:22:36 +0100 Subject: [PATCH] fix: ensure that the entry is already available after remote restore The `RestoreProjectEntryResponse` was simply returning the `entry_id`, instead of the whole entry information. On the `RemoteWorktree::restore_worktree` side, the `entry_id` was being used to obtain the entry, so as to then insert the proto entry, using `RemoteWorktree::insert_entry`. Unfortunately, this could lead to panics, for example: 1. Create a new file 2. Undo, which will trash file 3. Redo, which will restore the file As far as I can tell, this was happening because the `RemoteWorktree` wasn't yet updated on our end, so there wasn't actually an entry being returned for `RemoteWorktree::entry_for_id`. As such, this commit updates the `entry_id` field, and type, in `RestoreProjectEntryResponse` to the actual `Entry` data, just like in `ProjectEntryResponse`. --- crates/fs/src/fs.rs | 2 +- crates/project/src/project.rs | 2 +- crates/proto/proto/worktree.proto | 2 +- crates/worktree/src/worktree.rs | 24 +++++++++--------------- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/crates/fs/src/fs.rs b/crates/fs/src/fs.rs index 49a876a3fcb06c68ef681e2729d5b506794f69b1..3f04424277630ff0ddf5127255f315305221e682 100644 --- a/crates/fs/src/fs.rs +++ b/crates/fs/src/fs.rs @@ -2856,7 +2856,7 @@ impl Fs for FakeFs { .lock() .trash .lock() - .insert((trashed_entry.clone(), fake_entry)); + .insert((trashed_entry, fake_entry)); Ok(trash_id) } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 142da3b5095ee54795ba7ee69bb27bf83360fc19..c4e5c296721b32898cf203497f4dcc885533cbbd 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2620,7 +2620,7 @@ impl Project { Ok(ProjectPath { worktree_id: worktree_id, - path: entry.path.clone(), + path: entry.path, }) }) } diff --git a/crates/proto/proto/worktree.proto b/crates/proto/proto/worktree.proto index 3226f788aa947298616fdaec17b47777918d3799..2e55694d09769a82747845ae08ea8bbc5b82f338 100644 --- a/crates/proto/proto/worktree.proto +++ b/crates/proto/proto/worktree.proto @@ -161,7 +161,7 @@ message TrashProjectEntryResponse { } message RestoreProjectEntryResponse { - uint64 entry_id = 1; + Entry entry = 1; uint64 worktree_scan_id = 2; } diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index 40982cd8006c54d6de852a1675ca81b25f329d21..a57a62ba39c20211bb7fb2e5bd7ea68f1c35c9bd 100644 --- a/crates/worktree/src/worktree.rs +++ b/crates/worktree/src/worktree.rs @@ -1062,7 +1062,7 @@ impl Worktree { let entry = task.await?; Ok(proto::RestoreProjectEntryResponse { - entry_id: entry.id.to_proto(), + entry: Some(proto::Entry::from(&entry)), worktree_scan_id: scan_id as u64, }) } @@ -2261,21 +2261,15 @@ impl RemoteWorktree { cx.spawn(async move |this, cx| { let response = request.await?; let scan_id = response.worktree_scan_id as usize; - let entry_id = ProjectEntryId(response.entry_id as usize); + let proto_entry = response.entry.context("Missing entry in in response")?; - let (task, entry) = this.update(cx, |worktree, cx| { - // TODO!(dino): Remove `entry_for_id(entry_id).unwrap()` call, - // avoid unwrapping. - let remote_worktree = worktree.as_remote_mut().unwrap(); - let entry = remote_worktree.entry_for_id(entry_id).unwrap().clone(); - let proto_entry = proto::Entry::from(&entry); - let task = remote_worktree.insert_entry(proto_entry, scan_id, cx); - - (task, entry) - })?; - - task.await?; - Ok(entry) + this.update(cx, move |worktree, cx| { + worktree + .as_remote_mut() + .unwrap() + .insert_entry(proto_entry, scan_id, cx) + })? + .await }) }