From b75b3903ee10562ab89c83f1bf8c37eeebe101f1 Mon Sep 17 00:00:00 2001 From: Luuk Verhoeven Date: Sat, 6 Dec 2025 12:14:27 +0100 Subject: [PATCH 1/2] Enable unsaved buffer persistence for worktree-less windows (#15098) Previously, unsaved buffers in empty windows (no project open) or single file editing sessions were not persisted across restarts. This change enables the hot-exit functionality for these scenarios by: - Always serializing dirty buffers regardless of worktree presence - Including empty workspaces in session serialization - Removing the DetachFromSession behavior for local empty windows --- crates/editor/src/items.rs | 6 +++--- crates/workspace/src/persistence.rs | 7 ++++--- crates/workspace/src/workspace.rs | 8 +++----- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index ca8937bebe3d35..bc3a8178422266 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -1270,9 +1270,9 @@ impl SerializableItem for Editor { let project = self.project.clone()?; let serialize_dirty_buffers = match buffer_serialization { - // If we don't have a worktree, we don't serialize, because - // projects without worktrees aren't deserialized. - BufferSerialization::All => project.read(cx).visible_worktrees(cx).next().is_some(), + // Always serialize dirty buffers, including for worktree-less windows. + // This enables hot-exit functionality for empty windows and single files. + BufferSerialization::All => true, BufferSerialization::NonDirtyBuffers => false, }; diff --git a/crates/workspace/src/persistence.rs b/crates/workspace/src/persistence.rs index 103e51d548648c..b39ca8c40be657 100644 --- a/crates/workspace/src/persistence.rs +++ b/crates/workspace/src/persistence.rs @@ -1360,8 +1360,8 @@ impl WorkspaceDb { // WSL VM and file server to boot up. This can block for many seconds. // Supported scenarios use remote workspaces. if !has_wsl_path && paths.paths().iter().all(|path| path.exists()) { - // Only show directories in recent projects - if paths.paths().iter().any(|path| path.is_dir()) { + // Include workspaces with directories, or empty workspaces (for hot-exit support) + if paths.is_empty() || paths.paths().iter().any(|path| path.is_dir()) { result.push((id, SerializedWorkspaceLocation::Local, paths)); } } else { @@ -1405,8 +1405,9 @@ impl WorkspaceDb { window_id.map(WindowId::from), )); } else if paths.paths().iter().all(|path| path.exists()) - && paths.paths().iter().any(|path| path.is_dir()) + && (paths.is_empty() || paths.paths().iter().any(|path| path.is_dir())) { + // Include workspaces with directories, or empty workspaces (for hot-exit support) workspaces.push(( SerializedWorkspaceLocation::Local, paths, diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index b1ad520493b486..649cd1c94ba6c6 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -5552,11 +5552,9 @@ impl Workspace { if let Some(connection) = self.project.read(cx).remote_connection_options(cx) { WorkspaceLocation::Location(SerializedWorkspaceLocation::Remote(connection), paths) } else if self.project.read(cx).is_local() { - if !paths.is_empty() { - WorkspaceLocation::Location(SerializedWorkspaceLocation::Local, paths) - } else { - WorkspaceLocation::DetachFromSession - } + // Always serialize local workspaces, even without worktrees. + // This enables hot-exit functionality for empty windows and single files. + WorkspaceLocation::Location(SerializedWorkspaceLocation::Local, paths) } else { WorkspaceLocation::None } From 6a350e1678ee22b4833249aa1297852973e6cc24 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 15 Dec 2025 17:04:21 -0700 Subject: [PATCH 2/2] Remove unused DetachFromSession variant --- crates/workspace/src/workspace.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 649cd1c94ba6c6..7a661ee9f626e5 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1086,8 +1086,6 @@ pub enum OpenVisible { enum WorkspaceLocation { // Valid local paths or SSH project to serialize Location(SerializedWorkspaceLocation, PathList), - // No valid location found hence clear session id - DetachFromSession, // No valid location found to serialize None, } @@ -5537,12 +5535,6 @@ impl Workspace { persistence::DB.save_workspace(serialized_workspace).await; }) } - WorkspaceLocation::DetachFromSession => window.spawn(cx, async move |_| { - persistence::DB - .set_session_id(database_id, None) - .await - .log_err(); - }), WorkspaceLocation::None => Task::ready(()), } }