Skip to main content

dxm_init/
vcs.rs

1//! Contains code for initializing VCS repositories and files.
2
3use std::{error::Error, fmt::Display, path::Path, str::FromStr};
4
5use dxm_manifest::Manifest;
6use git2::Repository;
7
8const GITIGNORE_NAME: &str = ".gitignore";
9
10const ROOT_GITIGNORE: &str = "\
11# FXServer
12/artifact/
13
14# txAdmin
15/txData/
16";
17
18const DATA_GITIGNORE: &str = "\
19# Cache
20/cache/
21
22# KVP
23/db/
24
25# Miscellaneous
26/.replxx_history
27/imgui.ini
28";
29
30/// The possible version control systems to use in servers.
31#[derive(Default, Debug, PartialEq, Eq, Clone)]
32pub enum VcsOption {
33    #[default]
34    None,
35    Git,
36}
37
38#[derive(Debug)]
39pub struct ParseVcsOptionError {
40    option: String,
41}
42
43impl Display for ParseVcsOptionError {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        write!(f, "unknown vsc option {}", &self.option)?;
46
47        Ok(())
48    }
49}
50
51impl Error for ParseVcsOptionError {}
52
53impl FromStr for VcsOption {
54    type Err = ParseVcsOptionError;
55
56    fn from_str(option: &str) -> Result<Self, Self::Err> {
57        match option {
58            "none" => Ok(Self::None),
59            "git" => Ok(Self::Git),
60            _ => Err(ParseVcsOptionError {
61                option: option.to_owned(),
62            }),
63        }
64    }
65}
66
67impl VcsOption {
68    /// Initialize the VCS repository and files.
69    pub fn init<P>(&self, path: P, manifest: &Manifest) -> Result<(), Box<dyn Error>>
70    where
71        P: AsRef<Path>,
72    {
73        let path = path.as_ref();
74        let data_path = manifest.server.data(path);
75
76        match self {
77            VcsOption::None => Ok(()),
78            VcsOption::Git => {
79                Repository::init(path)?;
80
81                fs_err::write(path.join(GITIGNORE_NAME), ROOT_GITIGNORE)?;
82                fs_err::write(data_path.join(GITIGNORE_NAME), DATA_GITIGNORE)?;
83
84                Ok(())
85            }
86        }
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn parses_returns_value_when_valid() {
96        assert_eq!(VcsOption::from_str("none").unwrap(), VcsOption::None);
97    }
98
99    #[test]
100    #[should_panic]
101    fn parse_returns_error_when_invalid() {
102        VcsOption::from_str("").unwrap();
103    }
104}