pitchfork_cli/
state_file.rs

1use crate::daemon::Daemon;
2use crate::{env, Result};
3use miette::IntoDiagnostic;
4use once_cell::sync::Lazy;
5use std::collections::{BTreeMap, BTreeSet};
6use std::fmt::Debug;
7use std::path::{Path, PathBuf};
8
9#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
10pub struct StateFile {
11    pub daemons: BTreeMap<String, Daemon>,
12    pub disabled: BTreeSet<String>,
13    pub shell_dirs: BTreeMap<String, PathBuf>,
14    #[serde(skip)]
15    pub(crate) path: PathBuf,
16}
17
18impl StateFile {
19    pub fn new(path: PathBuf) -> Self {
20        Self {
21            daemons: Default::default(),
22            disabled: Default::default(),
23            shell_dirs: Default::default(),
24            path,
25        }
26    }
27
28    pub fn get() -> &'static Self {
29        static STATE_FILE: Lazy<StateFile> = Lazy::new(|| {
30            let path = &*env::PITCHFORK_STATE_FILE;
31            StateFile::read(path).expect("Error reading state file")
32        });
33        &STATE_FILE
34    }
35
36    pub fn read<P: AsRef<Path>>(path: P) -> Result<Self> {
37        let path = path.as_ref();
38        if !path.exists() {
39            return Ok(Self::new(path.to_path_buf()));
40        }
41        let _lock = xx::fslock::get(path, false)?;
42        let raw = xx::file::read_to_string(path).unwrap_or_else(|e| {
43            warn!("Error reading state file {:?}: {}", path, e);
44            String::new()
45        });
46        let mut state_file: Self = toml::from_str(&raw).unwrap_or_else(|e| {
47            warn!("Error parsing state file {:?}: {}", path, e);
48            Self::new(path.to_path_buf())
49        });
50        state_file.path = path.to_path_buf();
51        for (name, daemon) in state_file.daemons.iter_mut() {
52            daemon.id = name.clone();
53        }
54        Ok(state_file)
55    }
56
57    pub fn write(&self) -> Result<()> {
58        let _lock = xx::fslock::get(&self.path, false)?;
59        let raw = toml::to_string(self).into_diagnostic()?;
60        xx::file::write(&self.path, raw)?;
61        Ok(())
62    }
63}