archetect_core/config/
catalog.rs1use crate::source::{Source, SourceError};
2use std::fs;
3use std::path::{Path, PathBuf};
4
5pub const CATALOG_FILE_NAME: &str = "catalog.yml";
6
7#[derive(Debug, Serialize, Deserialize, Clone)]
8pub struct Catalog {
9 entries: Vec<CatalogEntry>,
10}
11
12impl Catalog {
13 pub fn new() -> Catalog {
14 Catalog { entries: vec![] }
15 }
16
17 pub fn load(source: Source) -> Result<Catalog, CatalogError> {
18 let catalog_path = match source {
20 Source::LocalFile { path } => path,
21 Source::RemoteHttp { url: _, path } => path,
22 Source::RemoteGit { url: _, path, gitref: _ } => path.join(CATALOG_FILE_NAME),
23 Source::LocalDirectory { path } => path.join(CATALOG_FILE_NAME),
24 };
25
26 if !catalog_path.exists() {
27 return Err(CatalogError::NotFound(catalog_path));
28 }
29
30 let catalog = fs::read_to_string(&catalog_path)?;
31 let catalog = serde_yaml::from_str(&catalog)?;
32 Ok(catalog)
33 }
34
35 pub fn save_to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), CatalogError> {
36 let yaml = serde_yaml::to_string(&self)?;
37 fs::write(path, &yaml)?;
38 Ok(())
39 }
40
41 pub fn entries(&self) -> &[CatalogEntry] {
42 self.entries.as_slice()
43 }
44
45 pub fn entries_owned(self) -> Vec<CatalogEntry> {
46 self.entries
47 }
48}
49
50#[derive(Debug, Serialize, Deserialize, Clone)]
51pub enum CatalogEntry {
52 #[serde(rename = "group")]
53 Group {
54 description: String,
55 entries: Vec<CatalogEntry>,
56 },
57 #[serde(rename = "catalog")]
58 Catalog { description: String, source: String },
59 #[serde(rename = "archetype")]
60 Archetype { description: String, source: String },
61}
62
63impl CatalogEntry {
64 pub fn description(&self) -> &str {
65 match self {
66 CatalogEntry::Group {
67 description,
68 entries: _,
69 } => description.as_str(),
70 CatalogEntry::Catalog { description, source: _ } => description.as_str(),
71 CatalogEntry::Archetype { description, source: _ } => description.as_str(),
72 }
73 }
74}
75
76#[derive(Debug, thiserror::Error)]
77pub enum CatalogError {
78 #[error("Catalog File is Empty")]
79 EmptyCatalog,
80 #[error("Selected Catalog Group is Empty")]
81 EmptyGroup,
82 #[error("Invalid Catalog Source: {0}")]
83 SourceError(SourceError),
84 #[error("Catalog not found: {0}")]
85 NotFound(PathBuf),
86 #[error("Catalog IO Error: {0}")]
87 IOError(std::io::Error),
88 #[error("Catalog Format Error: {0}")]
89 YamlError(serde_yaml::Error),
90}
91
92impl From<std::io::Error> for CatalogError {
93 fn from(e: std::io::Error) -> Self {
94 CatalogError::IOError(e)
95 }
96}
97
98impl From<serde_yaml::Error> for CatalogError {
99 fn from(e: serde_yaml::Error) -> Self {
100 CatalogError::YamlError(e)
101 }
102}
103
104impl From<SourceError> for CatalogError {
105 fn from(cause: SourceError) -> Self {
106 CatalogError::SourceError(cause)
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn test() {
116 let catalog = prototype_catalog();
117 let yaml = serde_yaml::to_string(&catalog).unwrap();
118 println!("{}", yaml);
119 }
120
121 #[test]
122 fn test_catalog_group() {
123 let group = lang_group();
124
125 let yaml = serde_yaml::to_string(&group).unwrap();
126 println!("{}", yaml);
127 }
128
129 fn prototype_catalog() -> Catalog {
130 Catalog {
131 entries: vec![
132 lang_group(),
133 CatalogEntry::Catalog {
134 description: "Java".to_owned(),
135 source: "~/projects/catalogs/java.yml".to_owned(),
136 },
137 ],
138 }
139 }
140
141 fn lang_group() -> CatalogEntry {
142 CatalogEntry::Group {
143 description: "Languages".to_owned(),
144 entries: vec![rust_group(), python_group()],
145 }
146 }
147
148 fn rust_group() -> CatalogEntry {
149 CatalogEntry::Group {
150 description: "Rust".to_owned(),
151 entries: vec![rust_cli_archetype(), rust_cli_workspace_archetype()],
152 }
153 }
154
155 fn rust_cli_archetype() -> CatalogEntry {
156 CatalogEntry::Archetype {
157 description: "Rust CLI".to_owned(),
158 source: "~/projects/test_archetypes/rust-cie".to_owned(),
159 }
160 }
161
162 fn rust_cli_workspace_archetype() -> CatalogEntry {
163 CatalogEntry::Archetype {
164 description: "Rust CLI Workspace".to_owned(),
165 source: "~/projects/test_archetypes/rust-cie".to_owned(),
166 }
167 }
168
169 fn python_group() -> CatalogEntry {
170 CatalogEntry::Group {
171 description: "Python".to_owned(),
172 entries: vec![CatalogEntry::Archetype {
173 description: "Python Service".to_owned(),
174 source: "~/projects/python/python-service".to_owned(),
175 }],
176 }
177 }
178}