core_lib/core/
state.rs

1#![allow(dead_code)]
2use std::{collections::HashMap, path::PathBuf};
3
4use crate::{core::watcher::WatchContext, log::logger::Logger};
5use anyhow::Result;
6use serde::{Deserialize, Serialize};
7use tokio::{fs, sync::RwLock};
8
9#[doc = include_str!("docs/app_state.md")]
10#[derive(Default)]
11pub struct AppState {
12    pub watches: RwLock<HashMap<String, WatchContext>>,
13}
14
15impl AppState {
16    pub async fn load_from_disk() -> Result<Self, anyhow::Error> {
17        let registry = AppState::load_watches().await?;
18        let mut watches: HashMap<String, WatchContext> = HashMap::new();
19
20        for mut ctx in registry.projects {
21            let logger = Logger::new(&ctx.log_path()).await?;
22            ctx.logger = logger;
23            watches.insert(ctx.id.clone(), ctx);
24        }
25
26        Ok(Self {
27            watches: RwLock::new(watches),
28        })
29    }
30
31    pub async fn save_to_disk(&self) -> Result<()> {
32        let guard = self.watches.read().await;
33        let registry = WatchRegistry {
34            projects: guard.values().cloned().collect(),
35        };
36        save_watches(&registry).await
37    }
38
39    // -----------------------
40    // Static methods
41    // -----------------------
42
43    pub async fn init_watch_file() -> Result<()> {
44        let path = get_watch_path();
45        println!("watch file at: {}", path.to_str().unwrap());
46        if !fs::try_exists(&path).await? {
47            if let Some(parent) = path.parent() {
48                fs::create_dir_all(parent).await?;
49            }
50            let empty = WatchRegistry::default();
51            let json = serde_json::to_string_pretty(&empty)?;
52            fs::write(path, json).await?;
53        }
54        Ok(())
55    }
56
57    /// load watches.json file and Serialize it into WatchRegistry
58    pub async fn load_watches() -> Result<WatchRegistry> {
59        let path = get_watch_path();
60        let data = fs::read_to_string(&path).await?;
61        let watches = serde_json::from_str(&data)?;
62        Ok(watches)
63    }
64
65    /// adds a view to the watches.json file
66    pub async fn add_watch(ctx: &WatchContext) -> Result<()> {
67        let mut watches = AppState::load_watches().await?;
68
69        if let Some(existing) = watches
70            .projects
71            .iter_mut()
72            .find(|p| p.project_dir == ctx.project_dir)
73        {
74            *existing = ctx.clone();
75        } else {
76            watches.projects.push(ctx.clone());
77        }
78
79        save_watches(&watches).await?;
80        Ok(())
81    }
82
83    /// deletes a WatchContext in the watches.json file
84    pub async fn remove_watch_by_id(id: &str) -> Result<()> {
85        let mut watches = AppState::load_watches().await?;
86        watches.projects.retain(|p| p.id != id); // garder seulement les projet avec un id different de celui a supprimé
87        save_watches(&watches).await?;
88        Ok(())
89    }
90}
91
92#[derive(Serialize, Deserialize, Clone, Default)]
93pub struct WatchRegistry {
94    pub projects: Vec<WatchContext>,
95}
96
97pub async fn get_id_by_name(name: &str) -> Result<Option<String>> {
98    let watches = AppState::load_watches().await?;
99    Ok(watches
100        .projects
101        .iter()
102        .find(|p| p.repo.name == name)
103        .map(|p| p.id.clone()))
104}
105
106pub async fn get_name_by_id(id: &str) -> Result<Option<String>> {
107    let watches = AppState::load_watches().await?;
108    Ok(watches
109        .projects
110        .iter()
111        .find(|p| p.id == id)
112        .map(|p| p.repo.name.clone()))
113}
114
115// -----------------------
116// Utils functions
117// -----------------------
118
119fn get_watch_path() -> PathBuf {
120    let path = dirs::data_local_dir()
121        .unwrap_or_else(|| std::env::current_dir().expect("Failed to get current directory"));
122    path.join("fleetd").join("watches.json")
123}
124
125async fn save_watches(watches: &WatchRegistry) -> Result<()> {
126    let path = get_watch_path();
127    let json = serde_json::to_string_pretty(watches)?;
128    fs::write(path, json).await?;
129    Ok(())
130}