cascade_cli/stack/
sync_state.rs1use crate::errors::{CascadeError, Result};
2use serde::{Deserialize, Serialize};
3use std::path::Path;
4
5#[derive(Serialize, Deserialize, Debug, Clone)]
7pub struct SyncState {
8 pub stack_id: String,
10 pub stack_name: String,
12 pub original_branch: String,
14 pub target_base: String,
16 pub remaining_entry_ids: Vec<String>,
18 pub current_entry_id: String,
20 pub current_entry_branch: String,
22 pub current_temp_branch: String,
24 pub temp_branches: Vec<String>,
26}
27
28impl SyncState {
29 pub fn save(&self, repo_root: &Path) -> Result<()> {
31 let state_path = repo_root.join(".git").join("CASCADE_SYNC_STATE");
32 let json = serde_json::to_string_pretty(self)
33 .map_err(|e| CascadeError::config(format!("Failed to serialize sync state: {e}")))?;
34
35 std::fs::write(&state_path, json)
36 .map_err(|e| CascadeError::config(format!("Failed to write sync state: {e}")))?;
37
38 tracing::debug!("Saved sync state to {:?}", state_path);
39 Ok(())
40 }
41
42 pub fn load(repo_root: &Path) -> Result<Self> {
44 let state_path = repo_root.join(".git").join("CASCADE_SYNC_STATE");
45
46 if !state_path.exists() {
47 return Err(CascadeError::config(
48 "No in-progress sync found. Nothing to continue.".to_string(),
49 ));
50 }
51
52 let json = std::fs::read_to_string(&state_path)
53 .map_err(|e| CascadeError::config(format!("Failed to read sync state: {e}")))?;
54
55 let state: Self = serde_json::from_str(&json)
56 .map_err(|e| CascadeError::config(format!("Failed to parse sync state: {e}")))?;
57
58 tracing::debug!("Loaded sync state from {:?}", state_path);
59 Ok(state)
60 }
61
62 pub fn delete(repo_root: &Path) -> Result<()> {
64 let state_path = repo_root.join(".git").join("CASCADE_SYNC_STATE");
65
66 if state_path.exists() {
67 std::fs::remove_file(&state_path)
68 .map_err(|e| CascadeError::config(format!("Failed to delete sync state: {e}")))?;
69 tracing::debug!("Deleted sync state file");
70 }
71
72 Ok(())
73 }
74
75 pub fn exists(repo_root: &Path) -> bool {
77 repo_root.join(".git").join("CASCADE_SYNC_STATE").exists()
78 }
79}