vtcode_memory/
manifest.rs1use std::fs;
2use std::path::Path;
3
4use crate::SessionManifest;
5use crate::TurnIndex;
6use crate::error::SessionStoreError;
7
8pub struct ManifestStore {
14 session_dir: std::path::PathBuf,
15}
16
17impl ManifestStore {
18 pub(crate) fn new(session_dir: std::path::PathBuf) -> Self {
20 Self { session_dir }
21 }
22
23 fn manifest_path(&self) -> std::path::PathBuf {
25 self.session_dir.join("manifest.json")
26 }
27
28 fn turns_path(&self) -> std::path::PathBuf {
30 self.session_dir.join("index").join("turns.json")
31 }
32
33 pub(crate) fn load_manifest(&self) -> Result<Option<SessionManifest>, SessionStoreError> {
39 let path = self.manifest_path();
40 let Some(bytes) = read_optional_private_file(&path)? else {
41 return Ok(None);
42 };
43 Ok(serde_json::from_slice(&bytes).ok())
44 }
45
46 pub(crate) fn load_turn_index(&self) -> Result<Option<TurnIndex>, SessionStoreError> {
50 let path = self.turns_path();
51 let Some(bytes) = read_optional_private_file(&path)? else {
52 return Ok(None);
53 };
54 Ok(serde_json::from_slice(&bytes).ok())
55 }
56 pub(crate) fn write_manifest(&self, manifest: &SessionManifest) -> Result<(), SessionStoreError> {
58 let path = self.manifest_path();
59 let bytes = serde_json::to_vec(manifest)?;
60 vtcode_commons::VtCodePaths::write_private_file_atomic(&path, &bytes)
61 .map_err(|error| SessionStoreError::io(path, std::io::Error::other(error)))
62 }
63
64 pub(crate) fn write_turn_index(&self, index: &TurnIndex) -> Result<(), SessionStoreError> {
66 let path = self.turns_path();
67 let bytes = serde_json::to_vec(index)?;
68 vtcode_commons::VtCodePaths::write_private_file_atomic(&path, &bytes)
69 .map_err(|error| SessionStoreError::io(path, std::io::Error::other(error)))
70 }
71}
72
73fn read_optional_private_file(path: &Path) -> Result<Option<Vec<u8>>, SessionStoreError> {
74 match fs::symlink_metadata(path) {
75 Ok(_) => vtcode_commons::VtCodePaths::read_file_no_follow(path)
76 .map(Some)
77 .map_err(|error| SessionStoreError::io(path.to_path_buf(), std::io::Error::other(error))),
78 Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(None),
79 Err(error) => Err(SessionStoreError::io(path.to_path_buf(), error)),
80 }
81}