diff --git a/crates/sidebar/src/sidebar.rs b/crates/sidebar/src/sidebar.rs index 69c23652c28971f1cde8a2d97f12335560d143db..b720c7f3cfc739c7f429ec60b69a6596af46b3c0 100644 --- a/crates/sidebar/src/sidebar.rs +++ b/crates/sidebar/src/sidebar.rs @@ -46,9 +46,9 @@ use ui::{ use util::ResultExt as _; use util::path_list::{PathList, SerializedPathList}; use workspace::{ - AddFolderToProject, CloseWindow, FocusWorkspaceSidebar, MultiWorkspace, MultiWorkspaceEvent, - Open, Sidebar as WorkspaceSidebar, SidebarSide, ToggleWorkspaceSidebar, Workspace, WorkspaceId, - sidebar_side_context_menu, + AddFolderToProject, AppState, CloseWindow, FocusWorkspaceSidebar, MultiWorkspace, + MultiWorkspaceEvent, Open, OpenOptions, Sidebar as WorkspaceSidebar, SidebarSide, + ToggleWorkspaceSidebar, Workspace, WorkspaceId, sidebar_side_context_menu, }; use zed_actions::OpenRecent; @@ -2302,7 +2302,7 @@ impl Sidebar { } Some(row) => { let fs = cx.update(|_window, cx| ::global(cx))?; - match Self::restore_archived_worktree(row, &workspaces, fs, cx).await { + match Self::restore_archived_worktree(row, fs, cx).await { Ok(restored_path) => { final_paths.push(restored_path); Self::maybe_cleanup_archived_worktree(row, &store, &workspaces, cx) @@ -2334,19 +2334,58 @@ impl Sidebar { async fn restore_archived_worktree( row: &ArchivedGitWorktree, - workspaces: &[Entity], fs: Arc, cx: &mut AsyncWindowContext, ) -> anyhow::Result { let commit_hash = row.commit_hash.clone(); + let main_repo_path = row.main_repo_path.clone(); + + // Ensure the main repo's workspace is open (finds existing or opens new). + let open_task = cx.update(|_window, cx| { + let app_state = AppState::global(cx); + workspace::open_paths( + std::slice::from_ref(&main_repo_path), + app_state, + OpenOptions::default(), + cx, + ) + })?; + let open_result = open_task.await?; + let project = open_result + .workspace + .update(cx, |workspace, _cx| workspace.project().clone()); + + // Wait for worktree scans to complete so the Repository entities are available. + let scan_futures = cx.update(|_window, cx| { + project + .read(cx) + .worktrees(cx) + .filter_map(|worktree| { + worktree + .read(cx) + .as_local() + .map(|local| local.scan_complete()) + }) + .collect::>() + })?; + for scan_future in scan_futures { + scan_future.await; + } - // Find the main repo entity. + // Find the main repo entity in the project. let main_repo = cx.update(|_window, cx| { - find_main_repo_in_workspaces(workspaces, &row.main_repo_path, cx) + project + .read(cx) + .repositories(cx) + .values() + .find_map(|repo_entity| { + let repo = repo_entity.read(cx); + (repo.is_main_worktree() && *repo.work_directory_abs_path == *main_repo_path) + .then(|| repo_entity.clone()) + }) })?; let Some(main_repo) = main_repo else { - // Main repo not found — fall back to fresh worktree. return Self::create_fresh_worktree(row, &fs, cx).await; }; @@ -2357,17 +2396,13 @@ impl Sidebar { let is_restored_and_valid = already_exists && row.restored && cx.update(|_window, cx| { - workspaces.iter().any(|workspace| { - let project = workspace.read(cx).project().clone(); - project - .read(cx) - .repositories(cx) - .values() - .any(|repo_entity| { - *repo_entity.read(cx).snapshot().work_directory_abs_path - == *worktree_path - }) - }) + project + .read(cx) + .repositories(cx) + .values() + .any(|repo_entity| { + *repo_entity.read(cx).snapshot().work_directory_abs_path == *worktree_path + }) })?; let final_worktree_path = if !already_exists { @@ -2431,52 +2466,35 @@ impl Sidebar { // Tell the project about the new worktree and wait for it // to finish scanning so the GitStore creates a Repository. - let project = cx.update(|_window, cx| { - workspaces.iter().find_map(|workspace| { - let project = workspace.read(cx).project().clone(); - let has_main_repo = project.read(cx).repositories(cx).values().any(|repo| { - let repo = repo.read(cx); - repo.is_main_worktree() - && *repo.work_directory_abs_path == *row.main_repo_path - }); - has_main_repo.then_some(project) + let path_for_register = final_worktree_path.clone(); + let worktree_result = project + .update(cx, |project, cx| { + project.find_or_create_worktree(path_for_register, true, cx) }) - })?; - - if let Some(project) = project { - let path_for_register = final_worktree_path.clone(); - let worktree_result = project - .update(cx, |project, cx| { - project.find_or_create_worktree(path_for_register, true, cx) - }) - .await; - if let Ok((worktree, _)) = worktree_result { - let scan_complete = cx.update(|_window, cx| { - worktree - .read(cx) - .as_local() - .map(project::LocalWorktree::scan_complete) - })?; - if let Some(future) = scan_complete { - future.await; - } + .await; + if let Ok((worktree, _)) = worktree_result { + let scan_complete = cx.update(|_window, cx| { + worktree + .read(cx) + .as_local() + .map(project::LocalWorktree::scan_complete) + })?; + if let Some(future) = scan_complete { + future.await; } } // Find the new worktree's repo entity. let worktree_repo = cx.update(|_window, cx| { - workspaces.iter().find_map(|workspace| { - let project = workspace.read(cx).project().clone(); - project - .read(cx) - .repositories(cx) - .values() - .find_map(|repo_entity| { - let snapshot = repo_entity.read(cx).snapshot(); - (*snapshot.work_directory_abs_path == *final_worktree_path) - .then(|| repo_entity.clone()) - }) - }) + project + .read(cx) + .repositories(cx) + .values() + .find_map(|repo_entity| { + let snapshot = repo_entity.read(cx).snapshot(); + (*snapshot.work_directory_abs_path == *final_worktree_path) + .then(|| repo_entity.clone()) + }) })?; if let Some(worktree_repo) = worktree_repo {