archetect_core/
requirements.rs1use crate::Archetect;
2use semver::{Version, VersionReq};
3use std::fs;
4use std::path::PathBuf;
5
6#[derive(Debug, Deserialize, Serialize)]
7pub struct Requirements {
8 #[serde(rename = "archetect")]
9 archetect_requirement: VersionReq,
10}
11
12impl Requirements {
13 pub fn new(archetect_version: VersionReq) -> Requirements {
14 Requirements {
15 archetect_requirement: archetect_version,
16 }
17 }
18
19 pub fn archetect_version(&self) -> &VersionReq {
20 &self.archetect_requirement
21 }
22
23 pub fn load<P: Into<PathBuf>>(path: P) -> Result<Option<Requirements>, RequirementsError> {
24 let mut path = path.into();
25 if path.is_dir() {
26 let candidates = vec!["requirements.yml", "requirements.yaml"];
27 for candidate in candidates {
28 let config_file = path.join(candidate);
29 if config_file.exists() {
30 path = config_file;
31 break;
32 }
33 }
34 }
35 if !path.exists() || path.is_dir() {
36 Ok(None)
37 } else {
38 let config = fs::read_to_string(&path)?;
39 match serde_yaml::from_str::<Requirements>(&config) {
40 Ok(result) => {
41 return Ok(Some(result));
42 }
43 Err(error) => {
44 return Err(RequirementsError::DeserializationError {
45 path: path,
46 cause: error,
47 });
48 }
49 }
50 }
51 }
52
53 pub fn verify(&self, archetect: &Archetect) -> Result<(), RequirementsError> {
54 if !self.archetect_requirement.matches(&archetect.version()) {
55 Err(RequirementsError::ArchetectVersion(
56 archetect.version().clone(),
57 self.archetect_requirement.clone(),
58 ))
59 } else {
60 Ok(())
61 }
62 }
63}
64
65#[derive(Debug, thiserror::Error)]
66pub enum RequirementsError {
67 #[error("Error Deserializing Requirements File `{path}`: {cause}")]
68 DeserializationError { path: PathBuf, cause: serde_yaml::Error },
69 #[error("Incompatible Archetect Version `{0}`. Requirements: {1}")]
70 ArchetectVersion(Version, VersionReq),
71 #[error("IO Error Reading Requirements File `{0}`.")]
72 IoError(std::io::Error),
73}
74
75impl From<std::io::Error> for RequirementsError {
76 fn from(error: std::io::Error) -> Self {
77 RequirementsError::IoError(error)
78 }
79}