Skip to main content

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        tracing::info!(
46            target: "fleet",
47            message = %format!("watch file at: {}", path.to_str().unwrap()),
48        );
49        if !fs::try_exists(&path).await? {
50            if let Some(parent) = path.parent() {
51                fs::create_dir_all(parent).await?;
52            }
53            let empty = WatchRegistry::default();
54            let json = serde_json::to_string_pretty(&empty)?;
55            fs::write(path, json).await?;
56        }
57        Ok(())
58    }
59
60    /// load watches.json file and Serialize it into WatchRegistry
61    pub async fn load_watches() -> Result<WatchRegistry> {
62        let path = get_watch_path();
63        let data = fs::read_to_string(&path).await?;
64        let watches = serde_json::from_str(&data)?;
65        Ok(watches)
66    }
67
68    /// adds a view to the watches.json file
69    pub async fn add_watch(ctx: &WatchContext) -> Result<()> {
70        let mut watches = AppState::load_watches().await?;
71
72        if let Some(existing) = watches
73            .projects
74            .iter_mut()
75            .find(|p| p.project_dir == ctx.project_dir)
76        {
77            *existing = ctx.clone();
78        } else {
79            watches.projects.push(ctx.clone());
80        }
81
82        save_watches(&watches).await?;
83        Ok(())
84    }
85
86    /// deletes a WatchContext in the watches.json file
87    pub async fn remove_watch_by_id(id: &str) -> Result<()> {
88        let mut watches = AppState::load_watches().await?;
89        watches.projects.retain(|p| p.id != id); // garder seulement les projet avec un id different de celui a supprimé
90        save_watches(&watches).await?;
91        Ok(())
92    }
93}
94
95#[derive(Serialize, Deserialize, Clone, Default)]
96pub struct WatchRegistry {
97    pub projects: Vec<WatchContext>,
98}
99
100pub async fn get_id_by_name(name: &str) -> Result<Option<String>> {
101    let watches = AppState::load_watches().await?;
102    Ok(watches
103        .projects
104        .iter()
105        .find(|p| p.repo.name == name)
106        .map(|p| p.id.clone()))
107}
108
109pub async fn get_name_by_id(id: &str) -> Result<Option<String>> {
110    let watches = AppState::load_watches().await?;
111    Ok(watches
112        .projects
113        .iter()
114        .find(|p| p.id == id)
115        .map(|p| p.repo.name.clone()))
116}
117
118// -----------------------
119// Utils functions
120// -----------------------
121
122fn get_watch_path() -> PathBuf {
123    let path = dirs::data_local_dir()
124        .unwrap_or_else(|| std::env::current_dir().expect("Failed to get current directory"));
125    path.join("fleetd").join("watches.json")
126}
127
128async fn save_watches(watches: &WatchRegistry) -> Result<()> {
129    let path = get_watch_path();
130    let json = serde_json::to_string_pretty(watches)?;
131    fs::write(path, json).await?;
132    Ok(())
133}