Skip to main content

guild_cli/
error.rs

1use std::path::PathBuf;
2use thiserror::Error;
3
4/// Errors from parsing configuration values and domain types.
5#[derive(Debug, Clone, PartialEq, Eq, Error)]
6pub enum ParseError {
7    #[error("invalid project name '{value}': {reason}")]
8    ProjectName { value: String, reason: String },
9
10    #[error("invalid target name '{value}': {reason}")]
11    TargetName { value: String, reason: String },
12
13    #[error("invalid depends_on '{value}': {reason}")]
14    DependsOn { value: String, reason: String },
15}
16
17/// Errors from loading and processing configuration files.
18#[derive(Debug, Error)]
19pub enum ConfigError {
20    #[error(transparent)]
21    Parse(#[from] ParseError),
22
23    #[error("failed to read '{path}': {source}")]
24    ReadFile {
25        path: PathBuf,
26        source: std::io::Error,
27    },
28
29    #[error("failed to parse '{path}': {source}")]
30    ParseToml {
31        path: PathBuf,
32        source: toml::de::Error,
33    },
34
35    #[error("no guild.toml found in '{path}' or any parent directory")]
36    WorkspaceNotFound { path: PathBuf },
37}
38
39/// Errors from building and validating the project dependency graph.
40#[derive(Debug, Error)]
41pub enum GraphError {
42    #[error(transparent)]
43    Config(#[from] ConfigError),
44
45    #[error("cycle detected in project dependencies: {cycle}")]
46    CycleDetected { cycle: String },
47
48    #[error("unknown project '{name}' referenced in depends_on of '{referenced_by}'")]
49    UnknownProject { name: String, referenced_by: String },
50}
51
52/// Errors from building and validating the task dependency graph.
53#[derive(Debug, Clone, PartialEq, Eq, Error)]
54pub enum TaskGraphError {
55    #[error("cycle detected in task dependencies: {project}:{target}")]
56    CycleDetected { project: String, target: String },
57
58    #[error(
59        "unknown target '{target}' referenced in depends_on of '{project}:{referencing_target}'"
60    )]
61    UnknownTarget {
62        target: String,
63        project: String,
64        referencing_target: String,
65    },
66
67    #[error("unknown project '{project}' referenced in task graph")]
68    UnknownProject { project: String },
69
70    #[error("task '{project}:{target}' not found in graph")]
71    TaskNotFound { project: String, target: String },
72}
73
74/// Errors from running tasks.
75#[derive(Debug, Error)]
76pub enum RunnerError {
77    #[error("task graph error: {0}")]
78    TaskGraph(#[from] TaskGraphError),
79
80    #[error("failed to spawn command: {message}")]
81    SpawnFailed { message: String },
82
83    #[error("task '{project}:{target}' has no command configured")]
84    NoCommand { project: String, target: String },
85
86    #[error("invalid target '{target}': {reason}")]
87    InvalidTarget { target: String, reason: String },
88
89    #[error("workspace not found from '{path}': {reason}")]
90    WorkspaceNotFound { path: PathBuf, reason: String },
91
92    #[error("configuration error in '{path}': {reason}")]
93    ConfigError { path: PathBuf, reason: String },
94
95    #[error("graph error: {reason}")]
96    GraphError { reason: String },
97
98    #[error("project '{name}' not found in workspace")]
99    ProjectNotFound { name: String },
100}
101
102/// Errors from detecting affected projects.
103#[derive(Debug, Error)]
104pub enum AffectedError {
105    #[error("not a git repository: {path}")]
106    NotAGitRepo { path: PathBuf },
107
108    #[error("git error: {message}")]
109    Git { message: String },
110
111    #[error("base branch '{branch}' not found")]
112    BaseBranchNotFound { branch: String },
113
114    #[error("workspace not found from '{path}': {reason}")]
115    WorkspaceNotFound { path: PathBuf, reason: String },
116
117    #[error("configuration error in '{path}': {reason}")]
118    ConfigError { path: PathBuf, reason: String },
119
120    #[error("graph error: {reason}")]
121    GraphError { reason: String },
122
123    #[error("invalid target '{target}': {reason}")]
124    InvalidTarget { target: String, reason: String },
125}
126
127/// Errors from initializing a workspace with `guild init`.
128#[derive(Debug, Error)]
129pub enum InitError {
130    #[error("failed to read '{path}': {source}")]
131    ReadFile {
132        path: PathBuf,
133        source: std::io::Error,
134    },
135
136    #[error("failed to write '{path}': {source}")]
137    WriteFile {
138        path: PathBuf,
139        source: std::io::Error,
140    },
141
142    #[error("failed to parse JSON '{path}': {source}")]
143    ParseJson {
144        path: PathBuf,
145        source: serde_json::Error,
146    },
147
148    #[error("failed to parse TOML '{path}': {source}")]
149    ParseToml {
150        path: PathBuf,
151        source: toml::de::Error,
152    },
153
154    #[error("failed to walk directory '{path}': {source}")]
155    WalkDir {
156        path: PathBuf,
157        source: walkdir::Error,
158    },
159
160    #[error("invalid path: {path}")]
161    InvalidPath { path: PathBuf },
162
163    #[error("I/O error: {source}")]
164    Io { source: std::io::Error },
165}
166
167/// Errors from cache operations.
168#[derive(Debug, Error)]
169pub enum CacheError {
170    #[error("failed to read '{path}': {source}")]
171    ReadFile {
172        path: PathBuf,
173        source: std::io::Error,
174    },
175
176    #[error("failed to write '{path}': {source}")]
177    WriteFile {
178        path: PathBuf,
179        source: std::io::Error,
180    },
181
182    #[error("failed to remove '{path}': {source}")]
183    RemoveFile {
184        path: PathBuf,
185        source: std::io::Error,
186    },
187
188    #[error("failed to create directory '{path}': {source}")]
189    CreateDir {
190        path: PathBuf,
191        source: std::io::Error,
192    },
193
194    #[error("failed to read directory '{path}': {source}")]
195    ReadDir {
196        path: PathBuf,
197        source: std::io::Error,
198    },
199
200    #[error("invalid glob pattern '{pattern}': {source}")]
201    GlobPattern {
202        pattern: String,
203        source: glob::PatternError,
204    },
205
206    #[error("glob entry error: {source}")]
207    GlobEntry { source: glob::GlobError },
208
209    #[error("failed to serialize cache entry for '{task}': {source}")]
210    SerializeEntry {
211        task: String,
212        source: serde_json::Error,
213    },
214}