Skip to main content

solar_core/
config.rs

1mod cargo_bin_basic;
2mod cargo_lib_basic;
3mod cargo_proc_basic;
4mod universal_default;
5
6pub use cargo_bin_basic::cargo_bin_basic;
7pub use cargo_lib_basic::cargo_lib_basic;
8pub use cargo_proc_basic::cargo_proc_basic;
9use derive_setters::Setters;
10pub use universal_default::universal_default;
11
12use std::{
13    fs,
14    io::Write,
15    path::{Path, PathBuf},
16};
17
18use derive_getters::Getters;
19use serde::{Deserialize, Serialize};
20
21use crate::{
22    SOLARCONFIGNAME, SolarError, ToolTrait,
23    tool::{CargoDeny, Commitalyzer, GithubWorkflows, Licenses, PreCommit, SemverRelease, Vhooks},
24};
25
26use clap::ValueEnum;
27
28#[derive(ValueEnum, Clone, Debug)]
29pub enum ProjConfig {
30    CargoBinBasic,
31    CargoLibBasic,
32    CargoProcBasic,
33    UniversalDefault,
34}
35
36impl ProjConfig {
37    pub fn get(&self) -> Config {
38        match self {
39            Self::CargoBinBasic => cargo_bin_basic(),
40            Self::CargoLibBasic => cargo_lib_basic(),
41            Self::CargoProcBasic => cargo_proc_basic(),
42            Self::UniversalDefault => universal_default(),
43        }
44    }
45}
46
47#[derive(Serialize, Deserialize, Debug, Getters, Setters)]
48pub struct Config {
49    #[serde(skip)]
50    #[setters(rename = "set_path")]
51    path: PathBuf,
52
53    #[setters(rename = "set_vhooks")]
54    vhooks: Option<Vhooks>,
55
56    #[setters(rename = "set_semver_release")]
57    semver_release: Option<SemverRelease>,
58
59    #[setters(rename = "set_pre_commit")]
60    pre_commit: Option<PreCommit>,
61
62    #[setters(rename = "set_licenses")]
63    licenses: Option<Licenses>,
64
65    #[setters(rename = "set_github_workflows")]
66    github_workflows: Option<GithubWorkflows>,
67
68    #[setters(rename = "set_commitalyzer")]
69    commitalyzer: Option<Commitalyzer>,
70
71    #[setters(rename = "set_cargo_deny")]
72    cargo_deny: Option<CargoDeny>,
73}
74
75impl ToolTrait for Config {
76    fn set_dest(&mut self, dest: &Path) {
77        self.on_all(|tool| tool.set_dest(dest));
78    }
79
80    fn act(&mut self, action: &crate::Action, dest: Option<&Path>) -> Result<(), SolarError> {
81        self.try_all(|tool| tool.act(action, dest))?;
82        Ok(())
83    }
84
85    fn install(&mut self) -> Result<(), SolarError> {
86        self.try_all(|tool| tool.install())?;
87        Ok(())
88    }
89
90    fn upgrade(&mut self) -> Result<(), SolarError> {
91        self.try_all(|tool| tool.upgrade())?;
92        Ok(())
93    }
94
95    fn uninstall(&mut self) -> Result<(), SolarError> {
96        self.try_all(|tool| tool.uninstall())?;
97        Ok(())
98    }
99}
100
101impl Config {
102    #[allow(clippy::too_many_arguments)]
103    pub fn new(
104        path: PathBuf,
105        vhooks: Option<Vhooks>,
106        semver_release: Option<SemverRelease>,
107        pre_commit: Option<PreCommit>,
108        licenses: Option<Licenses>,
109        github_workflows: Option<GithubWorkflows>,
110        commitalyzer: Option<Commitalyzer>,
111        cargo_deny: Option<CargoDeny>,
112    ) -> Self {
113        Self {
114            path,
115            vhooks,
116            semver_release,
117            pre_commit,
118            licenses,
119            github_workflows,
120            commitalyzer,
121            cargo_deny,
122        }
123    }
124
125    pub fn new_empty(dest: &Path) -> Self {
126        Self::new(dest.to_path_buf(), None, None, None, None, None, None, None)
127    }
128
129    pub fn on_all<F>(&mut self, mut f: F)
130    where
131        F: FnMut(&mut dyn ToolTrait),
132    {
133        if let Some(tool) = &mut self.vhooks {
134            f(tool);
135        }
136        if let Some(tool) = &mut self.semver_release {
137            f(tool);
138        }
139        if let Some(tool) = &mut self.pre_commit {
140            f(tool);
141        }
142        if let Some(tool) = &mut self.licenses {
143            f(tool);
144        }
145        if let Some(tool) = &mut self.github_workflows {
146            f(tool);
147        }
148        if let Some(tool) = &mut self.commitalyzer {
149            f(tool);
150        }
151        if let Some(tool) = &mut self.cargo_deny {
152            f(tool);
153        }
154    }
155
156    pub fn try_all<F>(&mut self, mut f: F) -> Result<(), SolarError>
157    where
158        F: FnMut(&mut dyn ToolTrait) -> Result<(), SolarError>,
159    {
160        if let Some(tool) = &mut self.vhooks {
161            f(tool)?;
162        }
163        if let Some(tool) = &mut self.semver_release {
164            f(tool)?;
165        }
166        if let Some(tool) = &mut self.pre_commit {
167            f(tool)?;
168        }
169        if let Some(tool) = &mut self.licenses {
170            f(tool)?;
171        }
172        if let Some(tool) = &mut self.github_workflows {
173            f(tool)?;
174        }
175        if let Some(tool) = &mut self.commitalyzer {
176            f(tool)?;
177        }
178        if let Some(tool) = &mut self.cargo_deny {
179            f(tool)?;
180        }
181        Ok(())
182    }
183
184    /// Creates a new Config from a file at the supplied path, provided the file contains
185    /// valid syntax for JSON and the config.
186    pub fn load_from_file(file_path: &Path) -> Result<Self, SolarError> {
187        let config_file = fs::read_to_string(file_path)?;
188        let config: Config = serde_json::from_str(&config_file)?;
189        Ok(config.set_path(file_path.to_path_buf()))
190    }
191
192    pub fn load_from(file_path: &Path) -> Result<Self, SolarError> {
193        Self::load_from_file(&file_path.join(SOLARCONFIGNAME))
194    }
195
196    pub fn load_or_default(file_path: &Path) -> Self {
197        Self::load_from(file_path).unwrap_or(Self::new_empty(&file_path.join(SOLARCONFIGNAME)))
198    }
199
200    pub fn save_to_file(&self, file_path: &Path) -> Result<(), SolarError> {
201        if !fs::exists(file_path)? {
202            fs::File::create(file_path)?;
203        }
204        let mut file = fs::File::options()
205            .write(true)
206            .truncate(true)
207            .open(file_path)?;
208        file.write_all(serde_json::to_string(self)?.as_bytes())?;
209        Ok(())
210    }
211
212    pub fn save_to(&self, file_path: &Path) -> Result<(), SolarError> {
213        self.save_to_file(&file_path.join(SOLARCONFIGNAME))
214    }
215
216    pub fn save(&self) -> Result<(), SolarError> {
217        self.save_to_file(&self.path)
218    }
219
220    pub fn is_empty(&self) -> bool {
221        self.vhooks.is_none()
222            && self.semver_release.is_none()
223            && self.pre_commit.is_none()
224            && self.licenses.is_none()
225            && self.github_workflows.is_none()
226            && self.commitalyzer.is_none()
227            && self.cargo_deny.is_none()
228    }
229}