guild_cli/config/
workspace.rs1use std::path::{Path, PathBuf};
2
3use serde::Deserialize;
4
5use crate::error::ConfigError;
6
7#[derive(Debug, Deserialize)]
9struct WorkspaceToml {
10 workspace: WorkspaceSection,
11}
12
13#[derive(Debug, Deserialize)]
14struct WorkspaceSection {
15 name: String,
16 projects: Vec<String>,
17}
18
19#[derive(Debug, Clone)]
21pub struct WorkspaceConfig {
22 name: String,
24 project_patterns: Vec<String>,
26 root: PathBuf,
28}
29
30impl WorkspaceConfig {
31 pub fn from_file(path: &Path) -> Result<Self, ConfigError> {
33 let content = std::fs::read_to_string(path).map_err(|e| ConfigError::ReadFile {
34 path: path.to_path_buf(),
35 source: e,
36 })?;
37 let raw: WorkspaceToml = toml::from_str(&content).map_err(|e| ConfigError::ParseToml {
38 path: path.to_path_buf(),
39 source: e,
40 })?;
41 let root = path
42 .parent()
43 .expect("guild.toml must have a parent directory")
44 .to_path_buf();
45 Ok(Self {
46 name: raw.workspace.name,
47 project_patterns: raw.workspace.projects,
48 root,
49 })
50 }
51
52 pub fn from_str(content: &str, root: PathBuf) -> Result<Self, ConfigError> {
54 let raw: WorkspaceToml = toml::from_str(content).map_err(|e| ConfigError::ParseToml {
55 path: root.join("guild.toml"),
56 source: e,
57 })?;
58 Ok(Self {
59 name: raw.workspace.name,
60 project_patterns: raw.workspace.projects,
61 root,
62 })
63 }
64
65 pub fn name(&self) -> &str {
66 &self.name
67 }
68
69 pub fn project_patterns(&self) -> &[String] {
70 &self.project_patterns
71 }
72
73 pub fn root(&self) -> &Path {
74 &self.root
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn test_parse_workspace_config() {
84 let toml = r#"
85[workspace]
86name = "my-monorepo"
87projects = ["apps/*", "libs/*"]
88"#;
89 let config = WorkspaceConfig::from_str(toml, PathBuf::from("/tmp")).unwrap();
90 assert_eq!(config.name(), "my-monorepo");
91 assert_eq!(config.project_patterns(), &["apps/*", "libs/*"]);
92 assert_eq!(config.root(), Path::new("/tmp"));
93 }
94
95 #[test]
96 fn test_parse_workspace_missing_name() {
97 let toml = r#"
98[workspace]
99projects = ["apps/*"]
100"#;
101 assert!(WorkspaceConfig::from_str(toml, PathBuf::from("/tmp")).is_err());
102 }
103
104 #[test]
105 fn test_parse_workspace_missing_projects() {
106 let toml = r#"
107[workspace]
108name = "test"
109"#;
110 assert!(WorkspaceConfig::from_str(toml, PathBuf::from("/tmp")).is_err());
111 }
112}