git_same/cache/
sync_history.rs1use anyhow::{Context, Result};
2use serde::{Deserialize, Serialize};
3use std::fs;
4use std::path::{Path, PathBuf};
5use tracing::debug;
6
7use crate::tui::app::SyncHistoryEntry;
8
9const HISTORY_VERSION: u32 = 1;
10const MAX_HISTORY_ENTRIES: usize = 50;
11
12#[derive(Debug, Serialize, Deserialize)]
13struct SyncHistoryFile {
14 version: u32,
15 entries: Vec<SyncHistoryEntry>,
16}
17
18pub struct SyncHistoryManager {
22 path: PathBuf,
23}
24
25impl SyncHistoryManager {
26 pub fn for_workspace(root: &Path) -> Result<Self> {
28 let path = crate::config::WorkspaceStore::sync_history_path(root);
29 Ok(Self { path })
30 }
31
32 pub fn load(&self) -> Result<Vec<SyncHistoryEntry>> {
34 if !self.path.exists() {
35 return Ok(Vec::new());
36 }
37 let content = fs::read_to_string(&self.path).context("Failed to read sync history file")?;
38 let file: SyncHistoryFile =
39 serde_json::from_str(&content).context("Failed to parse sync history")?;
40 if file.version != HISTORY_VERSION {
41 debug!(
42 file_version = file.version,
43 current_version = HISTORY_VERSION,
44 "Sync history version mismatch, starting fresh"
45 );
46 return Ok(Vec::new());
47 }
48 Ok(file.entries)
49 }
50
51 pub fn save(&self, entries: &[SyncHistoryEntry]) -> Result<()> {
53 if let Some(parent) = self.path.parent() {
54 fs::create_dir_all(parent).context("Failed to create history directory")?;
55 }
56 let capped: Vec<SyncHistoryEntry> = entries
57 .iter()
58 .rev()
59 .take(MAX_HISTORY_ENTRIES)
60 .rev()
61 .cloned()
62 .collect();
63 let file = SyncHistoryFile {
64 version: HISTORY_VERSION,
65 entries: capped,
66 };
67 let json =
68 serde_json::to_string_pretty(&file).context("Failed to serialize sync history")?;
69 fs::write(&self.path, &json).context("Failed to write sync history")?;
70 debug!(
71 path = %self.path.display(),
72 entries = file.entries.len(),
73 "Saved sync history"
74 );
75 Ok(())
76 }
77}
78
79#[cfg(test)]
80#[path = "sync_history_tests.rs"]
81mod tests;