blaze_common/
workspace.rs1use std::{
2 collections::{BTreeMap, BTreeSet},
3 path::{Path, PathBuf},
4};
5
6use serde::{de::Error, Deserialize, Serialize};
7
8use crate::{
9 configuration_file::ConfigurationFileFormat, settings::GlobalSettings, util::normalize_path,
10};
11
12#[derive(Debug, Serialize, Deserialize)]
14#[serde(rename_all = "camelCase")]
15pub struct Workspace {
16 root: PathBuf,
17 configuration_file_path: PathBuf,
18 configuration_file_format: ConfigurationFileFormat,
19 #[serde(flatten)]
20 configuration: WorkspaceConfiguration,
21}
22
23#[derive(Debug, Serialize)]
24pub struct ProjectRef {
25 path: PathBuf,
26 tags: BTreeSet<String>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 description: Option<String>,
29}
30
31impl ProjectRef {
32 pub fn path(&self) -> &Path {
33 &self.path
34 }
35
36 pub fn tags(&self) -> &BTreeSet<String> {
37 &self.tags
38 }
39
40 pub fn description(&self) -> Option<&str> {
41 self.description.as_deref()
42 }
43}
44
45impl From<PathBuf> for ProjectRef {
46 fn from(path: PathBuf) -> Self {
47 Self {
48 description: None,
49 tags: BTreeSet::new(),
50 path,
51 }
52 }
53}
54
55impl<'de> Deserialize<'de> for ProjectRef {
56 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
57 where
58 D: serde::Deserializer<'de>,
59 {
60 #[derive(Deserialize)]
61 #[serde(remote = "ProjectRef")]
62 struct ProjectRefAsObject {
63 path: PathBuf,
64 #[serde(default)]
65 tags: BTreeSet<String>,
66 description: Option<String>,
67 }
68
69 #[derive(Deserialize)]
70 #[serde(untagged)]
71 enum ProjectRefDeserializationModes {
72 SinglePath(PathBuf),
73 #[serde(with = "ProjectRefAsObject")]
74 Full(ProjectRef),
75 }
76
77 Ok(
78 match ProjectRefDeserializationModes::deserialize(deserializer)? {
79 ProjectRefDeserializationModes::SinglePath(path) => {
80 normalize_path(path).map_err(D::Error::custom)?.into()
81 }
82 ProjectRefDeserializationModes::Full(mut project_ref) => {
83 project_ref.path =
84 normalize_path(&project_ref.path).map_err(D::Error::custom)?;
85 project_ref
86 }
87 },
88 )
89 }
90}
91
92#[derive(Debug, Serialize, Deserialize)]
93pub struct WorkspaceConfiguration {
94 name: String,
95 #[serde(default)]
96 projects: BTreeMap<String, ProjectRef>,
97 #[serde(default)]
98 settings: GlobalSettings,
99}
100
101impl Workspace {
102 pub fn from_configuration_and_metadata<P: AsRef<Path>>(
104 source: (P, ConfigurationFileFormat),
105 configuration: WorkspaceConfiguration,
106 ) -> Self {
107 let mut root = source.0.as_ref().to_path_buf();
108 let _ = root.pop();
109
110 Self {
111 root,
112 configuration_file_path: source.0.as_ref().to_path_buf(),
113 configuration_file_format: source.1,
114 configuration,
115 }
116 }
117
118 pub fn root(&self) -> &Path {
119 &self.root
120 }
121
122 pub fn configuration_file_path(&self) -> &Path {
123 &self.configuration_file_path
124 }
125
126 pub fn configuration_file_format(&self) -> ConfigurationFileFormat {
127 self.configuration_file_format
128 }
129
130 pub fn name(&self) -> &str {
131 &self.configuration.name
132 }
133
134 pub fn projects(&self) -> &BTreeMap<String, ProjectRef> {
135 &self.configuration.projects
136 }
137
138 pub fn settings(&self) -> &GlobalSettings {
139 &self.configuration.settings
140 }
141}