1use 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#[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 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}