rebase fix - almost have serialize_workspace piped to the workspace constructor. Just a few compile errors left

K Simmons created

Change summary

crates/db/src/workspace.rs        |   5 
crates/workspace/src/workspace.rs | 164 +++++++++++++++++++-------------
crates/zed/src/zed.rs             |   6 
3 files changed, 106 insertions(+), 69 deletions(-)

Detailed changes

crates/db/src/workspace.rs 🔗

@@ -1,4 +1,7 @@
-use std::{path::Path, sync::Arc};
+use std::{
+    path::{Path, PathBuf},
+    sync::Arc,
+};
 
 use crate::pane::{PaneGroupId, PaneId, SerializedPane, SerializedPaneGroup};
 

crates/workspace/src/workspace.rs 🔗

@@ -15,7 +15,7 @@ use anyhow::{anyhow, Context, Result};
 use call::ActiveCall;
 use client::{proto, Client, PeerId, TypedEnvelope, UserStore};
 use collections::{hash_map, HashMap, HashSet};
-use db::{SerializedWorkspace, WorkspaceId};
+use db::{Db, SerializedWorkspace, WorkspaceId};
 use dock::{DefaultItemFactory, Dock, ToggleDockButton};
 use drag_and_drop::DragAndDrop;
 use fs::{self, Fs};
@@ -180,7 +180,11 @@ pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
         let app_state = Arc::downgrade(&app_state);
         move |_: &NewFile, cx: &mut MutableAppContext| {
             if let Some(app_state) = app_state.upgrade() {
-                open_new(&app_state, cx)
+                let task = open_new(&app_state, cx);
+                cx.spawn(|_| async {
+                    task.await;
+                })
+                .detach();
             }
         }
     });
@@ -188,7 +192,11 @@ pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
         let app_state = Arc::downgrade(&app_state);
         move |_: &NewWindow, cx: &mut MutableAppContext| {
             if let Some(app_state) = app_state.upgrade() {
-                open_new(&app_state, cx)
+                let task = open_new(&app_state, cx);
+                cx.spawn(|_| async {
+                    task.await;
+                })
+                .detach();
             }
         }
     });
@@ -1112,8 +1120,8 @@ enum FollowerItem {
 
 impl Workspace {
     pub fn new(
-        project: ModelHandle<Project>,
         serialized_workspace: SerializedWorkspace,
+        project: ModelHandle<Project>,
         dock_default_factory: DefaultItemFactory,
         cx: &mut ViewContext<Self>,
     ) -> Self {
@@ -1242,6 +1250,74 @@ impl Workspace {
         this
     }
 
+    fn new_local<T, F>(
+        abs_paths: &[PathBuf],
+        app_state: &Arc<AppState>,
+        cx: &mut MutableAppContext,
+        callback: F,
+    ) -> Task<T>
+    where
+        T: 'static,
+        F: 'static + FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T,
+    {
+        let project_handle = Project::local(
+            app_state.client.clone(),
+            app_state.user_store.clone(),
+            app_state.project_store.clone(),
+            app_state.languages.clone(),
+            app_state.fs.clone(),
+            cx,
+        );
+
+        cx.spawn(|mut cx| async move {
+            // Get project paths for all of the abs_paths
+            let mut worktree_roots: HashSet<Arc<Path>> = Default::default();
+            let mut project_paths = Vec::new();
+            for path in abs_paths {
+                if let Some((worktree, project_entry)) = cx
+                    .update(|cx| Workspace::project_path_for_path(project_handle, path, true, cx))
+                    .await
+                    .log_err()
+                {
+                    worktree_roots.insert(worktree.read_with(&mut cx, |tree, _| tree.abs_path()));
+                    project_paths.push(project_entry);
+                }
+            }
+
+            // Use the resolved worktree roots to get the serialized_db from the database
+            let serialized_workspace = cx.read(|cx| {
+                cx.global::<Db>()
+                    .workspace_for_worktree_roots(&Vec::from_iter(worktree_roots.into_iter())[..])
+            });
+
+            // Use the serialized workspace to construct the new window
+            let (_, workspace) = cx.add_window((app_state.build_window_options)(), |cx| {
+                let mut workspace = Workspace::new(
+                    serialized_workspace,
+                    project_handle,
+                    app_state.default_item_factory,
+                    cx,
+                );
+                (app_state.initialize_workspace)(&mut workspace, &app_state, cx);
+                workspace
+            });
+
+            // Call open path for each of the project paths
+            // (this will bring them to the front if they were in kthe serialized workspace)
+            let tasks = workspace.update(&mut cx, |workspace, cx| {
+                let tasks = Vec::new();
+                for path in project_paths {
+                    tasks.push(workspace.open_path(path, true, cx));
+                }
+                tasks
+            });
+            futures::future::join_all(tasks.into_iter()).await;
+
+            // Finally call callback on the workspace
+            workspace.update(&mut cx, |workspace, cx| callback(workspace, cx))
+        })
+    }
+
     pub fn weak_handle(&self) -> WeakViewHandle<Self> {
         self.weak_self.clone()
     }
@@ -1289,34 +1365,18 @@ impl Workspace {
     /// to the callback. Otherwise, a new empty window will be created.
     pub fn with_local_workspace<T, F>(
         &mut self,
+        app_state: &Arc<AppState>,
         cx: &mut ViewContext<Self>,
-        app_state: Arc<AppState>,
         callback: F,
-    ) -> T
+    ) -> Task<T>
     where
         T: 'static,
         F: FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T,
     {
         if self.project.read(cx).is_local() {
-            callback(self, cx)
+            Task::Ready(Some(callback(self, cx)))
         } else {
-            let (_, workspace) = cx.add_window((app_state.build_window_options)(), |cx| {
-                let mut workspace = Workspace::new(
-                    Project::local(
-                        app_state.client.clone(),
-                        app_state.user_store.clone(),
-                        app_state.project_store.clone(),
-                        app_state.languages.clone(),
-                        app_state.fs.clone(),
-                        cx,
-                    ),
-                    app_state.default_item_factory,
-                    cx,
-                );
-                (app_state.initialize_workspace)(&mut workspace, &app_state, cx);
-                workspace
-            });
-            workspace.update(cx, callback)
+            Self::new_local(&[], app_state, cx, callback)
         }
     }
 
@@ -1479,7 +1539,7 @@ impl Workspace {
             for path in &abs_paths {
                 project_paths.push(
                     this.update(&mut cx, |this, cx| {
-                        this.project_path_for_path(path, visible, cx)
+                        Workspace::project_path_for_path(this.project, path, visible, cx)
                     })
                     .await
                     .log_err(),
@@ -1544,15 +1604,15 @@ impl Workspace {
     }
 
     fn project_path_for_path(
-        &self,
+        project: ModelHandle<Project>,
         abs_path: &Path,
         visible: bool,
-        cx: &mut ViewContext<Self>,
+        cx: &mut MutableAppContext,
     ) -> Task<Result<(ModelHandle<Worktree>, ProjectPath)>> {
-        let entry = self.project().update(cx, |project, cx| {
+        let entry = project.update(cx, |project, cx| {
             project.find_or_create_local_worktree(abs_path, visible, cx)
         });
-        cx.spawn(|_, cx| async move {
+        cx.spawn(|cx| async move {
             let (worktree, path) = entry.await?;
             let worktree_id = worktree.read_with(&cx, |t, _| t.id());
             Ok((
@@ -2957,7 +3017,6 @@ pub fn open_paths(
     let app_state = app_state.clone();
     let abs_paths = abs_paths.to_vec();
     cx.spawn(|mut cx| async move {
-        let mut new_project = None;
         let workspace = if let Some(existing) = existing {
             existing
         } else {
@@ -2966,24 +3025,15 @@ pub fn open_paths(
                     .await
                     .contains(&false);
 
-            cx.add_window((app_state.build_window_options)(), |cx| {
-                let project = Project::local(
-                    app_state.client.clone(),
-                    app_state.user_store.clone(),
-                    app_state.project_store.clone(),
-                    app_state.languages.clone(),
-                    app_state.fs.clone(),
-                    cx,
-                );
-                new_project = Some(project.clone());
-                let mut workspace = Workspace::new(project, app_state.default_item_factory, cx);
-                (app_state.initialize_workspace)(&mut workspace, &app_state, cx);
-                if contains_directory {
-                    workspace.toggle_sidebar(SidebarSide::Left, cx);
-                }
-                workspace
+            cx.update(|cx| {
+                Workspace::new_local(&abs_paths[..], &app_state, cx, move |workspace, cx| {
+                    if contains_directory {
+                        workspace.toggle_sidebar(SidebarSide::Left, cx);
+                    }
+                    cx.handle()
+                })
             })
-            .1
+            .await
         };
 
         let items = workspace
@@ -2996,24 +3046,8 @@ pub fn open_paths(
     })
 }
 
-fn open_new(app_state: &Arc<AppState>, cx: &mut MutableAppContext) {
-    let (window_id, workspace) = cx.add_window((app_state.build_window_options)(), |cx| {
-        let mut workspace = Workspace::new(
-            Project::local(
-                app_state.client.clone(),
-                app_state.user_store.clone(),
-                app_state.project_store.clone(),
-                app_state.languages.clone(),
-                app_state.fs.clone(),
-                cx,
-            ),
-            app_state.default_item_factory,
-            cx,
-        );
-        (app_state.initialize_workspace)(&mut workspace, app_state, cx);
-        workspace
-    });
-    cx.dispatch_action_at(window_id, workspace.id(), NewFile);
+fn open_new(app_state: &Arc<AppState>, cx: &mut MutableAppContext) -> Task<()> {
+    Workspace::new_local(&[], app_state, cx, |_, cx| cx.dispatch_action(NewFile))
 }
 
 #[cfg(test)]

crates/zed/src/zed.rs 🔗

@@ -463,7 +463,7 @@ fn open_config_file(
 
         workspace
             .update(&mut cx, |workspace, cx| {
-                workspace.with_local_workspace(cx, app_state, |workspace, cx| {
+                workspace.with_local_workspace(app_state, cx, |workspace, cx| {
                     workspace.open_paths(vec![path.to_path_buf()], false, cx)
                 })
             })
@@ -480,7 +480,7 @@ fn open_log_file(
 ) {
     const MAX_LINES: usize = 1000;
 
-    workspace.with_local_workspace(cx, app_state.clone(), |_, cx| {
+    workspace.with_local_workspace(app_state.clone(), cx, |_, cx| {
         cx.spawn_weak(|workspace, mut cx| async move {
             let (old_log, new_log) = futures::join!(
                 app_state.fs.load(&paths::OLD_LOG),
@@ -532,7 +532,7 @@ fn open_telemetry_log_file(
     app_state: Arc<AppState>,
     cx: &mut ViewContext<Workspace>,
 ) {
-    workspace.with_local_workspace(cx, app_state.clone(), |_, cx| {
+    workspace.with_local_workspace(app_state.clone(), cx, |_, cx| {
         cx.spawn_weak(|workspace, mut cx| async move {
             let workspace = workspace.upgrade(&cx)?;
             let path = app_state.client.telemetry_log_file_path()?;