skootrs_statestore/
lib.rs1use std::collections::HashSet;
20
21use skootrs_lib::service::{
22 repo::{LocalRepoService, RepoService},
23 source::{LocalSourceService, SourceService},
24};
25
26use skootrs_model::skootrs::{InitializedProject, InitializedRepo, InitializedSource, SkootError};
27
28pub trait ProjectStateStore {
29 fn create(
30 &self,
31 project: InitializedProject,
32 ) -> impl std::future::Future<Output = Result<(), SkootError>> + Send;
33 fn read(
34 &self,
35 ) -> impl std::future::Future<Output = Result<Option<InitializedProject>, SkootError>> + Send;
36 fn update(
37 &self,
38 project: InitializedProject,
39 ) -> impl std::future::Future<Output = Result<(), SkootError>> + Send;
40}
41
42pub struct GitProjectStateStore<S: SourceService> {
43 pub source: InitializedSource,
45 pub source_service: S,
46}
47
48impl ProjectStateStore for GitProjectStateStore<LocalSourceService> {
49 async fn create(&self, project: InitializedProject) -> Result<(), SkootError> {
50 self.source_service.write_file(
51 self.source.clone(),
52 "./",
53 ".skootrs".to_string(),
54 serde_json::to_string(&project)?,
55 )?;
56 self.source_service.commit_and_push_changes(
57 self.source.clone(),
58 "Updated skootrs project state".to_string(),
59 )?;
60 Ok(())
61 }
62
63 async fn read(&self) -> Result<Option<InitializedProject>, SkootError> {
64 let project = self
65 .source_service
66 .read_file(&self.source, "./", ".skootrs".to_string())?;
67 Ok(Some(serde_json::from_str(&project).unwrap()))
68 }
69
70 async fn update(&self, project: InitializedProject) -> Result<(), SkootError> {
71 self.create(project).await
72 }
73}
74
75pub trait ProjectReferenceCache {
76 fn list(&self)
77 -> impl std::future::Future<Output = Result<HashSet<String>, SkootError>> + Send;
78 fn get(
79 &mut self,
80 repo_url: String,
81 ) -> impl std::future::Future<Output = Result<InitializedProject, SkootError>> + Send;
82 fn set(
83 &mut self,
84 repo_url: String,
85 ) -> impl std::future::Future<Output = Result<(), SkootError>> + Send;
86 fn delete(
87 &mut self,
88 repo_url: String,
89 ) -> impl std::future::Future<Output = Result<(), SkootError>> + Send;
90}
91
92pub struct InMemoryProjectReferenceCache {
93 pub save_path: String,
94 pub cache: HashSet<String>,
95 pub local_source_service: LocalSourceService,
96 pub local_repo_service: LocalRepoService,
97 pub clone_path: String,
98}
99
100impl ProjectReferenceCache for InMemoryProjectReferenceCache {
101 async fn list(&self) -> Result<HashSet<String>, SkootError> {
102 Ok(self.cache.clone())
103 }
104
105 async fn get(&mut self, repo_url: String) -> Result<InitializedProject, SkootError> {
106 let repo = InitializedRepo::try_from(repo_url)?;
107 let project = self
108 .local_repo_service
109 .fetch_file_content(&repo, ".skootrs")
110 .await?;
111 let initialized_project: InitializedProject = serde_json::from_str(&project)?;
112 Ok(initialized_project)
113 }
114
115 async fn set(&mut self, repo_url: String) -> Result<(), SkootError> {
116 self.cache.insert(repo_url);
117 self.save()?;
118 Ok(())
119 }
120
121 async fn delete(&mut self, repo_url: String) -> Result<(), SkootError> {
122 self.cache.remove(&repo_url);
123 self.save()?;
124 Ok(())
125 }
126}
127
128impl InMemoryProjectReferenceCache {
129 #[must_use]
131 pub fn new(save_path: String) -> Self {
132 Self {
133 save_path,
134 cache: HashSet::new(),
135 local_source_service: LocalSourceService {},
136 local_repo_service: LocalRepoService {},
137 clone_path: "/tmp".to_string(),
138 }
139 }
140
141 pub fn load_or_create(path: &str) -> Result<Self, SkootError> {
147 let mut cache = Self::new(path.to_string());
148 Ok(if cache.load().is_ok() {
149 cache
150 } else {
151 cache.save()?;
152 cache
153 })
154 }
155
156 pub fn load(&mut self) -> Result<(), SkootError> {
162 let deserialized_cache: HashSet<String> =
163 serde_json::from_str(&std::fs::read_to_string(&self.save_path)?)?;
164 self.cache = deserialized_cache;
165 Ok(())
166 }
167
168 pub fn save(&self) -> Result<(), SkootError> {
174 let serialized_cache = serde_json::to_string(&self.cache)?;
175 std::fs::write(&self.save_path, serialized_cache)?;
176 Ok(())
177 }
178}