ct_tracker_lib/projects/
project_frame.rs

1use super::{errors, persistent, project_path, Project};
2
3use std::{
4    fs::OpenOptions,
5    io::Write,
6    ops::{Deref, DerefMut},
7    path::PathBuf,
8};
9
10// Some RAII sugar
11pub struct ProjectFrame {
12    project: Project,
13}
14
15impl Deref for ProjectFrame {
16    type Target = Project;
17
18    fn deref(&self) -> &Self::Target {
19        &self.project
20    }
21}
22
23impl DerefMut for ProjectFrame {
24    fn deref_mut(&mut self) -> &mut Self::Target {
25        &mut self.project
26    }
27}
28
29impl Drop for ProjectFrame {
30    fn drop(&mut self) {
31        // TODO v0.2.0 -> Dirty flag, to prevent the saving of an unchanged project
32        if let Err(e) = self.save() {
33            eprintln!("Error while saving! {:?}", e);
34        }
35    }
36}
37
38impl ProjectFrame {
39    pub fn load_or_create_from_name(name: &str) -> errors::CtResult<ProjectFrame> {
40        let path = project_path(name)?;
41        if path.exists() {
42            return ProjectFrame::load(&path);
43        }
44        let frame = ProjectFrame {
45            project: Project::create(name)?,
46        };
47        frame.save()?;
48        Ok(frame)
49    }
50
51    fn load_persistent_and_stop() -> errors::CtResult<()> {
52        if let Some(name) = persistent::has_project()? {
53            let path = project_path(name.as_str())?;
54            // has_project makes sure that the peoject returned exists, so we can simply unwrap
55            let mut proj = ProjectFrame::load(&path)?;
56            // Should also deregister from store -> project.stop() doesn't do that
57            proj.stop()?;
58        }
59        Ok(())
60    }
61
62    pub fn load_from_name(name: &str) -> errors::CtResult<ProjectFrame> {
63        let path = project_path(name)?;
64        ProjectFrame::load(&path)
65    }
66
67    pub(crate) fn load(path: &PathBuf) -> errors::CtResult<ProjectFrame> {
68        if path.exists() {
69            assert!(path.is_file());
70            // Project already exists: Try to load it and return a new frame
71            let json = std::fs::read_to_string(&path)?;
72
73            Ok(ProjectFrame {
74                project: Project::from_json(json.as_str())?,
75            })
76        } else {
77            Err(errors::CtError::Own("Project does not exist!"))
78        }
79    }
80
81    fn save(&self) -> errors::CtResult<()> {
82        let file = project_path(self.name())?;
83        let mut file = OpenOptions::new()
84            .create(true)
85            .write(true)
86            .truncate(true)
87            .open(&file)?;
88        file.write_all(self.project.json(true)?.as_bytes())?;
89        Ok(())
90    }
91
92    pub fn start(&mut self) -> errors::CtResult<()> {
93        ProjectFrame::load_persistent_and_stop()?;
94        self.project.start();
95        persistent::register(self.project.name().as_str())?;
96        Ok(())
97    }
98
99    pub fn stop(&mut self) -> errors::CtResult<()> {
100        // Maybe assert that this project is the running one
101        persistent::deregister(Some(self.project.name().as_str()))?;
102        self.project.stop();
103        Ok(())
104    }
105}