aboutsummaryrefslogtreecommitdiff
path: root/src/persist/snapshot.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-22 02:21:12 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-22 02:23:35 +0300
commit0148c1379b76c5c0a9d05588c07dcb06ec32f93f (patch)
tree554766d959c738ca2aa433c3d4b4a7de25568008 /src/persist/snapshot.rs
parenta9ff4012bdca0dbdbc77bc6e53a430689fc899be (diff)
feat: add git worktree workspace management
refs #137
Diffstat (limited to 'src/persist/snapshot.rs')
-rw-r--r--src/persist/snapshot.rs38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/persist/snapshot.rs b/src/persist/snapshot.rs
index a3811c36..79d5c406 100644
--- a/src/persist/snapshot.rs
+++ b/src/persist/snapshot.rs
@@ -26,6 +26,8 @@ pub struct SessionSnapshot {
pub sidebar_width: Option<u16>,
#[serde(default)]
pub sidebar_section_split: Option<f32>,
+ #[serde(default)]
+ pub collapsed_space_keys: std::collections::HashSet<String>,
}
#[derive(Serialize, Deserialize)]
@@ -35,6 +37,8 @@ pub struct WorkspaceSnapshot {
#[serde(default)]
pub custom_name: Option<String>,
pub identity_cwd: PathBuf,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub worktree_space: Option<crate::workspace::WorktreeSpaceMembership>,
pub tabs: Vec<TabSnapshot>,
#[serde(default)]
pub active_tab: usize,
@@ -109,6 +113,7 @@ impl From<LegacyWorkspaceSnapshot> for WorkspaceSnapshot {
id: None,
custom_name: snap.custom_name,
identity_cwd,
+ worktree_space: None,
tabs: vec![tab],
active_tab: 0,
}
@@ -131,6 +136,8 @@ struct RawSessionSnapshot {
sidebar_width: Option<u16>,
#[serde(default)]
sidebar_section_split: Option<f32>,
+ #[serde(default)]
+ collapsed_space_keys: std::collections::HashSet<String>,
}
fn migrate_snapshot(raw: RawSessionSnapshot) -> Result<SessionSnapshot, String> {
@@ -146,6 +153,7 @@ fn migrate_snapshot(raw: RawSessionSnapshot) -> Result<SessionSnapshot, String>
agent_panel_scope: raw.agent_panel_scope,
sidebar_width: raw.sidebar_width,
sidebar_section_split: raw.sidebar_section_split,
+ collapsed_space_keys: raw.collapsed_space_keys,
})
}
@@ -208,6 +216,7 @@ pub fn capture(
agent_panel_scope: crate::app::state::AgentPanelScope,
sidebar_width: u16,
sidebar_section_split: f32,
+ collapsed_space_keys: std::collections::HashSet<String>,
) -> SessionSnapshot {
SessionSnapshot {
version: SNAPSHOT_VERSION,
@@ -220,6 +229,7 @@ pub fn capture(
agent_panel_scope,
sidebar_width: Some(sidebar_width),
sidebar_section_split: Some(sidebar_section_split),
+ collapsed_space_keys,
}
}
@@ -237,6 +247,7 @@ fn capture_workspace(
identity_cwd: ws
.resolved_identity_cwd_from(terminals, terminal_runtimes)
.unwrap_or_else(|| ws.identity_cwd.clone()),
+ worktree_space: ws.worktree_space.clone(),
tabs: ws
.tabs
.iter()
@@ -375,6 +386,7 @@ mod tests {
state.agent_panel_scope,
state.sidebar_width,
state.sidebar_section_split,
+ state.collapsed_space_keys.clone(),
)
}
@@ -395,6 +407,7 @@ mod tests {
agent_panel_scope: AgentPanelScope::CurrentWorkspace,
sidebar_width: Some(26),
sidebar_section_split: Some(0.5),
+ collapsed_space_keys: std::collections::HashSet::new(),
};
let json = serde_json::to_string(&snap).unwrap();
let restored = parse_snapshot(&json).unwrap();
@@ -451,6 +464,7 @@ mod tests {
id: Some("wproj".to_string()),
custom_name: Some("pi-mono".to_string()),
identity_cwd: PathBuf::from("/home/can/Projects/herdr"),
+ worktree_space: None,
tabs: vec![TabSnapshot {
custom_name: Some("api".to_string()),
layout: LayoutSnapshot::Split {
@@ -471,6 +485,7 @@ mod tests {
agent_panel_scope: AgentPanelScope::CurrentWorkspace,
sidebar_width: Some(26),
sidebar_section_split: Some(0.5),
+ collapsed_space_keys: std::collections::HashSet::new(),
version: SNAPSHOT_VERSION,
};
@@ -622,11 +637,32 @@ mod tests {
state.sidebar_width = 31;
state.sidebar_section_split = 0.4;
state.agent_panel_scope = AgentPanelScope::AllWorkspaces;
+ state.collapsed_space_keys.insert("repo-key".into());
let snapshot = capture_from_state(&state);
assert_eq!(snapshot.sidebar_width, Some(31));
assert_eq!(snapshot.sidebar_section_split, Some(0.4));
assert_eq!(snapshot.agent_panel_scope, AgentPanelScope::AllWorkspaces);
+ assert!(snapshot.collapsed_space_keys.contains("repo-key"));
+ }
+
+ #[test]
+ fn capture_contract_tracks_worktree_space_membership() {
+ let mut state = state_with_workspaces(&["main"]);
+ state.workspaces[0].worktree_space = Some(crate::workspace::WorktreeSpaceMembership {
+ key: "repo-key".into(),
+ label: "herdr".into(),
+ repo_root: PathBuf::from("/repo/herdr"),
+ checkout_path: PathBuf::from("/repo/herdr/worktree-a"),
+ is_linked_worktree: true,
+ });
+
+ let snapshot = capture_from_state(&state);
+
+ assert_eq!(
+ snapshot.workspaces[0].worktree_space,
+ state.workspaces[0].worktree_space
+ );
}
#[test]
@@ -776,6 +812,7 @@ mod tests {
id: Some("test-ws".to_string()),
custom_name: Some("fallback test".to_string()),
identity_cwd: PathBuf::from("/tmp"),
+ worktree_space: None,
tabs: vec![TabSnapshot {
custom_name: None,
layout: LayoutSnapshot::Split {
@@ -796,6 +833,7 @@ mod tests {
agent_panel_scope: AgentPanelScope::CurrentWorkspace,
sidebar_width: Some(26),
sidebar_section_split: Some(0.5),
+ collapsed_space_keys: std::collections::HashSet::new(),
};
let json = serde_json::to_string(&snap).unwrap();