From 5350164db91b1efa2d88534729e83071346ec4cc Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 21 Jun 2023 13:38:30 -0700 Subject: [PATCH] Get integration test passing. Wait for expand entry on remote projects. --- crates/collab/src/tests/integration_tests.rs | 21 ++++++ crates/project/src/project.rs | 79 ++++++++++++-------- crates/project/src/worktree.rs | 24 +++--- crates/project_panel/src/project_panel.rs | 6 +- crates/rpc/proto/zed.proto | 7 +- crates/rpc/src/proto.rs | 3 +- 6 files changed, 88 insertions(+), 52 deletions(-) diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index 92b63478cb..2211e53263 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -1266,6 +1266,27 @@ async fn test_share_project( let client_b_collaborator = project.collaborators().get(&client_b_peer_id).unwrap(); assert_eq!(client_b_collaborator.replica_id, replica_id_b); }); + project_b.read_with(cx_b, |project, cx| { + let worktree = project.worktrees(cx).next().unwrap().read(cx); + assert_eq!( + worktree.paths().map(AsRef::as_ref).collect::>(), + [ + Path::new(".gitignore"), + Path::new("a.txt"), + Path::new("b.txt"), + Path::new("ignored-dir"), + ] + ); + }); + + project_b + .update(cx_b, |project, cx| { + let worktree = project.worktrees(cx).next().unwrap(); + let entry = worktree.read(cx).entry_for_path("ignored-dir").unwrap(); + project.expand_entry(worktree_id, entry.id, cx).unwrap() + }) + .await + .unwrap(); project_b.read_with(cx_b, |project, cx| { let worktree = project.worktrees(cx).next().unwrap().read(cx); assert_eq!( diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 5c71202956..1c9336e2ae 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -1073,6 +1073,40 @@ impl Project { } } + pub fn expand_entry( + &mut self, + worktree_id: WorktreeId, + entry_id: ProjectEntryId, + cx: &mut ModelContext, + ) -> Option>> { + let worktree = self.worktree_for_id(worktree_id, cx)?; + if self.is_local() { + worktree.update(cx, |worktree, cx| { + worktree.as_local_mut().unwrap().expand_entry(entry_id, cx) + }) + } else { + let worktree = worktree.downgrade(); + let request = self.client.request(proto::ExpandProjectEntry { + project_id: self.remote_id().unwrap(), + entry_id: entry_id.to_proto(), + }); + Some(cx.spawn_weak(|_, mut cx| async move { + let response = request.await?; + if let Some(worktree) = worktree.upgrade(&cx) { + worktree + .update(&mut cx, |worktree, _| { + worktree + .as_remote_mut() + .unwrap() + .wait_for_snapshot(response.worktree_scan_id as usize) + }) + .await?; + } + Ok(()) + })) + } + } + pub fn shared(&mut self, project_id: u64, cx: &mut ModelContext) -> Result<()> { if self.client_state.is_some() { return Err(anyhow!("project was already shared")); @@ -5404,31 +5438,6 @@ impl Project { Some(ProjectPath { worktree_id, path }) } - pub fn mark_entry_expanded( - &mut self, - worktree_id: WorktreeId, - entry_id: ProjectEntryId, - cx: &mut ModelContext, - ) -> Option<()> { - if self.is_local() { - let worktree = self.worktree_for_id(worktree_id, cx)?; - worktree.update(cx, |worktree, cx| { - worktree - .as_local_mut() - .unwrap() - .expand_entry_for_id(entry_id, cx); - }); - } else if let Some(project_id) = self.remote_id() { - cx.background() - .spawn(self.client.request(proto::ExpandProjectEntry { - project_id, - entry_id: entry_id.to_proto(), - })) - .log_err(); - } - Some(()) - } - pub fn absolute_path(&self, project_path: &ProjectPath, cx: &AppContext) -> Option { let workspace_root = self .worktree_for_id(project_path.worktree_id, cx)? @@ -5736,18 +5745,22 @@ impl Project { envelope: TypedEnvelope, _: Arc, mut cx: AsyncAppContext, - ) -> Result { + ) -> Result { let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id); let worktree = this .read_with(&cx, |this, cx| this.worktree_for_entry(entry_id, cx)) .ok_or_else(|| anyhow!("invalid request"))?; - worktree.update(&mut cx, |worktree, cx| { - worktree - .as_local_mut() - .unwrap() - .expand_entry_for_id(entry_id, cx) - }); - Ok(proto::Ack {}) + worktree + .update(&mut cx, |worktree, cx| { + worktree + .as_local_mut() + .unwrap() + .expand_entry(entry_id, cx) + .ok_or_else(|| anyhow!("invalid entry")) + })? + .await?; + let worktree_scan_id = worktree.read_with(&cx, |worktree, _| worktree.scan_id()) as u64; + Ok(proto::ExpandProjectEntryResponse { worktree_scan_id }) } async fn handle_update_diagnostic_summary( diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 39350f1c8f..2f57b84bba 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -1127,21 +1127,17 @@ impl LocalWorktree { })) } - pub fn expand_entry_for_id( + pub fn expand_entry( &mut self, entry_id: ProjectEntryId, - _cx: &mut ModelContext, - ) -> barrier::Receiver { - let (tx, rx) = barrier::channel(); - if let Some(entry) = self.entry_for_id(entry_id) { - self.scan_requests_tx - .try_send(ScanRequest { - relative_paths: vec![entry.path.clone()], - done: tx, - }) - .ok(); - } - rx + cx: &mut ModelContext, + ) -> Option>> { + let path = self.entry_for_id(entry_id)?.path.clone(); + let mut refresh = self.refresh_entries_for_paths(vec![path]); + Some(cx.background().spawn(async move { + refresh.next().await; + Ok(()) + })) } pub fn refresh_entries_for_paths(&self, paths: Vec>) -> barrier::Receiver { @@ -1337,7 +1333,7 @@ impl RemoteWorktree { self.completed_scan_id >= scan_id } - fn wait_for_snapshot(&mut self, scan_id: usize) -> impl Future> { + pub(crate) fn wait_for_snapshot(&mut self, scan_id: usize) -> impl Future> { let (tx, rx) = oneshot::channel(); if self.observed_snapshot(scan_id) { let _ = tx.send(()); diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index c8dfb7cb38..57934c4adb 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -423,7 +423,7 @@ impl ProjectPanel { Ok(_) => self.select_next(&SelectNext, cx), Err(ix) => { self.project.update(cx, |project, cx| { - project.mark_entry_expanded(worktree_id, entry_id, cx); + project.expand_entry(worktree_id, entry_id, cx); }); expanded_dir_ids.insert(ix, entry_id); @@ -477,7 +477,7 @@ impl ProjectPanel { expanded_dir_ids.remove(ix); } Err(ix) => { - project.mark_entry_expanded(worktree_id, entry_id, cx); + project.expand_entry(worktree_id, entry_id, cx); expanded_dir_ids.insert(ix, entry_id); } } @@ -1084,7 +1084,7 @@ impl ProjectPanel { .worktree_for_id(worktree_id, cx) .zip(self.expanded_dir_ids.get_mut(&worktree_id)) { - project.mark_entry_expanded(worktree_id, entry_id, cx); + project.expand_entry(worktree_id, entry_id, cx); let worktree = worktree.read(cx); if let Some(mut entry) = worktree.entry_for_id(entry_id) { diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 78aab23a44..2bce1ce1e3 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -62,8 +62,9 @@ message Envelope { RenameProjectEntry rename_project_entry = 46; CopyProjectEntry copy_project_entry = 47; DeleteProjectEntry delete_project_entry = 48; - ExpandProjectEntry expand_project_entry = 114; ProjectEntryResponse project_entry_response = 49; + ExpandProjectEntry expand_project_entry = 114; + ExpandProjectEntryResponse expand_project_entry_response = 115; UpdateDiagnosticSummary update_diagnostic_summary = 50; StartLanguageServer start_language_server = 51; @@ -378,6 +379,10 @@ message ExpandProjectEntry { uint64 entry_id = 2; } +message ExpandProjectEntryResponse { + uint64 worktree_scan_id = 1; +} + message ProjectEntryResponse { Entry entry = 1; uint64 worktree_scan_id = 2; diff --git a/crates/rpc/src/proto.rs b/crates/rpc/src/proto.rs index 6311b043d3..4532e798e7 100644 --- a/crates/rpc/src/proto.rs +++ b/crates/rpc/src/proto.rs @@ -201,6 +201,7 @@ messages!( (Ping, Foreground), (PrepareRename, Background), (PrepareRenameResponse, Background), + (ExpandProjectEntryResponse, Foreground), (ProjectEntryResponse, Foreground), (RejoinRoom, Foreground), (RejoinRoomResponse, Foreground), @@ -256,7 +257,7 @@ request_messages!( (CreateRoom, CreateRoomResponse), (DeclineCall, Ack), (DeleteProjectEntry, ProjectEntryResponse), - (ExpandProjectEntry, Ack), + (ExpandProjectEntry, ExpandProjectEntryResponse), (Follow, FollowResponse), (FormatBuffers, FormatBuffersResponse), (GetChannelMessages, GetChannelMessagesResponse),