fix: ensure that the entry is already available after remote restore

dino created

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`.

Change summary

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(-)

Detailed changes

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)
             }

crates/project/src/project.rs 🔗

@@ -2620,7 +2620,7 @@ impl Project {
 
             Ok(ProjectPath {
                 worktree_id: worktree_id,
-                path: entry.path.clone(),
+                path: entry.path,
             })
         })
     }

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;
 }
 

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
         })
     }