Get more integration tests passing

Antonio Scandurra created

Change summary

crates/project/src/project.rs             | 67 +++++++++++-------------
crates/project/src/worktree.rs            |  8 +-
crates/project_panel/src/project_panel.rs |  6 +-
crates/rpc/src/proto.rs                   |  1 
crates/server/src/rpc.rs                  |  1 
crates/workspace/Cargo.toml               |  1 
crates/workspace/src/workspace.rs         | 45 ++++++----------
7 files changed, 58 insertions(+), 71 deletions(-)

Detailed changes

crates/project/src/project.rs 🔗

@@ -25,7 +25,6 @@ pub use worktree::*;
 
 pub struct Project {
     worktrees: Vec<ModelHandle<Worktree>>,
-    active_worktree: Option<usize>,
     active_entry: Option<ProjectEntry>,
     languages: Arc<LanguageRegistry>,
     client: Arc<client::Client>,
@@ -170,7 +169,6 @@ impl Project {
                     _maintain_remote_id_task,
                 },
                 subscriptions: Vec::new(),
-                active_worktree: None,
                 active_entry: None,
                 languages,
                 client,
@@ -230,7 +228,6 @@ impl Project {
 
         Ok(cx.add_model(|cx| Self {
             worktrees,
-            active_worktree: None,
             active_entry: None,
             collaborators,
             languages,
@@ -270,6 +267,7 @@ impl Project {
                 client.subscribe_to_entity(remote_id, cx, Self::handle_remove_collaborator),
                 client.subscribe_to_entity(remote_id, cx, Self::handle_update_worktree),
                 client.subscribe_to_entity(remote_id, cx, Self::handle_update_buffer),
+                client.subscribe_to_entity(remote_id, cx, Self::handle_save_buffer),
                 client.subscribe_to_entity(remote_id, cx, Self::handle_buffer_saved),
             ]);
         }
@@ -320,10 +318,10 @@ impl Project {
         &self.worktrees
     }
 
-    pub fn worktree_for_id(&self, id: usize) -> Option<ModelHandle<Worktree>> {
+    pub fn worktree_for_id(&self, id: usize, cx: &AppContext) -> Option<ModelHandle<Worktree>> {
         self.worktrees
             .iter()
-            .find(|worktree| worktree.id() == id)
+            .find(|worktree| worktree.read(cx).id() == id)
             .cloned()
     }
 
@@ -346,18 +344,19 @@ impl Project {
                 }
             })?;
 
-            rpc.send(proto::ShareProject { project_id }).await?;
+            rpc.request(proto::ShareProject { project_id }).await?;
+            let mut tasks = Vec::new();
             this.update(&mut cx, |this, cx| {
                 for worktree in &this.worktrees {
                     worktree.update(cx, |worktree, cx| {
-                        worktree
-                            .as_local_mut()
-                            .unwrap()
-                            .share(project_id, cx)
-                            .detach();
+                        let worktree = worktree.as_local_mut().unwrap();
+                        tasks.push(worktree.share(project_id, cx));
                     });
                 }
             });
+            for task in tasks {
+                task.await?;
+            }
             Ok(())
         })
     }
@@ -402,7 +401,7 @@ impl Project {
         path: ProjectPath,
         cx: &mut ModelContext<Self>,
     ) -> Task<Result<ModelHandle<Buffer>>> {
-        if let Some(worktree) = self.worktree_for_id(path.worktree_id) {
+        if let Some(worktree) = self.worktree_for_id(path.worktree_id, cx) {
             worktree.update(cx, |worktree, cx| worktree.open_buffer(path.path, cx))
         } else {
             cx.spawn(|_, _| async move { Err(anyhow!("no such worktree")) })
@@ -463,28 +462,13 @@ impl Project {
 
     fn add_worktree(&mut self, worktree: ModelHandle<Worktree>, cx: &mut ModelContext<Self>) {
         cx.observe(&worktree, |_, _, cx| cx.notify()).detach();
-        if self.active_worktree.is_none() {
-            self.set_active_worktree(Some(worktree.id()), cx);
-        }
         self.worktrees.push(worktree);
         cx.notify();
     }
 
-    fn set_active_worktree(&mut self, worktree_id: Option<usize>, cx: &mut ModelContext<Self>) {
-        if self.active_worktree != worktree_id {
-            self.active_worktree = worktree_id;
-            cx.notify();
-        }
-    }
-
-    pub fn active_worktree(&self) -> Option<ModelHandle<Worktree>> {
-        self.active_worktree
-            .and_then(|worktree_id| self.worktree_for_id(worktree_id))
-    }
-
     pub fn set_active_path(&mut self, entry: Option<ProjectPath>, cx: &mut ModelContext<Self>) {
         let new_active_entry = entry.and_then(|project_path| {
-            let worktree = self.worktree_for_id(project_path.worktree_id)?;
+            let worktree = self.worktree_for_id(project_path.worktree_id, cx)?;
             let entry = worktree.read(cx).entry_for_path(project_path.path)?;
             Some(ProjectEntry {
                 worktree_id: project_path.worktree_id,
@@ -492,9 +476,6 @@ impl Project {
             })
         });
         if new_active_entry != self.active_entry {
-            if let Some(worktree_id) = new_active_entry.map(|e| e.worktree_id) {
-                self.set_active_worktree(Some(worktree_id), cx);
-            }
             self.active_entry = new_active_entry;
             cx.emit(Event::ActiveEntryChanged(new_active_entry));
         }
@@ -637,7 +618,7 @@ impl Project {
         _: Arc<Client>,
         cx: &mut ModelContext<Self>,
     ) -> Result<()> {
-        if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize) {
+        if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
             worktree.update(cx, |worktree, cx| {
                 let worktree = worktree.as_remote_mut().unwrap();
                 worktree.update_from_remote(envelope, cx)
@@ -652,7 +633,7 @@ impl Project {
         _: Arc<Client>,
         cx: &mut ModelContext<Self>,
     ) -> Result<()> {
-        if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize) {
+        if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
             worktree.update(cx, |worktree, cx| {
                 worktree.handle_update_buffer(envelope, cx)
             })?;
@@ -660,13 +641,27 @@ impl Project {
         Ok(())
     }
 
+    pub fn handle_save_buffer(
+        &mut self,
+        envelope: TypedEnvelope<proto::SaveBuffer>,
+        rpc: Arc<Client>,
+        cx: &mut ModelContext<Self>,
+    ) -> Result<()> {
+        if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
+            worktree.update(cx, |worktree, cx| {
+                worktree.handle_save_buffer(envelope, rpc, cx)
+            })?;
+        }
+        Ok(())
+    }
+
     pub fn handle_open_buffer(
         &mut self,
         envelope: TypedEnvelope<proto::OpenBuffer>,
         rpc: Arc<Client>,
         cx: &mut ModelContext<Self>,
     ) -> anyhow::Result<()> {
-        if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize) {
+        if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
             return worktree.update(cx, |worktree, cx| {
                 worktree.handle_open_buffer(envelope, rpc, cx)
             });
@@ -681,7 +676,7 @@ impl Project {
         rpc: Arc<Client>,
         cx: &mut ModelContext<Self>,
     ) -> anyhow::Result<()> {
-        if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize) {
+        if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
             worktree.update(cx, |worktree, cx| {
                 worktree.handle_close_buffer(envelope, rpc, cx)
             })?;
@@ -695,7 +690,7 @@ impl Project {
         _: Arc<Client>,
         cx: &mut ModelContext<Self>,
     ) -> Result<()> {
-        if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize) {
+        if let Some(worktree) = self.worktree_for_id(envelope.payload.worktree_id as usize, cx) {
             worktree.update(cx, |worktree, cx| {
                 worktree.handle_buffer_saved(envelope, cx)
             })?;

crates/project/src/worktree.rs 🔗

@@ -166,7 +166,7 @@ impl Worktree {
         let worktree = cx.update(|cx| {
             cx.add_model(|cx: &mut ModelContext<Worktree>| {
                 let snapshot = Snapshot {
-                    id: cx.model_id(),
+                    id: remote_id as usize,
                     scan_id: 0,
                     abs_path: Path::new("").into(),
                     root_name,
@@ -1034,12 +1034,12 @@ impl LocalWorktree {
         path: &Path,
         cx: &mut ModelContext<Worktree>,
     ) -> Option<ModelHandle<Buffer>> {
-        let handle = cx.handle();
+        let worktree_id = self.id();
         let mut result = None;
         self.open_buffers.retain(|_buffer_id, buffer| {
             if let Some(buffer) = buffer.upgrade(cx.as_ref()) {
                 if let Some(file) = buffer.read(cx.as_ref()).file() {
-                    if file.worktree_id() == handle.id() && file.path().as_ref() == path {
+                    if file.worktree_id() == worktree_id && file.path().as_ref() == path {
                         result = Some(buffer);
                     }
                 }
@@ -1919,7 +1919,7 @@ impl language::File for File {
         version: clock::Global,
         cx: &mut MutableAppContext,
     ) -> Task<Result<(clock::Global, SystemTime)>> {
-        let worktree_id = self.worktree.id() as u64;
+        let worktree_id = self.worktree.read(cx).id() as u64;
         self.worktree.update(cx, |worktree, cx| match worktree {
             Worktree::Local(worktree) => {
                 let rpc = worktree.client.clone();

crates/project_panel/src/project_panel.rs 🔗

@@ -118,7 +118,7 @@ impl ProjectPanel {
                 worktree_id,
                 entry_id,
             } => {
-                if let Some(worktree) = project.read(cx).worktree_for_id(*worktree_id) {
+                if let Some(worktree) = project.read(cx).worktree_for_id(*worktree_id, cx) {
                     if let Some(entry) = worktree.read(cx).entry_for_id(*entry_id) {
                         workspace
                             .open_entry(
@@ -307,7 +307,7 @@ impl ProjectPanel {
     fn selected_entry<'a>(&self, cx: &'a AppContext) -> Option<(&'a Worktree, &'a project::Entry)> {
         let selection = self.selection?;
         let project = self.project.read(cx);
-        let worktree = project.worktree_for_id(selection.worktree_id)?.read(cx);
+        let worktree = project.worktree_for_id(selection.worktree_id, cx)?.read(cx);
         Some((worktree, worktree.entry_for_id(selection.entry_id)?))
     }
 
@@ -374,7 +374,7 @@ impl ProjectPanel {
     fn expand_entry(&mut self, worktree_id: usize, entry_id: usize, cx: &mut ViewContext<Self>) {
         let project = self.project.read(cx);
         if let Some((worktree, expanded_dir_ids)) = project
-            .worktree_for_id(worktree_id)
+            .worktree_for_id(worktree_id, cx)
             .zip(self.expanded_dir_ids.get_mut(&worktree_id))
         {
             let worktree = worktree.read(cx);

crates/rpc/src/proto.rs 🔗

@@ -170,6 +170,7 @@ request_messages!(
     (RegisterWorktree, Ack),
     (SaveBuffer, BufferSaved),
     (SendChannelMessage, SendChannelMessageResponse),
+    (ShareProject, Ack),
     (ShareWorktree, Ack),
     (UpdateBuffer, Ack),
 );

crates/server/src/rpc.rs 🔗

@@ -244,6 +244,7 @@ impl Server {
     ) -> tide::Result<()> {
         self.state_mut()
             .share_project(request.payload.project_id, request.sender_id);
+        self.peer.respond(request.receipt(), proto::Ack {}).await?;
         Ok(())
     }
 

crates/workspace/Cargo.toml 🔗

@@ -11,6 +11,7 @@ test-support = ["client/test-support", "project/test-support"]
 
 [dependencies]
 client = { path = "../client" }
+clock = { path = "../clock" }
 gpui = { path = "../gpui" }
 language = { path = "../language" }
 project = { path = "../project" }

crates/workspace/src/workspace.rs 🔗

@@ -6,6 +6,7 @@ mod status_bar;
 
 use anyhow::{anyhow, Result};
 use client::{Authenticate, ChannelList, Client, User, UserStore};
+use clock::ReplicaId;
 use gpui::{
     action,
     color::Color,
@@ -641,7 +642,7 @@ impl Workspace {
         let worktree = match self
             .project
             .read(cx)
-            .worktree_for_id(project_path.worktree_id)
+            .worktree_for_id(project_path.worktree_id, cx)
         {
             Some(worktree) => worktree,
             None => {
@@ -1007,17 +1008,12 @@ impl Workspace {
                         Align::new(
                             Flex::row()
                                 .with_children(self.render_collaborators(theme, cx))
-                                .with_child(
-                                    self.render_avatar(
-                                        self.user_store.read(cx).current_user().as_ref(),
-                                        self.project
-                                            .read(cx)
-                                            .active_worktree()
-                                            .map(|worktree| worktree.read(cx).replica_id()),
-                                        theme,
-                                        cx,
-                                    ),
-                                )
+                                .with_child(self.render_avatar(
+                                    self.user_store.read(cx).current_user().as_ref(),
+                                    self.project.read(cx).replica_id(),
+                                    theme,
+                                    cx,
+                                ))
                                 .with_children(self.render_connection_status())
                                 .boxed(),
                         )
@@ -1045,12 +1041,7 @@ impl Workspace {
         collaborators
             .into_iter()
             .map(|collaborator| {
-                self.render_avatar(
-                    Some(&collaborator.user),
-                    Some(collaborator.replica_id),
-                    theme,
-                    cx,
-                )
+                self.render_avatar(Some(&collaborator.user), collaborator.replica_id, theme, cx)
             })
             .collect()
     }
@@ -1058,7 +1049,7 @@ impl Workspace {
     fn render_avatar(
         &self,
         user: Option<&Arc<User>>,
-        replica_id: Option<u16>,
+        replica_id: ReplicaId,
         theme: &Theme,
         cx: &mut RenderContext<Self>,
     ) -> ElementBox {
@@ -1076,15 +1067,13 @@ impl Workspace {
                         .boxed(),
                     )
                     .with_child(
-                        AvatarRibbon::new(replica_id.map_or(Default::default(), |id| {
-                            theme.editor.replica_selection_style(id).cursor
-                        }))
-                        .constrained()
-                        .with_width(theme.workspace.titlebar.avatar_ribbon.width)
-                        .with_height(theme.workspace.titlebar.avatar_ribbon.height)
-                        .aligned()
-                        .bottom()
-                        .boxed(),
+                        AvatarRibbon::new(theme.editor.replica_selection_style(replica_id).cursor)
+                            .constrained()
+                            .with_width(theme.workspace.titlebar.avatar_ribbon.width)
+                            .with_height(theme.workspace.titlebar.avatar_ribbon.height)
+                            .aligned()
+                            .bottom()
+                            .boxed(),
                     )
                     .boxed(),
             )